blob: 8202b30e1e5ac7d3f7714c93f39f4b02721da067 [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;
Yi Tsengca34e1d2017-07-18 16:16:25 -070024
25import java.nio.ByteBuffer;
26import java.util.Objects;
27
28import static com.google.common.base.MoreObjects.toStringHelper;
29
Yi Tseng60bf35a2017-06-02 17:05:48 -070030/**
31 * Representation of an DHCPv6 Option.
32 * Base on RFC-3315.
33 */
Yi Tsengca34e1d2017-07-18 16:16:25 -070034public class Dhcp6Option extends BasePacket {
35 public static final int DEFAULT_LEN = 4;
Yi Tsengb4fdb042017-08-07 13:32:32 -070036 protected static final int UNSIGNED_SHORT_MASK = 0xffff;
Yi Tseng60bf35a2017-06-02 17:05:48 -070037 private short code;
38 private short length;
Yi Tsengca34e1d2017-07-18 16:16:25 -070039 // XXX: use "payload" from BasePacket for option data.
40
41 /**
42 * Default constructor.
43 */
44 public Dhcp6Option() {
45 }
46
47 /**
48 * Constructs a DHCPv6 option based on information from other DHCPv6 option.
49 *
50 * @param dhcp6Option other DHCPv6 option
51 */
52 public Dhcp6Option(Dhcp6Option dhcp6Option) {
Yi Tsengb4fdb042017-08-07 13:32:32 -070053 this.code = dhcp6Option.code;
54 this.length = dhcp6Option.length;
Yi Tsengca34e1d2017-07-18 16:16:25 -070055 this.payload = dhcp6Option.payload;
56 this.payload.setParent(this);
57 }
Yi Tseng60bf35a2017-06-02 17:05:48 -070058
59 /**
60 * Sets the code of this option.
61 *
62 * @param code the code to set
63 */
64 public void setCode(short code) {
65 this.code = code;
66 }
67
68 /**
Yi Tsengca34e1d2017-07-18 16:16:25 -070069 * Sets the data of this option.
Yi Tseng60bf35a2017-06-02 17:05:48 -070070 *
71 * @param data the data to set
72 */
73 public void setData(byte[] data) {
Yi Tsengca34e1d2017-07-18 16:16:25 -070074 try {
75 this.payload = Data.deserializer().deserialize(data, 0, data.length);
76 } catch (DeserializationException e) {
Ray Milkey986a47a2018-01-25 11:38:51 -080077 throw new IllegalArgumentException("Invalid data");
Yi Tsengca34e1d2017-07-18 16:16:25 -070078 }
Yi Tseng60bf35a2017-06-02 17:05:48 -070079 }
80
81 /**
82 * Sets length of this option.
83 *
84 * @param length the length to set
85 */
86 public void setLength(short length) {
87 this.length = length;
88 }
89
90 /**
91 * Gets the code of this option.
92 *
93 * @return the code
94 */
95 public short getCode() {
96 return code;
97 }
98
99 /**
100 * Gets the length of this option.
101 *
102 * @return the length of this option
103 */
104 public short getLength() {
105 return length;
106 }
107
108 /**
109 * Gets the data of this option.
110 *
111 * @return the data of this option
112 */
113 public byte[] getData() {
Yi Tsengca34e1d2017-07-18 16:16:25 -0700114 return payload.serialize();
115 }
116
117 /**
118 * Gets deserializer of DHCPv6 option.
119 *
120 * @return the deserializer of DHCPv6 option
121 */
122 public static Deserializer<Dhcp6Option> deserializer() {
123 return (data, offset, len) -> {
124 Dhcp6Option dhcp6Option = new Dhcp6Option();
125 if (len < DEFAULT_LEN) {
126 throw new DeserializationException("DHCPv6 option code length" +
127 "should be at least 4 bytes");
128 }
129 ByteBuffer bb = ByteBuffer.wrap(data, offset, len);
Yi Tsengb4fdb042017-08-07 13:32:32 -0700130 dhcp6Option.code = bb.getShort();
131 dhcp6Option.length = bb.getShort();
132 int optionLen = UNSIGNED_SHORT_MASK & dhcp6Option.length;
133 byte[] optData = new byte[optionLen];
Yi Tsengca34e1d2017-07-18 16:16:25 -0700134 bb.get(optData);
135 dhcp6Option.setData(optData);
136 return dhcp6Option;
137 };
138 }
139
140 @Override
141 public byte[] serialize() {
142 ByteBuffer bb = ByteBuffer.allocate(DEFAULT_LEN + getLength());
143 bb.putShort(getCode());
144 bb.putShort(getLength());
145 bb.put(payload.serialize());
146 return bb.array();
147 }
148
Yi Tsengca34e1d2017-07-18 16:16:25 -0700149
150 protected ToStringHelper getToStringHelper() {
151 return toStringHelper(Dhcp6Option.class)
152 .add("code", code)
153 .add("length", length);
154 }
155
156 @Override
157 public String toString() {
158 return getToStringHelper()
159 .add("data", payload.toString())
160 .toString();
161 }
162
163 @Override
164 public int hashCode() {
165 return 31 * super.hashCode() + Objects.hash(code, length);
166 }
167
168 @Override
169 public boolean equals(Object obj) {
170 if (this == obj) {
171 return true;
172 }
173 if (obj == null || getClass() != obj.getClass()) {
174 return false;
175 }
176 if (!super.equals(obj)) {
177 return false;
178 }
179 final Dhcp6Option other = (Dhcp6Option) obj;
180 return Objects.equals(this.code, other.code)
181 && Objects.equals(this.length, other.length);
Yi Tseng60bf35a2017-06-02 17:05:48 -0700182 }
183}