blob: e5eb21145f6f79aa3bfc5369364a310a32fedc91 [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();
122 byte[] subOptData = new byte[Dhcp6Option.DEFAULT_LEN + len];
123 bb.get(subOptData);
124
125 // TODO: put more sub-options?
126 if (code == DHCP6.OptionCode.IAADDR.value()) {
127 option = Dhcp6IaAddressOption.deserializer()
128 .deserialize(subOptData, 0, subOptData.length);
129 } else {
130 option = Dhcp6Option.deserializer()
131 .deserialize(subOptData, 0, subOptData.length);
132 }
133 iaTaOption.options.add(option);
134 }
135 return iaTaOption;
136 };
137 }
138
139 @Override
140 public byte[] serialize() {
141 int payloadLen = DEFAULT_LEN + options.stream()
142 .mapToInt(opt -> (int) opt.getLength())
143 .sum();
144 int len = Dhcp6Option.DEFAULT_LEN + payloadLen;
145 ByteBuffer bb = ByteBuffer.allocate(len);
146 bb.putShort(DHCP6.OptionCode.IA_TA.value());
147 bb.putShort((short) payloadLen);
148 bb.putInt(iaId);
149 options.stream().map(Dhcp6Option::serialize).forEach(bb::put);
150 return bb.array();
151 }
152
153 @Override
154 public int hashCode() {
155 return 31 * super.hashCode() + Objects.hash(iaId, options);
156 }
157
158 @Override
159 public boolean equals(Object obj) {
160 if (this == obj) {
161 return true;
162 }
163 if (obj == null || getClass() != obj.getClass()) {
164 return false;
165 }
166 final Dhcp6IaTaOption other = (Dhcp6IaTaOption) obj;
167 return Objects.equals(this.iaId, other.iaId)
168 && Objects.equals(this.options, other.options);
169 }
170
171 @Override
172 public String toString() {
173 return getToStringHelper()
174 .add("iaId", iaId)
175 .add("options", options)
176 .toString();
177 }
178}