blob: 515dd4ef4c15971b6f36b8db361fce10bafecb2f [file] [log] [blame]
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +08001/*
Dusan Pajina22b9702015-02-12 16:25:23 +01002 * Copyright 2014-2015 Open Networking Laboratory
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +08003 *
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 */
Charles M.C. Chanea5aa472015-01-03 13:40:39 +080016package org.onlab.packet.ndp;
17
18import org.onlab.packet.BasePacket;
19import org.onlab.packet.Data;
20import org.onlab.packet.IPacket;
21import org.onlab.packet.Ip6Address;
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +080022
23import java.nio.ByteBuffer;
24import java.util.Arrays;
25
26/**
Dusan Pajina22b9702015-02-12 16:25:23 +010027 * Implements ICMPv6 Neighbor Advertisement packet format (RFC 4861).
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +080028 */
29public class NeighborAdvertisement extends BasePacket {
30 public static final byte HEADER_LENGTH = 20; // bytes
Dusan Pajina22b9702015-02-12 16:25:23 +010031 public static final byte OPTION_TYPE_SOURCE_LL_ADDRESS = 1;
32 public static final byte OPTION_TYPE_TARGET_LL_ADDRESS = 2;
33 public static final byte OPTION_TYPE_PREFIX_INFORMATION = 3;
34 public static final byte OPTION_TYPE_REDIRECTED_HEADER = 4;
35 public static final byte OPTION_TYPE_MTU = 5;
36 public static final byte OPTION_LENGTH_IEEE802_ADDRESS = 8;
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +080037
38 protected byte routerFlag;
39 protected byte solicitedFlag;
40 protected byte overrideFlag;
41 protected byte[] targetAddress = new byte[Ip6Address.BYTE_LENGTH];
42
43 /**
Charles M.C. Chan7fee36a2014-12-31 00:19:59 +080044 * Gets router flag.
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +080045 *
Charles M.C. Chan7fee36a2014-12-31 00:19:59 +080046 * @return the router flag
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +080047 */
48 public byte getRouterFlag() {
49 return this.routerFlag;
50 }
51
52 /**
Charles M.C. Chan7fee36a2014-12-31 00:19:59 +080053 * Sets router flag.
54 *
55 * @param routerFlag the router flag to set
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +080056 * @return this
57 */
58 public NeighborAdvertisement setRouterFlag(final byte routerFlag) {
59 this.routerFlag = routerFlag;
60 return this;
61 }
62
63 /**
Charles M.C. Chan7fee36a2014-12-31 00:19:59 +080064 * Gets solicited flag.
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +080065 *
Charles M.C. Chan7fee36a2014-12-31 00:19:59 +080066 * @return the solicited flag
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +080067 */
68 public byte getSolicitedFlag() {
69 return this.solicitedFlag;
70 }
71
72 /**
Charles M.C. Chan7fee36a2014-12-31 00:19:59 +080073 * Sets solicited flag.
74 *
75 * @param solicitedFlag the solicited flag to set
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +080076 * @return this
77 */
78 public NeighborAdvertisement setSolicitedFlag(final byte solicitedFlag) {
79 this.solicitedFlag = solicitedFlag;
80 return this;
81 }
82
83 /**
Charles M.C. Chan7fee36a2014-12-31 00:19:59 +080084 * Gets override flag.
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +080085 *
Charles M.C. Chan7fee36a2014-12-31 00:19:59 +080086 * @return the override flag
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +080087 */
88 public byte getOverrideFlag() {
89 return this.overrideFlag;
90 }
91
92 /**
Charles M.C. Chan7fee36a2014-12-31 00:19:59 +080093 * Sets override flag.
94 *
95 * @param overrideFlag the override flag to set
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +080096 * @return this
97 */
98 public NeighborAdvertisement setOverrideFlag(final byte overrideFlag) {
99 this.overrideFlag = overrideFlag;
100 return this;
101 }
102
103 /**
Charles M.C. Chan7fee36a2014-12-31 00:19:59 +0800104 * Gets target address.
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +0800105 *
106 * @return the target IPv6 address
107 */
108 public byte[] getTargetAddress() {
109 return this.targetAddress;
110 }
111
112 /**
Charles M.C. Chan7fee36a2014-12-31 00:19:59 +0800113 * Sets target address.
114 *
115 * @param targetAddress the target IPv6 address to set
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +0800116 * @return this
117 */
118 public NeighborAdvertisement setTargetAddress(final byte[] targetAddress) {
119 this.targetAddress = Arrays.copyOfRange(targetAddress, 0, Ip6Address.BYTE_LENGTH);
120 return this;
121 }
122
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +0800123 @Override
124 public byte[] serialize() {
125 byte[] payloadData = null;
126 if (this.payload != null) {
127 this.payload.setParent(this);
128 payloadData = this.payload.serialize();
129 }
130
Charles M.C. Chan5c0b4762015-01-10 18:38:37 +0800131 int payloadLength = 0;
132 if (payloadData != null) {
133 payloadLength = payloadData.length;
134 }
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +0800135
136 final byte[] data = new byte[HEADER_LENGTH + payloadLength];
137 final ByteBuffer bb = ByteBuffer.wrap(data);
138
139 bb.putInt((this.routerFlag & 0x1) << 31 | (this.solicitedFlag & 0x1) << 30 | (this.overrideFlag & 0x1) << 29);
140 bb.put(this.targetAddress, 0, Ip6Address.BYTE_LENGTH);
141 if (payloadData != null) {
142 bb.put(payloadData);
143 }
144
145 return data;
146 }
147
148 @Override
149 public IPacket deserialize(byte[] data, int offset, int length) {
150 final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
151 int iscratch;
152
153 iscratch = bb.getInt();
154 this.routerFlag = (byte) (iscratch >> 31 & 0x1);
155 this.solicitedFlag = (byte) (iscratch >> 30 & 0x1);
156 this.overrideFlag = (byte) (iscratch >> 29 & 0x1);
157 bb.get(this.targetAddress, 0, Ip6Address.BYTE_LENGTH);
158
159 this.payload = new Data();
160 this.payload = this.payload.deserialize(data, bb.position(), bb.limit()
161 - bb.position());
162 this.payload.setParent(this);
163
164 return this;
165 }
166
167 /*
Charles M.C. Chan7fee36a2014-12-31 00:19:59 +0800168 * (non-Javadoc)
169 *
170 * @see java.lang.Object#hashCode()
171 */
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +0800172 @Override
173 public int hashCode() {
174 final int prime = 5807;
175 int result = super.hashCode();
176 ByteBuffer bb;
177 result = prime * result + this.routerFlag;
178 result = prime * result + this.solicitedFlag;
179 result = prime * result + this.overrideFlag;
180 bb = ByteBuffer.wrap(this.targetAddress);
181 for (int i = 0; i < 4; i++) {
182 result = prime * result + bb.getInt();
183 }
184 return result;
185 }
186
187 /*
188 * (non-Javadoc)
189 *
190 * @see java.lang.Object#equals(java.lang.Object)
191 */
192 @Override
193 public boolean equals(final Object obj) {
194 if (this == obj) {
195 return true;
196 }
197 if (!super.equals(obj)) {
198 return false;
199 }
200 if (!(obj instanceof NeighborAdvertisement)) {
201 return false;
202 }
203 final NeighborAdvertisement other = (NeighborAdvertisement) obj;
204 if (this.routerFlag != other.routerFlag) {
205 return false;
206 }
207 if (this.solicitedFlag != other.solicitedFlag) {
208 return false;
209 }
210 if (this.overrideFlag != other.overrideFlag) {
211 return false;
212 }
213 if (!Arrays.equals(this.targetAddress, other.targetAddress)) {
214 return false;
215 }
216 return true;
217 }
218}