2 * Copyright (c) 2013-2014 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.controller.sal.utils;
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;
19 import org.slf4j.Logger;
20 import org.slf4j.LoggerFactory;
23 * Utility class containing the common utility functions needed for operating on
24 * networking data structures
27 public abstract class NetUtils {
28 protected static final Logger logger = LoggerFactory.getLogger(NetUtils.class);
30 * Constant holding the number of bits in a byte
32 public static final int NumBitsInAByte = 8;
35 * Constant holding the number of bytes in MAC Address
37 public static final int MACAddrLengthInBytes = 6;
40 * Constant holding the number of words in MAC Address
42 public static final int MACAddrLengthInWords = 3;
45 * Constant holding the broadcast MAC address
47 private static final byte[] BroadcastMACAddr = {-1, -1, -1, -1, -1, -1};
50 * Converts a 4 bytes array into an integer number
53 * the 4 bytes long byte array
54 * @return the integer number
56 public static int byteArray4ToInt(byte[] ba) {
57 if (ba == null || ba.length != 4) {
60 return (0xff & ba[0]) << 24 | (0xff & ba[1]) << 16 | (0xff & ba[2]) << 8 | (0xff & ba[3]);
64 * Converts a 6 bytes array into a long number MAC addresses.
67 * The 6 bytes long byte array.
68 * @return The long number.
69 * Zero is returned if {@code ba} is {@code null} or
70 * the length of it is not six.
72 public static long byteArray6ToLong(byte[] ba) {
73 if (ba == null || ba.length != MACAddrLengthInBytes) {
79 num <<= NumBitsInAByte;
82 } while (i < MACAddrLengthInBytes);
87 * Converts a long number to a 6 bytes array for MAC addresses.
91 * @return The byte array.
93 public static byte[] longToByteArray6(long addr){
94 byte[] mac = new byte[MACAddrLengthInBytes];
95 int i = MACAddrLengthInBytes - 1;
98 addr >>>= NumBitsInAByte;
105 * Converts an integer number into a 4 bytes array
109 * @return the byte array
111 public static byte[] intToByteArray4(int i) {
112 return new byte[] { (byte) ((i >> 24) & 0xff), (byte) ((i >> 16) & 0xff), (byte) ((i >> 8) & 0xff),
117 * Converts an IP address passed as integer value into the respective
121 * the IP address in integer form
122 * @return the IP address in InetAddress form
124 public static InetAddress getInetAddress(int address) {
125 InetAddress ip = null;
127 ip = InetAddress.getByAddress(NetUtils.intToByteArray4(address));
128 } catch (UnknownHostException e) {
135 * Return the InetAddress Network Mask given the length of the prefix bit
136 * mask. The prefix bit mask indicates the contiguous leading bits that are
137 * NOT masked out. Example: A prefix bit mask length of 8 will give an
138 * InetAddress Network Mask of 255.0.0.0
140 * @param prefixMaskLength
141 * integer representing the length of the prefix network mask
143 * boolean representing the IP version of the returned address
146 public static InetAddress getInetNetworkMask(int prefixMaskLength, boolean isV6) {
147 if (prefixMaskLength < 0 || (!isV6 && prefixMaskLength > 32) || (isV6 && prefixMaskLength > 128)) {
150 byte v4Address[] = { 0, 0, 0, 0 };
151 byte v6Address[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
152 byte address[] = (isV6) ? v6Address : v4Address;
153 int numBytes = prefixMaskLength / 8;
154 int numBits = prefixMaskLength % 8;
156 for (; i < numBytes; i++) {
157 address[i] = (byte) 0xff;
161 for (int j = 0; j < numBits; j++) {
164 address[i] = (byte) rem;
168 return InetAddress.getByAddress(address);
169 } catch (UnknownHostException e) {
176 * Returns the prefix size in bits of the specified subnet mask. Example:
177 * For the subnet mask ff.ff.ff.e0 it returns 25 while for ff.00.00.00 it
178 * returns 8. If the passed subnetMask array is null, 0 is returned.
181 * the subnet mask as byte array
182 * @return the prefix length as number of bits
184 public static int getSubnetMaskLength(byte[] subnetMask) {
186 if (subnetMask != null && (subnetMask.length == 4 || subnetMask.length == 16)) {
188 while (index < subnetMask.length && subnetMask[index] == (byte) 0xFF) {
189 maskLength += NetUtils.NumBitsInAByte;
192 if (index != subnetMask.length) {
193 int bits = NetUtils.NumBitsInAByte - 1;
194 while (bits >= 0 && (subnetMask[index] & 1 << bits) != 0) {
204 * Returns the prefix size in bits of the specified subnet mask. Example:
205 * For the subnet mask 255.255.255.128 it returns 25 while for 255.0.0.0 it
206 * returns 8. If the passed subnetMask object is null, 0 is returned
209 * the subnet mask as InetAddress
210 * @return the prefix length as number of bits
212 public static int getSubnetMaskLength(InetAddress subnetMask) {
213 return subnetMask == null ? 0 : NetUtils.getSubnetMaskLength(subnetMask.getAddress());
217 * Given an IP address and a prefix network mask length, it returns the
218 * equivalent subnet prefix IP address Example: for ip = "172.28.30.254" and
219 * maskLen = 25 it will return "172.28.30.128"
222 * the IP address in InetAddress form
224 * the length of the prefix network mask
225 * @return the subnet prefix IP address in InetAddress form
227 public static InetAddress getSubnetPrefix(InetAddress ip, int maskLen) {
228 int bytes = maskLen / 8;
229 int bits = maskLen % 8;
231 byte[] sn = ip.getAddress();
233 modifiedByte = (byte) (sn[bytes] >> (8 - bits));
234 sn[bytes] = (byte) (modifiedByte << (8 - bits));
237 for (; bytes < sn.length; bytes++) {
238 sn[bytes] = (byte) (0);
241 return InetAddress.getByAddress(sn);
242 } catch (UnknownHostException e) {
248 * Checks if the test address and mask conflicts with the filter address and
252 * testAddress: 172.28.2.23
253 * testMask: 255.255.255.0
254 * filterAddress: 172.28.1.10
255 * testMask: 255.255.255.0
258 * testAddress: 172.28.2.23
259 * testMask: 255.255.255.0
260 * filterAddress: 172.28.1.10
261 * testMask: 255.255.0.0
264 * Null parameters are permitted
267 * @param filterAddress
272 public static boolean inetAddressConflict(InetAddress testAddress, InetAddress filterAddress, InetAddress testMask,
273 InetAddress filterMask) {
275 if ((testAddress == null) || (filterAddress == null)) {
280 if (isAny(testAddress) || isAny(filterAddress)) {
284 int testMaskLen = (testMask == null) ? ((testAddress instanceof Inet4Address) ? 32 : 128) : NetUtils
285 .getSubnetMaskLength(testMask);
286 int filterMaskLen = (filterMask == null) ? ((testAddress instanceof Inet4Address) ? 32 : 128) : NetUtils
287 .getSubnetMaskLength(filterMask);
289 // Mask length check. Test mask has to be more specific than filter one
290 if (testMaskLen < filterMaskLen) {
294 // Subnet Prefix on filter mask length must be the same
295 InetAddress prefix1 = getSubnetPrefix(testAddress, filterMaskLen);
296 InetAddress prefix2 = getSubnetPrefix(filterAddress, filterMaskLen);
297 return (!prefix1.equals(prefix2));
301 * Returns true if the passed MAC address is all zero
304 * the byte array representing the MAC address
305 * @return true if all MAC bytes are zero
307 public static boolean isZeroMAC(byte[] mac) {
308 for (short i = 0; i < 6; i++) {
317 * Returns true if the MAC address is the broadcast MAC address and false
323 public static boolean isBroadcastMACAddr(byte[] MACAddress) {
324 if (MACAddress.length == MACAddrLengthInBytes) {
325 for (int i = 0; i < 6; i++) {
326 if (MACAddress[i] != BroadcastMACAddr[i]) {
336 * Returns true if the MAC address is a unicast MAC address and false
342 public static boolean isUnicastMACAddr(byte[] MACAddress) {
343 if (MACAddress.length == MACAddrLengthInBytes) {
344 return (MACAddress[0] & 1) == 0;
350 * Returns true if the MAC address is a multicast MAC address and false
351 * otherwise. Note that this explicitly returns false for the broadcast MAC
357 public static boolean isMulticastMACAddr(byte[] MACAddress) {
358 if (MACAddress.length == MACAddrLengthInBytes && !isBroadcastMACAddr(MACAddress)) {
359 return (MACAddress[0] & 1) != 0;
365 * Returns true if the passed InetAddress contains all zero
368 * the IP address to test
369 * @return true if the address is all zero
371 public static boolean isAny(InetAddress ip) {
372 for (byte b : ip.getAddress()) {
380 public static boolean fieldsConflict(int field1, int field2) {
381 if ((field1 == 0) || (field2 == 0) || (field1 == field2)) {
387 public static InetAddress parseInetAddress(String addressString) {
388 InetAddress address = null;
390 address = InetAddress.getByName(addressString);
391 } catch (UnknownHostException e) {
398 * Checks if the passed IP v4 address in string form is valid The address
399 * may specify a mask at the end as "/MM"
402 * the v4 address as A.B.C.D/MM
405 public static boolean isIPv4AddressValid(String cidr) {
410 String values[] = cidr.split("/");
411 Pattern ipv4Pattern = Pattern
412 .compile("(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])");
413 Matcher mm = ipv4Pattern.matcher(values[0]);
417 if (values.length >= 2) {
418 int prefix = Integer.valueOf(values[1]);
419 if ((prefix < 0) || (prefix > 32)) {
427 * Checks if the passed IP v6 address in string form is valid The address
428 * may specify a mask at the end as "/MMM"
431 * the v6 address as A::1/MMM
434 public static boolean isIPv6AddressValid(String cidr) {
439 String values[] = cidr.split("/");
441 // when given an IP address, InetAddress.getByName validates the ip
443 InetAddress addr = InetAddress.getByName(values[0]);
444 if (!(addr instanceof Inet6Address)) {
447 } catch (UnknownHostException ex) {
451 if (values.length >= 2) {
452 int prefix = Integer.valueOf(values[1]);
453 if ((prefix < 0) || (prefix > 128)) {
461 * Checks if the passed IP address in string form is a valid v4 or v6
462 * address. The address may specify a mask at the end as "/MMM"
465 * the v4 or v6 address as IP/MMM
468 public static boolean isIPAddressValid(String cidr) {
469 return NetUtils.isIPv4AddressValid(cidr) || NetUtils.isIPv6AddressValid(cidr);
473 * Following utilities are useful when you need to compare or bit shift java
474 * primitive type variable which are inherently signed
477 * Returns the unsigned value of the passed byte variable
481 * @return the int variable containing the unsigned byte value
483 public static int getUnsignedByte(byte b) {
488 * Return the unsigned value of the passed short variable
492 * @return the int variable containing the unsigned short value
494 public static int getUnsignedShort(short s) {
499 * Returns the highest v4 or v6 InetAddress
502 * true for IPv6, false for Ipv4
503 * @return The highest IPv4 or IPv6 address
505 public static InetAddress gethighestIP(boolean v6) {
507 return (v6) ? InetAddress.getByName("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff") : InetAddress
508 .getByName("255.255.255.255");
509 } catch (UnknownHostException e) {
515 * Returns Broadcast MAC Address
517 * @return the byte array containing broadcast mac address
519 public static byte[] getBroadcastMACAddr() {
520 return Arrays.copyOf(BroadcastMACAddr, BroadcastMACAddr.length);