blob: 597732d0cb18e5123f1a9e7b877c84040a3714df [file] [log] [blame]
Yi Tseng60bf35a2017-06-02 17:05:48 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
Yi Tseng60bf35a2017-06-02 17:05:48 -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
Yi Tsengc7403c22017-06-19 16:23:22 -070017package org.onlab.packet.dhcp;
Yi Tseng60bf35a2017-06-02 17:05:48 -070018
Yi Tsengca34e1d2017-07-18 16:16:25 -070019import com.google.common.base.MoreObjects.ToStringHelper;
20import org.onlab.packet.BasePacket;
21import org.onlab.packet.Data;
22import org.onlab.packet.DeserializationException;
23import org.onlab.packet.Deserializer;
24import org.onlab.packet.IPacket;
25
26import java.nio.ByteBuffer;
27import java.util.Objects;
28
29import static com.google.common.base.MoreObjects.toStringHelper;
30
Yi Tseng60bf35a2017-06-02 17:05:48 -070031/**
32 * Representation of an DHCPv6 Option.
33 * Base on RFC-3315.
34 */
Yi Tsengca34e1d2017-07-18 16:16:25 -070035public class Dhcp6Option extends BasePacket {
36 public static final int DEFAULT_LEN = 4;
Yi Tsengb4fdb042017-08-07 13:32:32 -070037 protected static final int UNSIGNED_SHORT_MASK = 0xffff;
Yi Tseng60bf35a2017-06-02 17:05:48 -070038 private short code;
39 private short length;
Yi Tsengca34e1d2017-07-18 16:16:25 -070040 // XXX: use "payload" from BasePacket for option data.
41
42 /**
43 * Default constructor.
44 */
45 public Dhcp6Option() {
46 }
47
48 /**
49 * Constructs a DHCPv6 option based on information from other DHCPv6 option.
50 *
51 * @param dhcp6Option other DHCPv6 option
52 */
53 public Dhcp6Option(Dhcp6Option dhcp6Option) {
Yi Tsengb4fdb042017-08-07 13:32:32 -070054 this.code = dhcp6Option.code;
55 this.length = dhcp6Option.length;
Yi Tsengca34e1d2017-07-18 16:16:25 -070056 this.payload = dhcp6Option.payload;
57 this.payload.setParent(this);
58 }
Yi Tseng60bf35a2017-06-02 17:05:48 -070059
60 /**
61 * Sets the code of this option.
62 *
63 * @param code the code to set
64 */
65 public void setCode(short code) {
66 this.code = code;
67 }
68
69 /**
Yi Tsengca34e1d2017-07-18 16:16:25 -070070 * Sets the data of this option.
Yi Tseng60bf35a2017-06-02 17:05:48 -070071 *
72 * @param data the data to set
73 */
74 public void setData(byte[] data) {
Yi Tsengca34e1d2017-07-18 16:16:25 -070075 try {
76 this.payload = Data.deserializer().deserialize(data, 0, data.length);
77 } catch (DeserializationException e) {
78 throw new RuntimeException("Invalid data");
79 }
Yi Tseng60bf35a2017-06-02 17:05:48 -070080 }
81
82 /**
83 * Sets length of this option.
84 *
85 * @param length the length to set
86 */
87 public void setLength(short length) {
88 this.length = length;
89 }
90
91 /**
92 * Gets the code of this option.
93 *
94 * @return the code
95 */
96 public short getCode() {
97 return code;
98 }
99
100 /**
101 * Gets the length of this option.
102 *
103 * @return the length of this option
104 */
105 public short getLength() {
106 return length;
107 }
108
109 /**
110 * Gets the data of this option.
111 *
112 * @return the data of this option
113 */
114 public byte[] getData() {
Yi Tsengca34e1d2017-07-18 16:16:25 -0700115 return payload.serialize();
116 }
117
118 /**
119 * Gets deserializer of DHCPv6 option.
120 *
121 * @return the deserializer of DHCPv6 option
122 */
123 public static Deserializer<Dhcp6Option> deserializer() {
124 return (data, offset, len) -> {
125 Dhcp6Option dhcp6Option = new Dhcp6Option();
126 if (len < DEFAULT_LEN) {
127 throw new DeserializationException("DHCPv6 option code length" +
128 "should be at least 4 bytes");
129 }
130 ByteBuffer bb = ByteBuffer.wrap(data, offset, len);
Yi Tsengb4fdb042017-08-07 13:32:32 -0700131 dhcp6Option.code = bb.getShort();
132 dhcp6Option.length = bb.getShort();
133 int optionLen = UNSIGNED_SHORT_MASK & dhcp6Option.length;
134 byte[] optData = new byte[optionLen];
Yi Tsengca34e1d2017-07-18 16:16:25 -0700135 bb.get(optData);
136 dhcp6Option.setData(optData);
137 return dhcp6Option;
138 };
139 }
140
141 @Override
142 public byte[] serialize() {
143 ByteBuffer bb = ByteBuffer.allocate(DEFAULT_LEN + getLength());
144 bb.putShort(getCode());
145 bb.putShort(getLength());
146 bb.put(payload.serialize());
147 return bb.array();
148 }
149
150 @Override
151 public IPacket deserialize(byte[] data, int offset, int length) {
152 try {
153 return deserializer().deserialize(data, offset, length);
154 } catch (DeserializationException e) {
155 throw new RuntimeException("Can't deserialize data for DHCPv6 option.", e);
156 }
157 }
158
159 protected ToStringHelper getToStringHelper() {
160 return toStringHelper(Dhcp6Option.class)
161 .add("code", code)
162 .add("length", length);
163 }
164
165 @Override
166 public String toString() {
167 return getToStringHelper()
168 .add("data", payload.toString())
169 .toString();
170 }
171
172 @Override
173 public int hashCode() {
174 return 31 * super.hashCode() + Objects.hash(code, length);
175 }
176
177 @Override
178 public boolean equals(Object obj) {
179 if (this == obj) {
180 return true;
181 }
182 if (obj == null || getClass() != obj.getClass()) {
183 return false;
184 }
185 if (!super.equals(obj)) {
186 return false;
187 }
188 final Dhcp6Option other = (Dhcp6Option) obj;
189 return Objects.equals(this.code, other.code)
190 && Objects.equals(this.length, other.length);
Yi Tseng60bf35a2017-06-02 17:05:48 -0700191 }
192}