blob: 01b4cc3bc9bd9383180c373cd5e4cc1148ed612f [file] [log] [blame]
Lior Assoulinea21c0ca2018-01-28 16:18:48 -08001/*
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 */
17
18package org.onlab.packet.dhcp;
19
20import com.google.common.base.MoreObjects;
21import com.google.common.collect.Lists;
22import org.onlab.packet.DHCP6;
23import org.onlab.packet.DeserializationException;
24import org.onlab.packet.Deserializer;
25import org.onlab.packet.Ip6Address;
26
27import java.nio.ByteBuffer;
28import java.util.List;
29import java.util.Objects;
30
31/**
32 * DHCPv6 Client Data Option.
33 */
34public final class Dhcp6ClientDataOption extends Dhcp6Option {
35 private List<Dhcp6Option> options;
36 private Ip6Address clientIaAddress;
37 public static final int DEFAULT_LEN = 1 + 16;
38
39 public Dhcp6ClientDataOption(Dhcp6Option dhcp6Option) {
40 super(dhcp6Option);
41 }
42
43 @Override
44 public short getCode() {
45 return DHCP6.OptionCode.CLIENT_DATA.value();
46 }
47
48 @Override
49 public short getLength() {
50 //return (short) (DEFAULT_LEN + options.stream()
51 // .mapToInt(opt -> (int) opt.getLength() + Dhcp6Option.DEFAULT_LEN)
52 // .sum());
53 return (short) payload.serialize().length;
54 }
55
56 @Override
57 public byte[] getData() {
58 return payload.serialize();
59 }
60
61 public List<Dhcp6Option> getOptions() {
62 return options;
63 }
64
65 public Ip6Address getIaAddress() {
66 return clientIaAddress;
67 }
68
69 public static Deserializer<Dhcp6Option> deserializer() {
70 return (data, offset, length) -> {
71 Dhcp6Option dhcp6Option = Dhcp6Option.deserializer().deserialize(data, offset, length);
72 Dhcp6ClientDataOption clientData = new Dhcp6ClientDataOption(dhcp6Option);
73
74 if (dhcp6Option.getLength() < DEFAULT_LEN) {
75 throw new DeserializationException("Invalid length of Client Id option");
76 }
77
78 byte[] optionData = clientData.getData();
79
80 clientData.options = Lists.newArrayList();
81
82 ByteBuffer bb = ByteBuffer.wrap(optionData);
83
84 while (bb.remaining() >= Dhcp6Option.DEFAULT_LEN) {
85 Dhcp6Option option;
86 ByteBuffer optByteBuffer = ByteBuffer.wrap(optionData,
87 bb.position(),
88 optionData.length - bb.position());
89 short code = optByteBuffer.getShort();
90 short len = optByteBuffer.getShort();
91 int optLen = UNSIGNED_SHORT_MASK & len;
92 byte[] subOptData = new byte[Dhcp6Option.DEFAULT_LEN + optLen];
93 bb.get(subOptData);
94
95 // TODO: put more sub-options?
96 if (code == DHCP6.OptionCode.IAADDR.value()) {
97 option = Dhcp6IaAddressOption.deserializer()
98 .deserialize(subOptData, 0, subOptData.length);
99 clientData.clientIaAddress = ((Dhcp6IaAddressOption) option).getIp6Address();
100 } else if (code == DHCP6.OptionCode.CLIENTID.value()) {
101 option = Dhcp6ClientIdOption.deserializer()
102 .deserialize(subOptData, 0, subOptData.length);
103 } else if (code == DHCP6.OptionCode.CLIENT_LT.value()) {
104 option = Dhcp6CLTOption.deserializer()
105 .deserialize(subOptData, 0, subOptData.length);
106 } else {
107 option = Dhcp6Option.deserializer()
108 .deserialize(subOptData, 0, subOptData.length);
109 }
110 clientData.options.add(option);
111 }
112 return clientData;
113 };
114 }
115
116 @Override
117 public byte[] serialize() {
118 ByteBuffer bb = ByteBuffer.allocate(this.getLength() + Dhcp6Option.DEFAULT_LEN);
119 bb.putShort(getCode());
120 bb.putShort(getLength());
121 bb.put(payload.serialize());
122 return bb.array();
123 }
124
125
126 @Override
127 public String toString() {
128 return MoreObjects.toStringHelper(getClass())
129 .add("code", getCode())
130 .add("length", getLength())
131 .add("clientAddr", getIaAddress())
132 .toString();
133 }
134
135 @Override
136 public int hashCode() {
137 return Objects.hash(super.hashCode(), clientIaAddress, options);
138 }
139
140 @Override
141 public boolean equals(Object obj) {
142 if (this == obj) {
143 return true;
144 }
145 if (obj == null) {
146 return false;
147 }
148 if (!(obj instanceof Dhcp6ClientDataOption)) {
149 return false;
150 }
151 if (!super.equals(obj)) {
152 return false;
153 }
154 final Dhcp6ClientDataOption other = (Dhcp6ClientDataOption) obj;
155
156 return Objects.equals(getCode(), other.getCode()) &&
157 Objects.equals(getLength(), other.getLength()) &&
158 Objects.equals(clientIaAddress, other.clientIaAddress) &&
159 Objects.equals(options, other.options);
160 }
161}