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