3 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
5 * This program and the accompanying materials are made available under the
6 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
7 * and is available at http://www.eclipse.org/legal/epl-v10.html
10 package org.opendaylight.controller.sal.utils;
12 import java.net.Inet6Address;
13 import java.net.InetAddress;
14 import java.net.UnknownHostException;
15 import java.util.regex.Matcher;
16 import java.util.regex.Pattern;
18 import org.slf4j.Logger;
19 import org.slf4j.LoggerFactory;
22 * Utility class containing the common utility functions needed
23 * for operating on networking data structures
28 public abstract class NetUtils {
29 protected static final Logger logger = LoggerFactory
30 .getLogger(NetUtils.class);
32 * Constant holding the number of bits in a byte
34 public static final int NumBitsInAByte = 8;
37 * Converts a 4 bytes array into an integer number
39 * @param ba the 4 bytes long byte array
40 * @return the integer number
42 public static int byteArray4ToInt(byte[] ba) {
43 if (ba == null || ba.length != 4) {
46 return (0xff & ba[0]) << 24 | (0xff & ba[1]) << 16
47 | (0xff & ba[2]) << 8 | (0xff & ba[3]);
51 * Converts an integer number into a 4 bytes array
53 * @param i the integer number
54 * @return the byte array
56 public static byte[] intToByteArray4(int i) {
57 return new byte[] { (byte) ((i >> 24) & 0xff),
58 (byte) ((i >> 16) & 0xff), (byte) ((i >> 8) & 0xff),
63 * Converts an IP address passed as integer value into the
64 * respective InetAddress object
66 * @param address the IP address in integer form
67 * @return the IP address in InetAddress form
69 public static InetAddress getInetAddress(int address) {
70 InetAddress ip = null;
72 ip = InetAddress.getByAddress(NetUtils.intToByteArray4(address));
73 } catch (UnknownHostException e) {
80 * Return the InetAddress Network Mask given the length of the prefix bit mask.
81 * The prefix bit mask indicates the contiguous leading bits that are NOT masked out.
82 * Example: A prefix bit mask length of 8 will give an InetAddress Network Mask of 255.0.0.0
84 * @param prefixMaskLength integer representing the length of the prefix network mask
85 * @param isV6 boolean representing the IP version of the returned address
88 public static InetAddress getInetNetworkMask(int prefixMaskLength,
90 if (prefixMaskLength < 0 || (!isV6 && prefixMaskLength > 32)
91 || (isV6 && prefixMaskLength > 128)) {
94 byte v4Address[] = { 0, 0, 0, 0 };
95 byte v6Address[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
96 byte address[] = (isV6) ? v6Address : v4Address;
97 int numBytes = prefixMaskLength / 8;
98 int numBits = prefixMaskLength % 8;
100 for (; i < numBytes; i++) {
101 address[i] = (byte) 0xff;
105 for (int j = 0; j < numBits; j++) {
108 address[i] = (byte) rem;
112 return InetAddress.getByAddress(address);
113 } catch (UnknownHostException e) {
120 * Returns the number of contiguous bits belonging to the subnet, that have to be masked out
121 * Example: A prefix network byte mask of ff.ff.ff.00 will give a subnet mask length of 8,
122 * while ff.00.00.00 will return a subnet mask length of 24.
123 * If the passed prefixMask object is null, 0 is returned
125 * @param prefixMask the prefix mask as byte array
126 * @return the length of the prefix network mask
128 public static int getSubnetMaskLength(byte[] prefixMask) {
130 if (prefixMask != null) {
133 int numBytes = prefixMask.length;
134 for (int i = 0; i < numBytes; i++) {
135 intMask |= (prefixMask[i] & 0xff) << (8 * (numBytes - 1 - i));
139 while (((intMask & bit) == 0) && (maskLength <= (numBytes * 8))) {
148 * Returns the number of contiguous bits belonging to the subnet, that have to be masked out
149 * Example: A prefix network byte mask of ff.ff.ff.00 will give a subnet mask length of 8,
150 * while ff.00.00.00 will return a subnet mask length of 24
151 * If the passed prefixMask object is null, 0 is returned
153 * @param prefixMask the prefix mask as InetAddress
154 * @return the length of the prefix network mask
156 public static int getSubnetMaskLength(InetAddress prefixMask) {
157 return (prefixMask == null) ? 0 : NetUtils
158 .getSubnetMaskLength(prefixMask.getAddress());
162 * Given an IP address and a prefix network mask length, it returns
163 * the equivalent subnet prefix IP address
164 * Example: for ip = "172.28.30.254" and maskLen = 25 it will return "172.28.30.128"
166 * @param ip the IP address in InetAddress form
167 * @param maskLen the length of the prefix network mask
168 * @return the subnet prefix IP address in InetAddress form
170 public static InetAddress getSubnetPrefix(InetAddress ip, int maskLen) {
171 int bytes = maskLen / 8;
172 int bits = maskLen % 8;
174 byte[] sn = ip.getAddress();
176 modifiedByte = (byte) (sn[bytes] >> (8 - bits));
177 sn[bytes] = (byte) (modifiedByte << (8 - bits));
180 for (; bytes < sn.length; bytes++) {
181 sn[bytes] = (byte) (0);
184 return InetAddress.getByAddress(sn);
185 } catch (UnknownHostException e) {
191 * Checks if the test address and mask conflicts with
192 * the filter address and mask
195 * testAddress: 172.28.2.23 testMask: 255.255.255.0
196 * filtAddress: 172.28.1.10 testMask: 255.255.255.0
199 * testAddress: 172.28.2.23 testMask: 255.255.255.0
200 * filtAddress: 172.28.1.10 testMask: 255.255.0.0
203 * Null parameters are permitted
206 * @param filterAddress
211 public static boolean inetAddressConflict(InetAddress testAddress,
212 InetAddress filterAddress, InetAddress testMask,
213 InetAddress filterMask) {
215 if ((testAddress == null) || (filterAddress == null)) {
220 if (isAny(testAddress) || isAny(filterAddress)) {
224 int testMaskLen = (testMask != null) ? NetUtils.getSubnetMaskLength(testMask.getAddress()) : 0;
225 int filterMaskLen = (filterMask != null) ? NetUtils.getSubnetMaskLength(filterMask.getAddress()) : 0;
227 int testPrefixLen = (testAddress instanceof Inet6Address) ? (128 - testMaskLen) : (32 - testMaskLen);
228 int filterPrefixLen = (filterAddress instanceof Inet6Address) ? (128 - filterMaskLen) : (32 - filterMaskLen);
230 // Mask length check. Test mask has to be more specific than filter one
231 if (testPrefixLen < filterPrefixLen) {
235 // Subnet Prefix on filter mask length must be the same
236 InetAddress prefix1 = getSubnetPrefix(testAddress, filterPrefixLen);
237 InetAddress prefix2 = getSubnetPrefix(filterAddress, filterPrefixLen);
238 return (!prefix1.equals(prefix2));
242 * Returns true if the passed MAC address is all zero
244 * @param mac the byte array representing the MAC address
245 * @return true if all MAC bytes are zero
247 public static boolean isZeroMAC(byte[] mac) {
248 for (short i = 0; i < 6; i++) {
257 * Returns true if the passed InetAddress contains all zero
259 * @param ip the IP address to test
260 * @return true if the address is all zero
262 public static boolean isAny(InetAddress ip) {
263 for (byte b : ip.getAddress()) {
271 public static boolean fieldsConflict(int field1, int field2) {
272 if ((field1 == 0) || (field2 == 0) || (field1 == field2)) {
278 public static InetAddress parseInetAddress(String addressString) {
279 InetAddress address = null;
281 address = InetAddress.getByName(addressString);
282 } catch (UnknownHostException e) {
289 * Checks if the passed IP v4 address in string form is valid
290 * The address may specify a mask at the end as "/MM"
292 * @param cidr the v4 address as A.B.C.D/MM
295 public static boolean isIPv4AddressValid(String cidr) {
300 String values[] = cidr.split("/");
301 Pattern ipv4Pattern = Pattern
302 .compile("(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])");
303 Matcher mm = ipv4Pattern.matcher(values[0]);
307 if (values.length >= 2) {
308 int prefix = Integer.valueOf(values[1]);
309 if ((prefix < 0) || (prefix > 32)) {
317 * Checks if the passed IP v6 address in string form is valid
318 * The address may specify a mask at the end as "/MMM"
320 * @param cidr the v6 address as A::1/MMM
323 public static boolean isIPv6AddressValid(String cidr) {
328 String values[] = cidr.split("/");
330 //when given an IP address, InetAddress.getByName validates the ip address
331 InetAddress addr = InetAddress.getByName(values[0]);
332 if (!(addr instanceof Inet6Address)) {
335 } catch (UnknownHostException ex) {
339 if (values.length >= 2) {
340 int prefix = Integer.valueOf(values[1]);
341 if ((prefix < 0) || (prefix > 128)) {
349 * Checks if the passed IP address in string form is a valid v4 or v6
350 * address. The address may specify a mask at the end as "/MMM"
353 * the v4 or v6 address as IP/MMM
356 public static boolean isIPAddressValid(String cidr) {
357 return NetUtils.isIPv4AddressValid(cidr)
358 || NetUtils.isIPv6AddressValid(cidr);
362 * Following utilities are useful when you need to
363 * compare or bit shift java primitive type variable
364 * which are inerently signed
367 * Returns the unsigned value of the passed byte variable
369 * @param b the byte value
370 * @return the int variable containing the unsigned byte value
372 public static int getUnsignedByte(byte b) {
373 return (b > 0)? (int)b : (b & 0x7F | 0x80);
377 * Return the unsigned value of the passed short variable
379 * @param s the short value
380 * @return the int variable containing the unsigned short value
382 public static int getUnsignedShort(short s) {
383 return (s > 0)? (int)s : (s & 0x7FFF | 0x8000);