blob: b3c073fdcab8b0d77712860bee0afcd8a843a942 [file] [log] [blame]
Yi Tsengc7403c22017-06-19 16:23:22 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
Yi Tsengc7403c22017-06-19 16:23:22 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.onlab.packet.dhcp;
18
19import com.google.common.collect.Maps;
Yi Tsengc7403c22017-06-19 16:23:22 -070020import org.onlab.packet.Deserializer;
Yi Tsengc7403c22017-06-19 16:23:22 -070021import org.slf4j.Logger;
22
23import java.nio.ByteBuffer;
24import java.util.Map;
25import java.util.Objects;
26
27import static org.slf4j.LoggerFactory.getLogger;
28
29/**
30 * Representation of DHCP relay agent option (option 82).
31 */
32public class DhcpRelayAgentOption extends DhcpOption {
33 private static final int SUB_OPT_DEFAULT_LEN = 2;
34 private final Logger log = getLogger(getClass());
35 private final Map<Byte, DhcpOption> subOptions = Maps.newHashMap();
36
37 // Sub-option codes for option 82
38 public enum RelayAgentInfoOptions {
39 CIRCUIT_ID((byte) 1),
40 REMOTE_ID((byte) 2),
41 DOCSIS((byte) 4),
42 LINK_SELECTION((byte) 5),
43 SUBSCRIBER_ID((byte) 6),
44 RADIUS((byte) 7),
45 AUTH((byte) 8),
46 VENDOR_SPECIFIC((byte) 9),
47 RELAY_AGENT_FLAGS((byte) 10),
48 SERVER_ID_OVERRIDE((byte) 11),
49 VIRTUAL_SUBNET_SELECTION((byte) 151),
50 VIRTUAL_SUBNET_SELECTION_CTRL((byte) 152);
51
52 private byte value;
53 public byte getValue() {
54 return value;
55 }
56 RelayAgentInfoOptions(byte value) {
57 this.value = value;
58 }
59 }
60
61 @Override
62 public byte[] serialize() {
63 int totalLen = 0;
64 totalLen += subOptions.size() * SUB_OPT_DEFAULT_LEN;
65 totalLen += subOptions.values().stream().mapToInt(DhcpOption::getLength).sum();
66 totalLen += DEFAULT_LEN;
67 ByteBuffer byteBuffer = ByteBuffer.allocate(totalLen);
68 byteBuffer.put(code);
69 byteBuffer.put(length);
70 subOptions.values().forEach(subOpt -> {
71 byteBuffer.put(subOpt.code);
72 byteBuffer.put(subOpt.length);
73 byteBuffer.put(subOpt.data);
74 });
75 return byteBuffer.array();
76 }
77
Ray Milkeyf0c47612017-09-28 11:29:38 -070078
Yi Tsengc7403c22017-06-19 16:23:22 -070079
80 /**
81 * Deserializer function for DHCP relay agent option.
82 *
83 * @return deserializer function
84 */
85 public static Deserializer<DhcpOption> deserializer() {
86 return (data, offset, length) -> {
87 DhcpRelayAgentOption relayOption = new DhcpRelayAgentOption();
88 ByteBuffer byteBuffer = ByteBuffer.wrap(data, offset, length);
89 relayOption.code = byteBuffer.get();
90 relayOption.length = byteBuffer.get();
Saurav Das9e5d47f2020-10-10 19:12:51 -070091 relayOption.data = data;
Yi Tsengc7403c22017-06-19 16:23:22 -070092
93 while (byteBuffer.remaining() >= DEFAULT_LEN) {
94 byte subOptCode = byteBuffer.get();
95 byte subOptLen = byteBuffer.get();
Yi Tsengb4fdb042017-08-07 13:32:32 -070096 int subOptLenInt = UNSIGNED_BYTE_MASK & subOptLen;
97 byte[] subOptData = new byte[subOptLenInt];
Yi Tsengc7403c22017-06-19 16:23:22 -070098 byteBuffer.get(subOptData);
99
100 DhcpOption subOption = new DhcpOption();
101 subOption.code = subOptCode;
102 subOption.length = subOptLen;
103 subOption.data = subOptData;
104 relayOption.subOptions.put(subOptCode, subOption);
105 }
106
107 return relayOption;
108 };
109 }
110
111 /**
112 * Gets sub-option from this option by given option code.
113 *
114 * @param code the option code
115 * @return sub-option of given code; null if there is no sub-option for given
116 * code
117 */
118 public DhcpOption getSubOption(byte code) {
119 return subOptions.get(code);
120 }
121
122 /**
123 * Adds a sub-option for this option.
124 *
125 * @param subOption the sub-option
126 */
127 public void addSubOption(DhcpOption subOption) {
128 this.length += SUB_OPT_DEFAULT_LEN + subOption.length;
129 this.subOptions.put(subOption.getCode(), subOption);
130 }
131
132 /**
133 * Removes a sub-option by given sub-option code.
134 *
135 * @param code the code for sub-option
136 * @return sub-option removed; null of sub-option not exists
137 */
138 public DhcpOption removeSubOption(byte code) {
139 DhcpOption subOption = subOptions.remove(code);
140 if (subOption != null) {
141 this.length -= SUB_OPT_DEFAULT_LEN + subOption.length;
142 }
143 return subOption;
144 }
145
146 @Override
147 public boolean equals(Object obj) {
148 if (!super.equals(obj)) {
149 return false;
150 }
151 if (!(obj instanceof DhcpRelayAgentOption)) {
152 return false;
153 }
154 DhcpRelayAgentOption that = (DhcpRelayAgentOption) obj;
155 return Objects.equals(this.subOptions, that.subOptions);
156 }
157
158 @Override
159 public int hashCode() {
160 return Objects.hash(super.hashCode(), subOptions);
161 }
162}