blob: 1cee5bed31ded80c74c79a87e95377a7e6c23eb5 [file] [log] [blame]
Charles M.C. Chan94f37372015-01-10 17:53:42 +08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
Charles M.C. Chan94f37372015-01-10 17:53:42 +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 */
16
17package org.onlab.packet.ipv6;
18
19import org.onlab.packet.BasePacket;
20import org.onlab.packet.Data;
Jonathan Hart2a655752015-04-07 16:46:33 -070021import org.onlab.packet.Deserializer;
Charles M.C. Chan94f37372015-01-10 17:53:42 +080022import org.onlab.packet.IPacket;
23import org.onlab.packet.IPv6;
Jonathan Hart2a655752015-04-07 16:46:33 -070024
Charles M.C. Chan94f37372015-01-10 17:53:42 +080025import java.nio.ByteBuffer;
26import java.util.Arrays;
27
Jian Li5fc14292015-12-04 11:30:46 -080028import static com.google.common.base.MoreObjects.toStringHelper;
Jonathan Hart2a655752015-04-07 16:46:33 -070029import static org.onlab.packet.PacketUtils.checkInput;
30
Charles M.C. Chan94f37372015-01-10 17:53:42 +080031/**
32 * Implements IPv6 authentication extension header format. (RFC 4302)
33 */
34public class Authentication extends BasePacket implements IExtensionHeader {
35 public static final byte FIXED_HEADER_LENGTH = 12; // bytes
36 public static final byte LENGTH_UNIT = 4; // bytes per unit
37 public static final byte MINUS = 2;
38
39 protected byte nextHeader;
40 protected byte payloadLength;
41 protected int securityParamIndex;
42 protected int sequence;
43 protected byte[] integrityCheck;
44
45 @Override
46 public byte getNextHeader() {
47 return this.nextHeader;
48 }
49
50 @Override
51 public Authentication setNextHeader(final byte nextHeader) {
52 this.nextHeader = nextHeader;
53 return this;
54 }
55
56 /**
57 * Gets the payload length of this header.
58 *
59 * @return the payload length
60 */
61 public byte getPayloadLength() {
62 return this.payloadLength;
63 }
64
65 /**
66 * Sets the payload length of this header.
67 *
68 * @param payloadLength the payload length to set
69 * @return this
70 */
71 public Authentication setPayloadLength(final byte payloadLength) {
72 this.payloadLength = payloadLength;
73 return this;
74 }
75
76 /**
77 * Gets the security parameter index of this header.
78 *
79 * @return the security parameter index
80 */
81 public int getSecurityParamIndex() {
82 return this.securityParamIndex;
83 }
84
85 /**
86 * Sets the security parameter index of this header.
87 *
88 * @param securityParamIndex the security parameter index to set
89 * @return this
90 */
91 public Authentication setSecurityParamIndex(final int securityParamIndex) {
92 this.securityParamIndex = securityParamIndex;
93 return this;
94 }
95
96 /**
97 * Gets the sequence number of this header.
98 *
99 * @return the sequence number
100 */
101 public int getSequence() {
102 return this.sequence;
103 }
104
105 /**
106 * Sets the sequence number of this header.
107 *
108 * @param sequence the sequence number to set
109 * @return this
110 */
111 public Authentication setSequence(final int sequence) {
112 this.sequence = sequence;
113 return this;
114 }
115
116 /**
117 * Gets the integrity check value of this header.
118 *
119 * @return the integrity check value
120 */
121 public byte[] getIntegrityCheck() {
122 return this.integrityCheck;
123 }
124
125 /**
126 * Sets the integrity check value of this header.
127 *
128 * @param integrityCheck the integrity check value to set
129 * @return this
130 */
131 public Authentication setIngegrityCheck(final byte[] integrityCheck) {
132 this.integrityCheck =
133 Arrays.copyOfRange(integrityCheck, 0, integrityCheck.length);
134 return this;
135 }
136
137 /**
138 * Gets the total length of this header.
139 * According to spec, payload length should be the total length of this AH
140 * in 4-octet unit, minus 2
141 *
142 * @return the total length
143 */
144 public int getTotalLength() {
145 return (this.payloadLength + MINUS) * LENGTH_UNIT;
146 }
147
148 @Override
149 public byte[] serialize() {
150 byte[] payloadData = null;
151 if (this.payload != null) {
152 this.payload.setParent(this);
153 payloadData = this.payload.serialize();
154 }
155
156 int headerLength = FIXED_HEADER_LENGTH + integrityCheck.length;
157 int payloadLength = 0;
158 if (payloadData != null) {
159 payloadLength = payloadData.length;
160 }
161
162 final byte[] data = new byte[headerLength + payloadLength];
163 final ByteBuffer bb = ByteBuffer.wrap(data);
164
165 bb.put(this.nextHeader);
166 bb.put(this.payloadLength);
167 bb.putShort((short) 0);
168 bb.putInt(this.securityParamIndex);
169 bb.putInt(this.sequence);
170 bb.put(this.integrityCheck, 0, integrityCheck.length);
171
172 if (payloadData != null) {
173 bb.put(payloadData);
174 }
175
176 if (this.parent != null && this.parent instanceof IExtensionHeader) {
177 ((IExtensionHeader) this.parent).setNextHeader(IPv6.PROTOCOL_AH);
178 }
179 return data;
180 }
181
Charles M.C. Chan94f37372015-01-10 17:53:42 +0800182 /*
183 * (non-Javadoc)
184 *
185 * @see java.lang.Object#hashCode()
186 */
187 @Override
188 public int hashCode() {
189 final int prime = 5807;
190 int result = super.hashCode();
191 result = prime * result + this.nextHeader;
192 result = prime * result + this.payloadLength;
193 result = prime * result + this.securityParamIndex;
194 result = prime * result + this.sequence;
195 for (byte b : this.integrityCheck) {
196 result = prime * result + b;
197 }
198 return result;
199 }
200
201 /*
202 * (non-Javadoc)
203 *
204 * @see java.lang.Object#equals(java.lang.Object)
205 */
206 @Override
207 public boolean equals(final Object obj) {
208 if (this == obj) {
209 return true;
210 }
211 if (!super.equals(obj)) {
212 return false;
213 }
214 if (!(obj instanceof Authentication)) {
215 return false;
216 }
217 final Authentication other = (Authentication) obj;
218 if (this.nextHeader != other.nextHeader) {
219 return false;
220 }
221 if (this.payloadLength != other.payloadLength) {
222 return false;
223 }
224 if (this.securityParamIndex != other.securityParamIndex) {
225 return false;
226 }
227 if (this.sequence != other.sequence) {
228 return false;
229 }
230 if (!Arrays.equals(this.integrityCheck, other.integrityCheck)) {
231 return false;
232 }
233 return true;
234 }
Jonathan Hart2a655752015-04-07 16:46:33 -0700235
236 /**
237 * Deserializer function for authentication headers.
238 *
239 * @return deserializer function
240 */
241 public static Deserializer<Authentication> deserializer() {
242 return (data, offset, length) -> {
243 checkInput(data, offset, length, FIXED_HEADER_LENGTH);
244
245 Authentication authentication = new Authentication();
246
247 ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
248 authentication.nextHeader = bb.get();
249 authentication.payloadLength = bb.get();
250 bb.getShort();
251 authentication.securityParamIndex = bb.getInt();
252 authentication.sequence = bb.getInt();
253 int icvLength = (authentication.payloadLength + MINUS) * LENGTH_UNIT - FIXED_HEADER_LENGTH;
254 authentication.integrityCheck = new byte[icvLength];
255 bb.get(authentication.integrityCheck, 0, icvLength);
256
257 Deserializer<? extends IPacket> deserializer;
258 if (IPv6.PROTOCOL_DESERIALIZER_MAP.containsKey(authentication.nextHeader)) {
259 deserializer = IPv6.PROTOCOL_DESERIALIZER_MAP.get(authentication.nextHeader);
260 } else {
261 deserializer = Data.deserializer();
262 }
263 authentication.payload = deserializer.deserialize(data, bb.position(),
264 bb.limit() - bb.position());
265 authentication.payload.setParent(authentication);
266
267 return authentication;
268 };
269 }
Jian Li5fc14292015-12-04 11:30:46 -0800270
271 @Override
272 public String toString() {
273 return toStringHelper(getClass())
274 .add("nextHeader", Byte.toString(nextHeader))
275 .add("payloadLength", Byte.toString(payloadLength))
276 .add("securityParamIndex", Integer.toString(securityParamIndex))
277 .add("sequence", Integer.toString(sequence))
278 .add("integrityCheck", Arrays.toString(integrityCheck))
279 .toString();
280 }
Charles M.C. Chan94f37372015-01-10 17:53:42 +0800281}