blob: e76f0553f05fc6a81ca45c0f2b160590c72bdb06 [file] [log] [blame]
Kalhee Kim45fede42017-09-05 19:05:06 +00001/*
2 * Copyright 2017-present Open Networking Foundation
3 *
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.Lists;
20import org.onlab.packet.DHCP6;
21import org.onlab.packet.DeserializationException;
22import org.onlab.packet.Deserializer;
23
24import java.nio.ByteBuffer;
25import java.util.List;
26import java.util.Objects;
27
28/**
29 * DHCPv6 Identity Association for Prefix Delegation Option.
30 * Based on RFC-3633
31 */
32public final class Dhcp6IaPdOption extends Dhcp6Option {
33 public static final int DEFAULT_LEN = 12;
34 private int iaId;
35 private int t1;
36 private int t2;
37 private List<Dhcp6Option> options;
38
39 @Override
40 public short getCode() {
41 return DHCP6.OptionCode.IA_PD.value();
42 }
43
44 @Override
45 public short getLength() {
46 return (short) (DEFAULT_LEN + options.stream()
47 .mapToInt(opt -> (int) opt.getLength() + Dhcp6Option.DEFAULT_LEN)
48 .sum());
49
50 }
51
52 /**
53 * Gets Identity Association ID.
54 * The unique identifier for this IA_PD; the IAID must
55 * be unique among the identifiers for all of this
56 * requesting router's IA_PDs.
57 *
58 * @return the Identity Association ID
59 */
60 public int getIaId() {
61 return iaId;
62 }
63
64 /**
65 * Sets Identity Association ID.
66 *
67 * @param iaId the Identity Association ID.
68 */
69 public void setIaId(int iaId) {
70 this.iaId = iaId;
71 }
72
73 /**
74 * Gets time 1.
75 * The time at which the requesting router should
76 * contact the delegating router from which the
77 * prefixes in the IA_PD were obtained to extend the
78 * lifetimes of the prefixes delegated to the IA_PD;
79 * T1 is a time duration relative to the current time
80 * expressed in units of seconds.
81 *
82 * @return the value of time 1
83 */
84 public int getT1() {
85 return t1;
86 }
87
88 /**
89 * Sets time 1.
90 *
91 * @param t1 the value of time 1
92 */
93 public void setT1(int t1) {
94 this.t1 = t1;
95 }
96
97 /**
98 * Gets time 2.
99 * The time at which the requesting router should
100 * contact any available delegating router to extend
101 * the lifetimes of the prefixes assigned to the
102 * IA_PD; T2 is a time duration relative to the
103 * current time expressed in units of seconds.
104 *
105 * @return the value of time 2
106 */
107 public int getT2() {
108 return t2;
109 }
110
111 /**
112 * Sets time 2.
113 *
114 * @param t2 the value of time 2
115 */
116 public void setT2(int t2) {
117 this.t2 = t2;
118 }
119
120 /**
121 * Gets sub-options.
122 *
123 * @return sub-options of this option
124 */
125 public List<Dhcp6Option> getOptions() {
126 return options;
127 }
128
129 /**
130 * Sets sub-options.
131 *
132 * @param options the sub-options of this option
133 */
134 public void setOptions(List<Dhcp6Option> options) {
135 this.options = options;
136 }
137
138 /**
139 * Default constructor.
140 */
141 public Dhcp6IaPdOption() {
142 }
143
144 /**
145 * Constructs a DHCPv6 IA PD option with DHCPv6 option.
146 *
147 * @param dhcp6Option the DHCPv6 option
148 */
149 public Dhcp6IaPdOption(Dhcp6Option dhcp6Option) {
150 super(dhcp6Option);
151 }
152
153 /**
154 * Gets deserializer.
155 *
156 * @return the deserializer
157 */
158 public static Deserializer<Dhcp6Option> deserializer() {
159 return (data, offset, length) -> {
160 Dhcp6Option dhcp6Option =
161 Dhcp6Option.deserializer().deserialize(data, offset, length);
162 if (dhcp6Option.getLength() < DEFAULT_LEN) {
163 throw new DeserializationException("Invalid IA PD option data");
164 }
165 Dhcp6IaPdOption iaPdOption = new Dhcp6IaPdOption(dhcp6Option);
166 byte[] optionData = iaPdOption.getData();
167 ByteBuffer bb = ByteBuffer.wrap(optionData);
168 iaPdOption.iaId = bb.getInt();
169 iaPdOption.t1 = bb.getInt();
170 iaPdOption.t2 = bb.getInt();
171
172 iaPdOption.options = Lists.newArrayList();
173 while (bb.remaining() >= Dhcp6Option.DEFAULT_LEN) {
174 Dhcp6Option option;
175 ByteBuffer optByteBuffer = ByteBuffer.wrap(optionData,
176 bb.position(),
177 optionData.length - bb.position());
178 short code = optByteBuffer.getShort();
179 short len = optByteBuffer.getShort();
180 int optLen = UNSIGNED_SHORT_MASK & len;
181 byte[] subOptData = new byte[Dhcp6Option.DEFAULT_LEN + optLen];
182 bb.get(subOptData);
183
184 // TODO: put more sub-options?
185 if (code == DHCP6.OptionCode.IAPREFIX.value()) {
186 option = Dhcp6IaPrefixOption.deserializer()
187 .deserialize(subOptData, 0, subOptData.length);
188 } else {
189 option = Dhcp6Option.deserializer()
190 .deserialize(subOptData, 0, subOptData.length);
191 }
192 iaPdOption.options.add(option);
193 }
194 return iaPdOption;
195 };
196 }
197
198 @Override
199 public byte[] serialize() {
200 int payloadLen = DEFAULT_LEN + options.stream()
201 .mapToInt(opt -> (int) opt.getLength() + Dhcp6Option.DEFAULT_LEN)
202 .sum();
203 int len = Dhcp6Option.DEFAULT_LEN + payloadLen;
204 ByteBuffer bb = ByteBuffer.allocate(len);
205 bb.putShort(DHCP6.OptionCode.IA_PD.value());
206 bb.putShort((short) payloadLen);
207 bb.putInt(iaId);
208 bb.putInt(t1);
209 bb.putInt(t2);
210
211 options.stream().map(Dhcp6Option::serialize).forEach(bb::put);
212 return bb.array();
213 }
214
215 @Override
216 public int hashCode() {
217 return 31 * super.hashCode() + Objects.hash(iaId, t1, t2, options);
218 }
219
220 @Override
221 public boolean equals(Object obj) {
222 if (this == obj) {
223 return true;
224 }
225 if (obj == null || getClass() != obj.getClass()) {
226 return false;
227 }
228 if (!super.equals(obj)) {
229 return false;
230 }
231 final Dhcp6IaPdOption other = (Dhcp6IaPdOption) obj;
232 return Objects.equals(this.iaId, other.iaId)
233 && Objects.equals(this.t1, other.t1)
234 && Objects.equals(this.t2, other.t2)
235 && Objects.equals(this.options, other.options);
236 }
237
238 @Override
239 public String toString() {
240 return getToStringHelper()
241 .add("iaId", iaId)
242 .add("t1", t1)
243 .add("t2", t2)
244 .add("options", options)
245 .toString();
246 }
247}