2 * Copyright (c) 2013, 2015 Cisco Systems, Inc. and others. All rights reserved.
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
9 package org.opendaylight.openflowplugin.libraries.liblldp;
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;
22 * Utility class containing the common utility functions needed for operating on networking data structures.
24 public abstract class NetUtils {
25 private static final Logger LOG = LoggerFactory.getLogger(NetUtils.class);
28 * Constant holding the number of bits in a byte.
30 public static final int NUM_BITS_IN_A_BYTE = 8;
33 * Constant holding the number of bytes in MAC Address.
35 public static final int MAC_ADDR_LENGTH_IN_BYTES = 6;
38 * Constant holding the number of words in MAC Address.
40 public static final int MAC_ADDR_LENGTH_IN_WORDS = 3;
43 * Constant holding the broadcast MAC address.
45 private static final byte[] BROADCAST_MAC_ADDR = {-1, -1, -1, -1, -1, -1};
48 * Converts a 4 bytes array into an integer number.
51 * the 4 bytes long byte array
52 * @return the integer number
54 public static int byteArray4ToInt(final byte[] ba) {
55 if (ba == null || ba.length != 4) {
58 return (0xff & ba[0]) << 24 | (0xff & ba[1]) << 16 | (0xff & ba[2]) << 8 | 0xff & ba[3];
62 * Converts a 6 bytes array into a long number MAC addresses.
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.
70 public static long byteArray6ToLong(final byte[] ba) {
71 if (ba == null || ba.length != MAC_ADDR_LENGTH_IN_BYTES) {
77 num <<= NUM_BITS_IN_A_BYTE;
78 num |= 0xff & ba[index];
80 } while (index < MAC_ADDR_LENGTH_IN_BYTES);
85 * Converts a long number to a 6 bytes array for MAC addresses.
89 * @return The byte array.
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;
95 mac[index] = (byte) addr;
96 addr >>>= NUM_BITS_IN_A_BYTE;
103 * Converts an integer number into a 4 bytes array.
107 * @return the byte array
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) };
115 * Converts an IP address passed as integer value into the respective InetAddress object.
118 * the IP address in integer form
119 * @return the IP address in InetAddress form
121 public static InetAddress getInetAddress(final int address) {
122 InetAddress ip = null;
124 ip = InetAddress.getByAddress(NetUtils.intToByteArray4(address));
125 } catch (final UnknownHostException e) {
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
137 * @param prefixMaskLength
138 * integer representing the length of the prefix network mask
140 * boolean representing the IP version of the returned address
142 public static InetAddress getInetNetworkMask(final int prefixMaskLength, final boolean isV6) {
143 if (prefixMaskLength < 0 || !isV6 && prefixMaskLength > 32 || isV6 && prefixMaskLength > 128) {
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;
152 for (; index < numBytes; index++) {
153 address[index] = (byte) 0xff;
157 for (int j = 0; j < numBits; j++) {
160 address[index] = (byte) rem;
164 return InetAddress.getByAddress(address);
165 } catch (final UnknownHostException e) {
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.
177 * the subnet mask as byte array
178 * @return the prefix length as number of bits
180 public static int getSubnetMaskLength(final byte[] subnetMask) {
182 if (subnetMask != null && (subnetMask.length == 4 || subnetMask.length == 16)) {
184 while (index < subnetMask.length && subnetMask[index] == (byte) 0xFF) {
185 maskLength += NetUtils.NUM_BITS_IN_A_BYTE;
188 if (index != subnetMask.length) {
189 int bits = NetUtils.NUM_BITS_IN_A_BYTE - 1;
190 while (bits >= 0 && (subnetMask[index] & 1 << bits) != 0) {
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
205 * the subnet mask as InetAddress
206 * @return the prefix length as number of bits
208 public static int getSubnetMaskLength(final InetAddress subnetMask) {
209 return subnetMask == null ? 0 : NetUtils.getSubnetMaskLength(subnetMask.getAddress());
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".
218 * the IP address in InetAddress form
220 * the length of the prefix network mask
221 * @return the subnet prefix IP address in InetAddress form
223 public static InetAddress getSubnetPrefix(final InetAddress ip, final int maskLen) {
224 int bytes = maskLen / 8;
225 int bits = maskLen % 8;
227 byte[] sn = ip.getAddress();
229 modifiedByte = (byte) (sn[bytes] >> 8 - bits);
230 sn[bytes] = (byte) (modifiedByte << 8 - bits);
233 for (; bytes < sn.length; bytes++) {
234 sn[bytes] = (byte) 0;
237 return InetAddress.getByAddress(sn);
238 } catch (final UnknownHostException e) {
244 * Checks if the test address and mask conflicts with the filter address and mask.
248 * testAddress: 172.28.2.23
249 * testMask: 255.255.255.0
250 * filterAddress: 172.28.1.10
251 * testMask: 255.255.255.0
255 * testAddress: 172.28.2.23
256 * testMask: 255.255.255.0
257 * filterAddress: 172.28.1.10
258 * testMask: 255.255.0.0
262 * Null parameters are permitted.
264 public static boolean inetAddressConflict(final InetAddress testAddress, final InetAddress filterAddress,
265 final InetAddress testMask, final InetAddress filterMask) {
267 if (testAddress == null || filterAddress == null) {
272 if (isAny(testAddress) || isAny(filterAddress)) {
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);
281 // Mask length check. Test mask has to be more specific than filter one
282 if (testMaskLen < filterMaskLen) {
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);
293 * Returns true if the passed MAC address is all zero.
296 * the byte array representing the MAC address
297 * @return true if all MAC bytes are zero
299 public static boolean isZeroMAC(final byte[] mac) {
300 for (short i = 0; i < 6; i++) {
309 * Returns true if the MAC address is the broadcast MAC address and false otherwise.
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]) {
325 * Returns true if the MAC address is a unicast MAC address and false otherwise.
327 public static boolean isUnicastMACAddr(final byte[] macAddress) {
328 if (macAddress.length == MAC_ADDR_LENGTH_IN_BYTES) {
329 return (macAddress[0] & 1) == 0;
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
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;
347 * Returns true if the passed InetAddress contains all zero.
350 * the IP address to test
351 * @return true if the address is all zero
353 public static boolean isAny(final InetAddress ip) {
354 for (byte b : ip.getAddress()) {
362 public static boolean fieldsConflict(final int field1, final int field2) {
363 return field1 != 0 && field2 != 0 && field1 != field2;
366 public static InetAddress parseInetAddress(final String addressString) {
367 InetAddress address = null;
369 address = InetAddress.getByName(addressString);
370 } catch (final UnknownHostException e) {
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".
381 * the v4 address as A.B.C.D/MM
383 public static boolean isIPv4AddressValid(final String cidr) {
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]);
395 if (values.length >= 2) {
396 int prefix = Integer.parseInt(values[1]);
397 if (prefix < 0 || prefix > 32) {
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".
409 * the v6 address as A::1/MMM
411 public static boolean isIPv6AddressValid(final String cidr) {
416 String[] values = cidr.split("/");
418 // when given an IP address, InetAddress.getByName validates the ip
420 InetAddress addr = InetAddress.getByName(values[0]);
421 if (!(addr instanceof Inet6Address)) {
424 } catch (final UnknownHostException ex) {
428 if (values.length >= 2) {
429 int prefix = Integer.parseInt(values[1]);
430 if (prefix < 0 || prefix > 128) {
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"
442 * the v4 or v6 address as IP/MMM
444 public static boolean isIPAddressValid(final String cidr) {
445 return NetUtils.isIPv4AddressValid(cidr) || NetUtils.isIPv6AddressValid(cidr);
449 * Following utilities are useful when you need to compare or bit shift java
450 * primitive type variable which are inherently signed
454 * Returns the unsigned value of the passed byte variable.
458 * @return the int variable containing the unsigned byte value
460 public static int getUnsignedByte(final byte value) {
465 * Return the unsigned value of the passed short variable.
469 * @return the int variable containing the unsigned short value
471 public static int getUnsignedShort(final short value) {
472 return value & 0xFFFF;
476 * Returns the highest v4 or v6 InetAddress.
479 * true for IPv6, false for Ipv4
480 * @return The highest IPv4 or IPv6 address
482 public static InetAddress gethighestIP(final boolean v6) {
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) {
492 * Returns Broadcast MAC Address.
494 * @return the byte array containing broadcast mac address
496 public static byte[] getBroadcastMACAddr() {
497 return Arrays.copyOf(BROADCAST_MAC_ADDR, BROADCAST_MAC_ADDR.length);