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