Merge "OPNFLWPLUG-898 : remove deprecated checkedfuture"
[openflowplugin.git] / libraries / liblldp / src / main / java / org / opendaylight / openflowplugin / libraries / liblldp / NetUtils.java
1 /*
2  * Copyright (c) 2013, 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.openflowplugin.libraries.liblldp;
10
11 import java.net.Inet4Address;
12 import java.net.Inet6Address;
13 import java.net.InetAddress;
14 import java.net.UnknownHostException;
15 import java.util.Arrays;
16 import java.util.regex.Matcher;
17 import java.util.regex.Pattern;
18 import org.slf4j.Logger;
19 import org.slf4j.LoggerFactory;
20
21 /**
22  * Utility class containing the common utility functions needed for operating on networking data structures.
23  */
24 public abstract class NetUtils {
25     protected static final Logger LOG = LoggerFactory.getLogger(NetUtils.class);
26
27     /**
28      * Constant holding the number of bits in a byte.
29      */
30     public static final int NUM_BITS_IN_A_BYTE = 8;
31
32     /**
33      * Constant holding the number of bytes in MAC Address.
34      */
35     public static final int MAC_ADDR_LENGTH_IN_BYTES = 6;
36
37     /**
38      * Constant holding the number of words in MAC Address.
39      */
40     public static final int MAC_ADDR_LENGTH_IN_WORDS = 3;
41
42     /**
43      * Constant holding the broadcast MAC address.
44      */
45     private static final byte[] BROADCAST_MAC_ADDR = {-1, -1, -1, -1, -1, -1};
46
47     /**
48      * Converts a 4 bytes array into an integer number.
49      *
50      * @param ba
51      *            the 4 bytes long byte array
52      * @return the integer number
53      */
54     public static int byteArray4ToInt(final byte[] ba) {
55         if (ba == null || ba.length != 4) {
56             return 0;
57         }
58         return (0xff & ba[0]) << 24 | (0xff & ba[1]) << 16 | (0xff & ba[2]) << 8 | 0xff & ba[3];
59     }
60
61     /**
62      * Converts a 6 bytes array into a long number MAC addresses.
63      *
64      * @param ba
65      *            The 6 bytes long byte array.
66      * @return The long number.
67      *         Zero is returned if {@code ba} is {@code null} or
68      *         the length of it is not six.
69      */
70     public static long byteArray6ToLong(final byte[] ba) {
71         if (ba == null || ba.length != MAC_ADDR_LENGTH_IN_BYTES) {
72             return 0L;
73         }
74         long num = 0L;
75         int index = 0;
76         do {
77             num <<= NUM_BITS_IN_A_BYTE;
78             num |= 0xff & ba[index];
79             index++;
80         } while (index < MAC_ADDR_LENGTH_IN_BYTES);
81         return num;
82     }
83
84     /**
85      * Converts a long number to a 6 bytes array for MAC addresses.
86      *
87      * @param addr
88      *            The long number.
89      * @return The byte array.
90      */
91     public static byte[] longToByteArray6(long addr) {
92         byte[] mac = new byte[MAC_ADDR_LENGTH_IN_BYTES];
93         int index = MAC_ADDR_LENGTH_IN_BYTES - 1;
94         do {
95             mac[index] = (byte) addr;
96             addr >>>= NUM_BITS_IN_A_BYTE;
97             index--;
98         } while (index >= 0);
99         return mac;
100     }
101
102     /**
103      * Converts an integer number into a 4 bytes array.
104      *
105      * @param number
106      *            the integer number
107      * @return the byte array
108      */
109     public static byte[] intToByteArray4(final int number) {
110         return new byte[] { (byte) (number >> 24 & 0xff), (byte) (number >> 16 & 0xff), (byte) (number >> 8 & 0xff),
111             (byte) (number & 0xff) };
112     }
113
114     /**
115      * Converts an IP address passed as integer value into the respective InetAddress object.
116      *
117      * @param address
118      *            the IP address in integer form
119      * @return the IP address in InetAddress form
120      */
121     public static InetAddress getInetAddress(final int address) {
122         InetAddress ip = null;
123         try {
124             ip = InetAddress.getByAddress(NetUtils.intToByteArray4(address));
125         } catch (final UnknownHostException e) {
126             LOG.error("", e);
127         }
128         return ip;
129     }
130
131     /**
132      * Return the InetAddress Network Mask given the length of the prefix bit
133      * mask. The prefix bit mask indicates the contiguous leading bits that are
134      * NOT masked out. Example: A prefix bit mask length of 8 will give an
135      * InetAddress Network Mask of 255.0.0.0
136      *
137      * @param prefixMaskLength
138      *            integer representing the length of the prefix network mask
139      * @param isV6
140      *            boolean representing the IP version of the returned address
141      */
142     public static InetAddress getInetNetworkMask(final int prefixMaskLength, final boolean isV6) {
143         if (prefixMaskLength < 0 || !isV6 && prefixMaskLength > 32 || isV6 && prefixMaskLength > 128) {
144             return null;
145         }
146         byte[] v4Address = { 0, 0, 0, 0 };
147         byte[] v6Address = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
148         byte[] address = isV6 ? v6Address : v4Address;
149         int numBytes = prefixMaskLength / 8;
150         int numBits = prefixMaskLength % 8;
151         int index = 0;
152         for (; index < numBytes; index++) {
153             address[index] = (byte) 0xff;
154         }
155         if (numBits > 0) {
156             int rem = 0;
157             for (int j = 0; j < numBits; j++) {
158                 rem |= 1 << 7 - j;
159             }
160             address[index] = (byte) rem;
161         }
162
163         try {
164             return InetAddress.getByAddress(address);
165         } catch (final UnknownHostException e) {
166             LOG.error("", e);
167         }
168         return null;
169     }
170
171     /**
172      * Returns the prefix size in bits of the specified subnet mask. Example:
173      * For the subnet mask ff.ff.ff.e0 it returns 25 while for ff.00.00.00 it
174      * returns 8. If the passed subnetMask array is null, 0 is returned.
175      *
176      * @param subnetMask
177      *            the subnet mask as byte array
178      * @return the prefix length as number of bits
179      */
180     public static int getSubnetMaskLength(final byte[] subnetMask) {
181         int maskLength = 0;
182         if (subnetMask != null && (subnetMask.length == 4 || subnetMask.length == 16)) {
183             int index = 0;
184             while (index < subnetMask.length && subnetMask[index] == (byte) 0xFF) {
185                 maskLength += NetUtils.NUM_BITS_IN_A_BYTE;
186                 index++;
187             }
188             if (index != subnetMask.length) {
189                 int bits = NetUtils.NUM_BITS_IN_A_BYTE - 1;
190                 while (bits >= 0 && (subnetMask[index] & 1 << bits)  != 0) {
191                     bits--;
192                     maskLength++;
193                 }
194             }
195         }
196         return maskLength;
197     }
198
199     /**
200      * Returns the prefix size in bits of the specified subnet mask. Example:
201      * For the subnet mask 255.255.255.128 it returns 25 while for 255.0.0.0 it
202      * returns 8. If the passed subnetMask object is null, 0 is returned
203      *
204      * @param subnetMask
205      *            the subnet mask as InetAddress
206      * @return the prefix length as number of bits
207      */
208     public static int getSubnetMaskLength(final InetAddress subnetMask) {
209         return subnetMask == null ? 0 : NetUtils.getSubnetMaskLength(subnetMask.getAddress());
210     }
211
212     /**
213      * Given an IP address and a prefix network mask length, it returns the
214      * equivalent subnet prefix IP address Example: for ip = "172.28.30.254" and
215      * maskLen = 25 it will return "172.28.30.128".
216      *
217      * @param ip
218      *            the IP address in InetAddress form
219      * @param maskLen
220      *            the length of the prefix network mask
221      * @return the subnet prefix IP address in InetAddress form
222      */
223     public static InetAddress getSubnetPrefix(final InetAddress ip, final int maskLen) {
224         int bytes = maskLen / 8;
225         int bits = maskLen % 8;
226         byte modifiedByte;
227         byte[] sn = ip.getAddress();
228         if (bits > 0) {
229             modifiedByte = (byte) (sn[bytes] >> 8 - bits);
230             sn[bytes] = (byte) (modifiedByte << 8 - bits);
231             bytes++;
232         }
233         for (; bytes < sn.length; bytes++) {
234             sn[bytes] = (byte) 0;
235         }
236         try {
237             return InetAddress.getByAddress(sn);
238         } catch (final UnknownHostException e) {
239             return null;
240         }
241     }
242
243     /**
244      * Checks if the test address and mask conflicts with the filter address and mask.
245      *
246      * <p>
247      * For example:
248      * testAddress: 172.28.2.23
249      * testMask: 255.255.255.0
250      * filterAddress: 172.28.1.10
251      * testMask: 255.255.255.0
252      * do conflict
253      *
254      *  <p>
255      * testAddress: 172.28.2.23
256      * testMask: 255.255.255.0
257      * filterAddress: 172.28.1.10
258      * testMask: 255.255.0.0
259      * do not conflict
260      *
261      *  <p>
262      * Null parameters are permitted.
263      */
264     public static boolean inetAddressConflict(final InetAddress testAddress, final InetAddress filterAddress,
265             final InetAddress testMask, final InetAddress filterMask) {
266         // Sanity check
267         if (testAddress == null || filterAddress == null) {
268             return false;
269         }
270
271         // Presence check
272         if (isAny(testAddress) || isAny(filterAddress)) {
273             return false;
274         }
275
276         int testMaskLen = testMask == null ? testAddress instanceof Inet4Address ? 32 : 128 : NetUtils
277                 .getSubnetMaskLength(testMask);
278         int filterMaskLen = filterMask == null ? testAddress instanceof Inet4Address ? 32 : 128 : NetUtils
279                 .getSubnetMaskLength(filterMask);
280
281         // Mask length check. Test mask has to be more specific than filter one
282         if (testMaskLen < filterMaskLen) {
283             return true;
284         }
285
286         // Subnet Prefix on filter mask length must be the same
287         InetAddress prefix1 = getSubnetPrefix(testAddress, filterMaskLen);
288         InetAddress prefix2 = getSubnetPrefix(filterAddress, filterMaskLen);
289         return !prefix1.equals(prefix2);
290     }
291
292     /**
293      * Returns true if the passed MAC address is all zero.
294      *
295      * @param mac
296      *            the byte array representing the MAC address
297      * @return true if all MAC bytes are zero
298      */
299     public static boolean isZeroMAC(final byte[] mac) {
300         for (short i = 0; i < 6; i++) {
301             if (mac[i] != 0) {
302                 return false;
303             }
304         }
305         return true;
306     }
307
308     /**
309      * Returns true if the MAC address is the broadcast MAC address and false otherwise.
310      */
311     public static boolean isBroadcastMACAddr(final byte[] macAddress) {
312         if (macAddress.length == MAC_ADDR_LENGTH_IN_BYTES) {
313             for (int i = 0; i < 6; i++) {
314                 if (macAddress[i] != BROADCAST_MAC_ADDR[i]) {
315                     return false;
316                 }
317             }
318             return true;
319         }
320
321         return false;
322     }
323
324     /**
325      * Returns true if the MAC address is a unicast MAC address and false otherwise.
326      */
327     public static boolean isUnicastMACAddr(final byte[] macAddress) {
328         if (macAddress.length == MAC_ADDR_LENGTH_IN_BYTES) {
329             return (macAddress[0] & 1) == 0;
330         }
331         return false;
332     }
333
334     /**
335      * Returns true if the MAC address is a multicast MAC address and false
336      * otherwise. Note that this explicitly returns false for the broadcast MAC
337      * address.
338      */
339     public static boolean isMulticastMACAddr(final byte[] macAddress) {
340         if (macAddress.length == MAC_ADDR_LENGTH_IN_BYTES && !isBroadcastMACAddr(macAddress)) {
341             return (macAddress[0] & 1) != 0;
342         }
343         return false;
344     }
345
346     /**
347      * Returns true if the passed InetAddress contains all zero.
348      *
349      * @param ip
350      *            the IP address to test
351      * @return true if the address is all zero
352      */
353     public static boolean isAny(final InetAddress ip) {
354         for (byte b : ip.getAddress()) {
355             if (b != 0) {
356                 return false;
357             }
358         }
359         return true;
360     }
361
362     public static boolean fieldsConflict(final int field1, final int field2) {
363         return field1 != 0 && field2 != 0 && field1 != field2;
364     }
365
366     public static InetAddress parseInetAddress(final String addressString) {
367         InetAddress address = null;
368         try {
369             address = InetAddress.getByName(addressString);
370         } catch (final UnknownHostException e) {
371             LOG.error("", e);
372         }
373         return address;
374     }
375
376     /**
377      * Checks if the passed IP v4 address in string form is valid The address
378      * may specify a mask at the end as "/MM".
379      *
380      * @param cidr
381      *            the v4 address as A.B.C.D/MM
382      */
383     public static boolean isIPv4AddressValid(final String cidr) {
384         if (cidr == null) {
385             return false;
386         }
387
388         String[] values = cidr.split("/");
389         Pattern ipv4Pattern = Pattern
390                 .compile("(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])");
391         Matcher mm = ipv4Pattern.matcher(values[0]);
392         if (!mm.matches()) {
393             return false;
394         }
395         if (values.length >= 2) {
396             int prefix = Integer.parseInt(values[1]);
397             if (prefix < 0 || prefix > 32) {
398                 return false;
399             }
400         }
401         return true;
402     }
403
404     /**
405      * Checks if the passed IP v6 address in string form is valid The address
406      * may specify a mask at the end as "/MMM".
407      *
408      * @param cidr
409      *            the v6 address as A::1/MMM
410      */
411     public static boolean isIPv6AddressValid(final String cidr) {
412         if (cidr == null) {
413             return false;
414         }
415
416         String[] values = cidr.split("/");
417         try {
418             // when given an IP address, InetAddress.getByName validates the ip
419             // address
420             InetAddress addr = InetAddress.getByName(values[0]);
421             if (!(addr instanceof Inet6Address)) {
422                 return false;
423             }
424         } catch (final UnknownHostException ex) {
425             return false;
426         }
427
428         if (values.length >= 2) {
429             int prefix = Integer.parseInt(values[1]);
430             if (prefix < 0 || prefix > 128) {
431                 return false;
432             }
433         }
434         return true;
435     }
436
437     /**
438      * Checks if the passed IP address in string form is a valid v4 or v6
439      * address. The address may specify a mask at the end as "/MMM"
440      *
441      * @param cidr
442      *            the v4 or v6 address as IP/MMM
443      */
444     public static boolean isIPAddressValid(final String cidr) {
445         return NetUtils.isIPv4AddressValid(cidr) || NetUtils.isIPv6AddressValid(cidr);
446     }
447
448     /*
449      * Following utilities are useful when you need to compare or bit shift java
450      * primitive type variable which are inherently signed
451      */
452
453     /**
454      * Returns the unsigned value of the passed byte variable.
455      *
456      * @param value
457      *            the byte value
458      * @return the int variable containing the unsigned byte value
459      */
460     public static int getUnsignedByte(final byte value) {
461         return value & 0xFF;
462     }
463
464     /**
465      * Return the unsigned value of the passed short variable.
466      *
467      * @param value
468      *            the short value
469      * @return the int variable containing the unsigned short value
470      */
471     public static int getUnsignedShort(final short value) {
472         return value & 0xFFFF;
473     }
474
475     /**
476      * Returns the highest v4 or v6 InetAddress.
477      *
478      * @param v6
479      *            true for IPv6, false for Ipv4
480      * @return The highest IPv4 or IPv6 address
481      */
482     public static InetAddress gethighestIP(final boolean v6) {
483         try {
484             return v6 ? InetAddress.getByName("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff") : InetAddress
485                     .getByName("255.255.255.255");
486         } catch (final UnknownHostException e) {
487             return null;
488         }
489     }
490
491     /**
492      * Returns Broadcast MAC Address.
493      *
494      * @return the byte array containing  broadcast mac address
495      */
496     public static byte[] getBroadcastMACAddr() {
497         return Arrays.copyOf(BROADCAST_MAC_ADDR, BROADCAST_MAC_ADDR.length);
498     }
499 }