blob: e8fdba6f605e0b4d60fb6396214f8ebe47dec361 [file] [log] [blame]
Yi Tsengca34e1d2017-07-18 16:16:25 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
Yi Tsengca34e1d2017-07-18 16:16:25 -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 */
17
18package org.onlab.packet.dhcp;
19
20import com.google.common.collect.Lists;
21import org.onlab.packet.DHCP6;
22import org.onlab.packet.DeserializationException;
23import org.onlab.packet.Deserializer;
24
25import java.nio.ByteBuffer;
26import java.util.List;
27import java.util.Objects;
28
29public final class Dhcp6IaTaOption extends Dhcp6Option {
30 public static final int DEFAULT_LEN = 4;
31 private int iaId;
32 private List<Dhcp6Option> options;
33
34 @Override
35 public short getCode() {
36 return DHCP6.OptionCode.IA_TA.value();
37 }
38
39 @Override
40 public short getLength() {
41 return (short) (DEFAULT_LEN + options.stream()
42 .mapToInt(opt -> (int) opt.getLength() + Dhcp6Option.DEFAULT_LEN)
43 .sum());
44 }
45
46 /**
47 * Gets Identity Association ID.
48 *
49 * @return the Identity Association ID
50 */
51 public int getIaId() {
52 return iaId;
53 }
54
55 /**
56 * Sets Identity Association ID.
57 *
58 * @param iaId the Identity Association ID.
59 */
60 public void setIaId(int iaId) {
61 this.iaId = iaId;
62 }
63
64 /**
65 * Gets sub-options.
66 *
67 * @return sub-options of this option
68 */
69 public List<Dhcp6Option> getOptions() {
70 return options;
71 }
72
73 /**
74 * Sets sub-options.
75 *
76 * @param options the sub-options of this option
77 */
78 public void setOptions(List<Dhcp6Option> options) {
79 this.options = options;
80 }
81
82 /**
83 * Default constructor.
84 */
85 public Dhcp6IaTaOption() {
86 }
87
88 /**
89 * Constructs a DHCPv6 IA TA option with DHCPv6 option.
90 *
91 * @param dhcp6Option the DHCPv6 option
92 */
93 public Dhcp6IaTaOption(Dhcp6Option dhcp6Option) {
94 super(dhcp6Option);
95 }
96
97 /**
98 * Gets deserializer.
99 *
100 * @return the deserializer
101 */
102 public static Deserializer<Dhcp6Option> deserializer() {
103 return (data, offset, length) -> {
104 Dhcp6Option dhcp6Option =
105 Dhcp6Option.deserializer().deserialize(data, offset, length);
106 if (dhcp6Option.getLength() < DEFAULT_LEN) {
107 throw new DeserializationException("Invalid IA NA option data");
108 }
109 Dhcp6IaTaOption iaTaOption = new Dhcp6IaTaOption(dhcp6Option);
110 byte[] optionData = iaTaOption.getData();
111 ByteBuffer bb = ByteBuffer.wrap(optionData);
112 iaTaOption.iaId = bb.getInt();
113
114 iaTaOption.options = Lists.newArrayList();
115 while (bb.remaining() >= Dhcp6Option.DEFAULT_LEN) {
116 Dhcp6Option option;
117 ByteBuffer optByteBuffer = ByteBuffer.wrap(optionData,
118 bb.position(),
119 optionData.length - bb.position());
120 short code = optByteBuffer.getShort();
121 short len = optByteBuffer.getShort();
Yi Tsengb4fdb042017-08-07 13:32:32 -0700122 int optLen = UNSIGNED_SHORT_MASK & len;
123 byte[] subOptData = new byte[Dhcp6Option.DEFAULT_LEN + optLen];
Yi Tsengca34e1d2017-07-18 16:16:25 -0700124 bb.get(subOptData);
125
126 // TODO: put more sub-options?
127 if (code == DHCP6.OptionCode.IAADDR.value()) {
128 option = Dhcp6IaAddressOption.deserializer()
129 .deserialize(subOptData, 0, subOptData.length);
130 } else {
131 option = Dhcp6Option.deserializer()
132 .deserialize(subOptData, 0, subOptData.length);
133 }
134 iaTaOption.options.add(option);
135 }
136 return iaTaOption;
137 };
138 }
139
140 @Override
141 public byte[] serialize() {
142 int payloadLen = DEFAULT_LEN + options.stream()
143 .mapToInt(opt -> (int) opt.getLength())
144 .sum();
145 int len = Dhcp6Option.DEFAULT_LEN + payloadLen;
146 ByteBuffer bb = ByteBuffer.allocate(len);
147 bb.putShort(DHCP6.OptionCode.IA_TA.value());
148 bb.putShort((short) payloadLen);
149 bb.putInt(iaId);
150 options.stream().map(Dhcp6Option::serialize).forEach(bb::put);
151 return bb.array();
152 }
153
154 @Override
155 public int hashCode() {
156 return 31 * super.hashCode() + Objects.hash(iaId, options);
157 }
158
159 @Override
160 public boolean equals(Object obj) {
161 if (this == obj) {
162 return true;
163 }
164 if (obj == null || getClass() != obj.getClass()) {
165 return false;
166 }
167 final Dhcp6IaTaOption other = (Dhcp6IaTaOption) obj;
168 return Objects.equals(this.iaId, other.iaId)
169 && Objects.equals(this.options, other.options);
170 }
171
172 @Override
173 public String toString() {
174 return getToStringHelper()
175 .add("iaId", iaId)
176 .add("options", options)
177 .toString();
178 }
179}