blob: 08f488d16b7dc12d44942d09a7ffa04d1079ab9f [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();
91
92 while (byteBuffer.remaining() >= DEFAULT_LEN) {
93 byte subOptCode = byteBuffer.get();
94 byte subOptLen = byteBuffer.get();
Yi Tsengb4fdb042017-08-07 13:32:32 -070095 int subOptLenInt = UNSIGNED_BYTE_MASK & subOptLen;
96 byte[] subOptData = new byte[subOptLenInt];
Yi Tsengc7403c22017-06-19 16:23:22 -070097 byteBuffer.get(subOptData);
98
99 DhcpOption subOption = new DhcpOption();
100 subOption.code = subOptCode;
101 subOption.length = subOptLen;
102 subOption.data = subOptData;
103 relayOption.subOptions.put(subOptCode, subOption);
104 }
105
106 return relayOption;
107 };
108 }
109
110 /**
111 * Gets sub-option from this option by given option code.
112 *
113 * @param code the option code
114 * @return sub-option of given code; null if there is no sub-option for given
115 * code
116 */
117 public DhcpOption getSubOption(byte code) {
118 return subOptions.get(code);
119 }
120
121 /**
122 * Adds a sub-option for this option.
123 *
124 * @param subOption the sub-option
125 */
126 public void addSubOption(DhcpOption subOption) {
127 this.length += SUB_OPT_DEFAULT_LEN + subOption.length;
128 this.subOptions.put(subOption.getCode(), subOption);
129 }
130
131 /**
132 * Removes a sub-option by given sub-option code.
133 *
134 * @param code the code for sub-option
135 * @return sub-option removed; null of sub-option not exists
136 */
137 public DhcpOption removeSubOption(byte code) {
138 DhcpOption subOption = subOptions.remove(code);
139 if (subOption != null) {
140 this.length -= SUB_OPT_DEFAULT_LEN + subOption.length;
141 }
142 return subOption;
143 }
144
145 @Override
146 public boolean equals(Object obj) {
147 if (!super.equals(obj)) {
148 return false;
149 }
150 if (!(obj instanceof DhcpRelayAgentOption)) {
151 return false;
152 }
153 DhcpRelayAgentOption that = (DhcpRelayAgentOption) obj;
154 return Objects.equals(this.subOptions, that.subOptions);
155 }
156
157 @Override
158 public int hashCode() {
159 return Objects.hash(super.hashCode(), subOptions);
160 }
161}