blob: 0185542e5df16fd113b6b20a309a82e4a0530e0c [file] [log] [blame]
Chidambar babu86b3b1a2016-02-16 17:39:52 +05301/*
2 * Copyright 2016 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 */
16package org.onosproject.ospf.protocol.util;
17
18import com.google.common.primitives.Bytes;
19import org.jboss.netty.buffer.ChannelBuffer;
20import org.jboss.netty.buffer.ChannelBuffers;
21import org.onlab.packet.Ip4Address;
22import org.onosproject.ospf.protocol.lsa.LsaHeader;
23import org.onosproject.ospf.protocol.lsa.OpaqueLsaHeader;
24import org.slf4j.Logger;
25import org.slf4j.LoggerFactory;
26
27import javax.xml.bind.DatatypeConverter;
28import java.net.InetAddress;
29import java.util.Arrays;
30import java.util.Collections;
31import java.util.List;
32import java.util.Random;
33import java.util.StringTokenizer;
34
35/**
36 * Representation of an OSPF constants and utility methods.
37 */
38public final class OspfUtil {
39
40 public static final int OSPF_VERSION_2 = 2;
41 public static final int OSPF_VERSION = OSPF_VERSION_2;
42 public static final int PACKET_MINIMUM_LENGTH = 24;
43 public static final int OSPF_HEADER_LENGTH = 24;
44 public static final int LSA_HEADER_LENGTH = 20;
45 public static final int DD_HEADER_LENGTH = OSPF_HEADER_LENGTH + 8;
46 public static final int LSREQUEST_LENGTH = 12;
47 public static final int OSPFPACKET_LENGTH_POS1 = 2;
48 public static final int OSPFPACKET_LENGTH_POS2 = 3;
49 public static final int OSPFPACKET_CHECKSUM_POS1 = 12;
50 public static final int OSPFPACKET_CHECKSUM_POS2 = 13;
51 public static final int LSAPACKET_CHECKSUM_POS1 = 16;
52 public static final int LSAPACKET_CHECKSUM_POS2 = 17;
53 public static final Ip4Address ALL_SPF_ROUTERS = Ip4Address.valueOf("224.0.0.5");
54 public static final Ip4Address ALL_DROUTERS = Ip4Address.valueOf("224.0.0.6");
55 public static final int ONLY_ALL_SPF_ROUTERS = 1;
56 public static final int JOIN_ALL_DROUTERS = 2;
57 public static final int INITIALIZE_SET = 1;
58 public static final int INITIALIZE_NOTSET = 0;
59 public static final int MORE_SET = 1;
60 public static final int MORE_NOTSET = 0;
61 public static final int IS_MASTER = 1;
62 public static final int NOT_MASTER = 0;
63 public static final int NOT_ASSIGNED = 0;
64 public static final int FOUR_BYTES = 4;
65 public static final int EIGHT_BYTES = 8;
66 public static final int TWELVE_BYTES = 12;
67 public static final int EXTERNAL_DESTINATION_LENGTH = 12;
68 private static final Logger log =
69 LoggerFactory.getLogger(OspfUtil.class);
70
71 /**
72 * Creates an instance.
73 */
74 private OspfUtil() {
75
76 }
77
78 /**
79 * Checks given IPs are in same network or not.
80 *
81 * @param ip1 IP address
82 * @param ip2 IP address
83 * @param mask network mask
84 * @return true if both are in same network else false
85 * @throws Exception might throws exception while parsing ip address
86 */
87 public static boolean sameNetwork(Ip4Address ip1, Ip4Address ip2, Ip4Address mask)
88 throws Exception {
89
90 byte[] a1 = ip1.toOctets();
91 byte[] a2 = ip2.toOctets();
92 byte[] m = mask.toOctets();
93
94 for (int i = 0; i < a1.length; i++) {
95 if ((a1[i] & m[i]) != (a2[i] & m[i])) {
96 return false;
97 }
98 }
99
100 return true;
101 }
102
103 /**
104 * Converts IP address to long.
105 *
106 * @param ipAddress IP address
107 * @return long value represents IP address
108 */
109 public static long ipAddressToLong(String ipAddress) {
110 StringTokenizer st = new StringTokenizer(ipAddress, ".");
111 long ipAsNumber = Long.parseLong(st.nextToken()) * (long) Math.pow(256, 3);
112 ipAsNumber += Long.parseLong(st.nextToken()) * (long) Math.pow(256, 2);
113 ipAsNumber += Long.parseLong(st.nextToken()) * 256;
114 ipAsNumber += +Long.parseLong(st.nextToken());
115
116 return ipAsNumber;
117 }
118
119 /**
120 * Checks option field to see whether opaque enabled or not.
121 * 2nd Bit in options field of DdPacket represents Opaque.
122 * 7th bit is external capability.
123 * This method checks Opaque bit is set in the options or not.
124 *
125 * @param options options value
126 * @return true if opaque enabled else false.
127 */
128 public static boolean isOpaqueEnabled(int options) {
129 Boolean[] bits = new Boolean[8];
130 for (int i = 7; i >= 0; i--) {
131 bits[i] = (options & (1 << i)) != 0;
132 }
133
134 List<Boolean> list = Arrays.asList(bits);
135 Collections.reverse(list);
136
137 //2nd bit is Opaque.
138 return list.get(1);
139 }
140
141 /**
142 * Converts a byte to integer variable.
143 *
144 * @param bytesToConvert bytes to convert
145 * @return integer representation of bytes
146 */
147 public static int byteToInteger(byte[] bytesToConvert) {
148 final StringBuilder builder = new StringBuilder();
149 for (byte eachByte : bytesToConvert) {
150 builder.append(String.format("%02x", eachByte));
151 }
152 int num = Integer.parseInt(builder.toString(), 16);
153 return num;
154 }
155
156 /**
157 * Converts a byte to long variable.
158 *
159 * @param bytesToConvert bytes to convert
160 * @return long representation of bytes
161 */
162 public static long byteToLong(byte[] bytesToConvert) {
163 final StringBuilder builder = new StringBuilder();
164 for (byte eachByte : bytesToConvert) {
165 builder.append(String.format("%02x", eachByte));
166 }
167 long num = Long.parseLong(builder.toString(), 16);
168 return num;
169 }
170
171 /**
172 * Creates a random number.
173 *
174 * @return random number
175 */
176 public static int createRandomNumber() {
177 Random rnd = new Random();
178 int randomNumber = 10000000 + rnd.nextInt(90000000);
179 return randomNumber;
180 }
181
182 /**
183 * Reads the LSA header from channel buffer.
184 *
185 * @param channelBuffer channel buffer instance
186 * @return LSA header instance.
187 * @throws Exception might throws exception while parsing buffer
188 */
189 public static LsaHeader readLsaHeader(ChannelBuffer channelBuffer) throws Exception {
190 //add all the LSA Headers - one header is of 20 bytes
191 LsaHeader lsaHeader = null;
192 if (channelBuffer.readableBytes() >= OspfUtil.LSA_HEADER_LENGTH) {
193 byte[] byteArray = new byte[OspfUtil.FOUR_BYTES];
194 channelBuffer.readBytes(byteArray, 0, OspfUtil.FOUR_BYTES);
195 ChannelBuffer tempBuffer = ChannelBuffers.copiedBuffer(byteArray);
196 int lsType = byteArray[3];
197 if (lsType == OspfParameters.AREA_LOCAL_OPAQUE_LSA || lsType == OspfParameters.LINK_LOCAL_OPAQUE_LSA
198 || lsType == OspfParameters.AS_OPAQUE_LSA) {
199 OpaqueLsaHeader header = new OpaqueLsaHeader();
200 header.setAge(tempBuffer.readShort());
201 header.setOptions(tempBuffer.readByte());
202 header.setLsType(tempBuffer.readByte());
203 header.setOpaqueType(channelBuffer.readByte());
204 header.setOpaqueId(channelBuffer.readUnsignedMedium());
205 byte[] tempByteArray = new byte[OspfUtil.FOUR_BYTES];
206 channelBuffer.readBytes(tempByteArray, 0, OspfUtil.FOUR_BYTES);
207 header.setAdvertisingRouter(Ip4Address.valueOf(tempByteArray));
208 header.setLsSequenceNo(channelBuffer.readInt());
209 header.setLsCheckSum(channelBuffer.readUnsignedShort());
210 header.setLsPacketLen(channelBuffer.readShort());
211 byte[] opaqueIdBytes = OspfUtil.convertToTwoBytes(header.opaqueId());
212 header.setLinkStateId(header.opaqueType() + "." + "0" + "." +
213 opaqueIdBytes[0] + "." + opaqueIdBytes[1]);
214 lsaHeader = header;
215 } else {
216 LsaHeader header = new LsaHeader();
217 header.setAge(tempBuffer.readShort());
218 header.setOptions(tempBuffer.readByte());
219 header.setLsType(tempBuffer.readByte());
220 byte[] tempByteArray = new byte[OspfUtil.FOUR_BYTES];
221 channelBuffer.readBytes(tempByteArray, 0, OspfUtil.FOUR_BYTES);
222 header.setLinkStateId(InetAddress.getByAddress(tempByteArray).getHostName());
223 tempByteArray = new byte[OspfUtil.FOUR_BYTES];
224 channelBuffer.readBytes(tempByteArray, 0, OspfUtil.FOUR_BYTES);
225 header.setAdvertisingRouter(Ip4Address.valueOf(tempByteArray));
226 header.setLsSequenceNo(channelBuffer.readInt());
227 header.setLsCheckSum(channelBuffer.readUnsignedShort());
228 header.setLsPacketLen(channelBuffer.readShort());
229 lsaHeader = header;
230 }
231 }
232 return lsaHeader;
233 }
234
235
236 /**
237 * Converts an integer to two bytes.
238 *
239 * @param numberToConvert number to convert
240 * @return given number as bytes
241 */
242 public static byte[] convertToTwoBytes(int numberToConvert) {
243
244 byte[] numInBytes = new byte[2];
245 String s1 = Integer.toHexString(numberToConvert);
246 if (s1.length() % 2 != 0) {
247 s1 = "0" + s1;
248 }
249 byte[] hexas = DatatypeConverter.parseHexBinary(s1);
250 if (hexas.length == 1) {
251 numInBytes[0] = 0;
252 numInBytes[1] = hexas[0];
253 } else {
254 numInBytes[0] = hexas[0];
255 numInBytes[1] = hexas[1];
256 }
257 return numInBytes;
258 }
259
260 /**
261 * Converts a number to three bytes.
262 *
263 * @param numberToConvert number to convert
264 * @return given number as bytes
265 */
266 public static byte[] convertToThreeBytes(int numberToConvert) {
267 byte[] numInBytes = new byte[3];
268 String s1 = Integer.toHexString(numberToConvert);
269 if (s1.length() % 2 != 0) {
270 s1 = "0" + s1;
271 }
272 byte[] hexas = DatatypeConverter.parseHexBinary(s1);
273 if (hexas.length == 1) {
274 numInBytes[0] = 0;
275 numInBytes[1] = 0;
276 numInBytes[2] = hexas[0];
277 } else if (hexas.length == 2) {
278 numInBytes[0] = 0;
279 numInBytes[1] = hexas[0];
280 numInBytes[2] = hexas[1];
281 } else {
282 numInBytes[0] = hexas[0];
283 numInBytes[1] = hexas[1];
284 numInBytes[2] = hexas[2];
285 }
286 return numInBytes;
287 }
288
289 /**
290 * Converts a number to four bytes.
291 *
292 * @param numberToConvert number to convert
293 * @return given number as bytes
294 */
295 public static byte[] convertToFourBytes(int numberToConvert) {
296
297 byte[] numInBytes = new byte[4];
298 String s1 = Integer.toHexString(numberToConvert);
299 if (s1.length() % 2 != 0) {
300 s1 = "0" + s1;
301 }
302 byte[] hexas = DatatypeConverter.parseHexBinary(s1);
303 if (hexas.length == 1) {
304 numInBytes[0] = 0;
305 numInBytes[1] = 0;
306 numInBytes[2] = 0;
307 numInBytes[3] = hexas[0];
308 } else if (hexas.length == 2) {
309 numInBytes[0] = 0;
310 numInBytes[1] = 0;
311 numInBytes[2] = hexas[0];
312 numInBytes[3] = hexas[1];
313 } else if (hexas.length == 3) {
314 numInBytes[0] = 0;
315 numInBytes[1] = hexas[0];
316 numInBytes[2] = hexas[1];
317 numInBytes[3] = hexas[2];
318 } else {
319 numInBytes[0] = hexas[0];
320 numInBytes[1] = hexas[1];
321 numInBytes[2] = hexas[2];
322 numInBytes[3] = hexas[3];
323 }
324 return numInBytes;
325 }
326
327 /**
328 * Converts a number to four bytes.
329 *
330 * @param numberToConvert number to convert
331 * @return given number as bytes
332 */
333 public static byte[] convertToFourBytes(long numberToConvert) {
334
335 byte[] numInBytes = new byte[4];
336 String s1 = Long.toHexString(numberToConvert);
337 if (s1.length() % 2 != 0) {
338 s1 = "0" + s1;
339 }
340 if (s1.length() == 16) {
341 s1 = s1.substring(8, s1.length());
342 }
343 byte[] hexas = DatatypeConverter.parseHexBinary(s1);
344 if (hexas.length == 1) {
345 numInBytes[0] = 0;
346 numInBytes[1] = 0;
347 numInBytes[2] = 0;
348 numInBytes[3] = hexas[0];
349 } else if (hexas.length == 2) {
350 numInBytes[0] = 0;
351 numInBytes[1] = 0;
352 numInBytes[2] = hexas[0];
353 numInBytes[3] = hexas[1];
354 } else if (hexas.length == 3) {
355 numInBytes[0] = 0;
356 numInBytes[1] = hexas[0];
357 numInBytes[2] = hexas[1];
358 numInBytes[3] = hexas[2];
359 } else {
360 numInBytes[0] = hexas[0];
361 numInBytes[1] = hexas[1];
362 numInBytes[2] = hexas[2];
363 numInBytes[3] = hexas[3];
364 }
365 return numInBytes;
366 }
367
368 /**
369 * Adds the checksum and length in packet.
370 *
371 * @param ospfPacket ospf packet
372 * @param lengthBytePos1 length byte position
373 * @param lengthBytePos2 length byte position
374 * @param checksumBytePos1 checksum byte position
375 * @param checksumBytePos2 checksum byte position
376 * @return byte array with checksum and length
377 */
378 public static byte[] addLengthAndCheckSum(byte[] ospfPacket, int lengthBytePos1, int lengthBytePos2,
379 int checksumBytePos1, int checksumBytePos2) {
380 //Set the length of the packet
381 //Get the total length of the packet
382 int length = ospfPacket.length;
383 //Convert the lenth to two bytes as the length field is 2 bytes
384 byte[] lenthInTwoBytes = OspfUtil.convertToTwoBytes(length);
385 //ospf header 3rd and 4th position represents length
386 ospfPacket[lengthBytePos1] = lenthInTwoBytes[0]; //assign 1st byte in lengthBytePos1
387 ospfPacket[lengthBytePos2] = lenthInTwoBytes[1]; //assign 2st byte in lengthBytePos2
388
389 //Get the checksum as two bytes.
390 byte[] checkSumInTwoBytes = new ChecksumCalculator().calculateOspfCheckSum(ospfPacket,
391 checksumBytePos1, checksumBytePos2);
392 ospfPacket[checksumBytePos1] = checkSumInTwoBytes[0]; //assign 1st byte in checksumBytePos1
393 ospfPacket[checksumBytePos2] = checkSumInTwoBytes[1]; //assign 2st byte in checksumBytePos2
394
395 return ospfPacket;
396 }
397
398 /**
399 * Adds metadata to ospf packet like whether to join multi cast group and destination IP.
400 *
401 * @param ospfPacket OSPF packet
402 * @param allDroutersValue whether to join multi cast or not
403 * @param destinationIp destination ip address
404 * @return byte array
405 */
406 public static byte[] addMetadata(byte[] ospfPacket, int allDroutersValue, Ip4Address destinationIp) {
407 byte[] packet;
408 byte[] allDroutersByteVal = {(byte) allDroutersValue};
409 byte[] destIpAsBytes = destinationIp.toOctets();
410 byte[] metadata = Bytes.concat(allDroutersByteVal, destIpAsBytes);
411
412 packet = Bytes.concat(metadata, ospfPacket);
413
414 return packet;
415 }
416}