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