2 * Copyright (c) 2013 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.Inet6Address;
12 import java.net.InetAddress;
13 import java.net.UnknownHostException;
14 import java.util.regex.Matcher;
15 import java.util.regex.Pattern;
17 import org.slf4j.Logger;
18 import org.slf4j.LoggerFactory;
21 * Utility class containing the common utility functions needed for operating on
22 * networking data structures
24 public abstract class NetUtils {
25 protected static final Logger logger = LoggerFactory.getLogger(NetUtils.class);
27 * Constant holding the number of bits in a byte
29 public static final int NumBitsInAByte = 8;
32 * Constant holding the number of bytes in MAC Address
34 public static final int MACAddrLengthInBytes = 6;
37 * Constant holding the number of words in MAC Address
39 public static final int MACAddrLengthInWords = 3;
42 * Converts a 4 bytes array into an integer number
45 * the 4 bytes long byte array
46 * @return the integer number
48 public static int byteArray4ToInt(byte[] ba) {
49 if (ba == null || ba.length != 4) {
52 return (0xff & ba[0]) << 24 | (0xff & ba[1]) << 16 | (0xff & ba[2]) << 8 | (0xff & ba[3]);
56 * Converts a long to 6 bytes array for mac addresses
61 public static byte[] longToByteArray6(long addr){
62 byte[] mac = new byte[6];
63 for(int i = 0; i < 6; i++){
64 mac[i] = (byte) (addr >> (i*8));
71 * Converts an integer number into a 4 bytes array
75 * @return the byte array
77 public static byte[] intToByteArray4(int i) {
78 return new byte[] { (byte) ((i >> 24) & 0xff), (byte) ((i >> 16) & 0xff), (byte) ((i >> 8) & 0xff),
83 * Converts an IP address passed as integer value into the respective
87 * the IP address in integer form
88 * @return the IP address in InetAddress form
90 public static InetAddress getInetAddress(int address) {
91 InetAddress ip = null;
93 ip = InetAddress.getByAddress(NetUtils.intToByteArray4(address));
94 } catch (UnknownHostException e) {
101 * Return the InetAddress Network Mask given the length of the prefix bit
102 * mask. The prefix bit mask indicates the contiguous leading bits that are
103 * NOT masked out. Example: A prefix bit mask length of 8 will give an
104 * InetAddress Network Mask of 255.0.0.0
106 * @param prefixMaskLength
107 * integer representing the length of the prefix network mask
109 * boolean representing the IP version of the returned address
112 public static InetAddress getInetNetworkMask(int prefixMaskLength, boolean isV6) {
113 if (prefixMaskLength < 0 || (!isV6 && prefixMaskLength > 32) || (isV6 && prefixMaskLength > 128)) {
116 byte v4Address[] = { 0, 0, 0, 0 };
117 byte v6Address[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
118 byte address[] = (isV6) ? v6Address : v4Address;
119 int numBytes = prefixMaskLength / 8;
120 int numBits = prefixMaskLength % 8;
122 for (; i < numBytes; i++) {
123 address[i] = (byte) 0xff;
127 for (int j = 0; j < numBits; j++) {
130 address[i] = (byte) rem;
134 return InetAddress.getByAddress(address);
135 } catch (UnknownHostException e) {
142 * Returns the number of contiguous bits belonging to the subnet, that have
143 * to be masked out Example: A prefix network byte mask of ff.ff.ff.00 will
144 * give a subnet mask length of 8, while ff.00.00.00 will return a subnet
145 * mask length of 24. If the passed prefixMask object is null, 0 is returned
148 * the prefix mask as byte array
149 * @return the length of the prefix network mask
151 public static int getSubnetMaskLength(byte[] prefixMask) {
153 if (prefixMask != null) {
156 int numBytes = prefixMask.length;
157 for (int i = 0; i < numBytes; i++) {
158 intMask |= (prefixMask[i] & 0xff) << (8 * (numBytes - 1 - i));
162 while (((intMask & bit) == 0) && (maskLength <= (numBytes * 8))) {
171 * Returns the number of contiguous bits belonging to the subnet, that have
172 * to be masked out Example: A prefix network byte mask of ff.ff.ff.00 will
173 * give a subnet mask length of 8, while ff.00.00.00 will return a subnet
174 * mask length of 24 If the passed prefixMask object is null, 0 is returned
177 * the prefix mask as InetAddress
178 * @return the length of the prefix network mask
180 public static int getSubnetMaskLength(InetAddress prefixMask) {
181 return (prefixMask == null) ? 0 : NetUtils.getSubnetMaskLength(prefixMask.getAddress());
185 * Given an IP address and a prefix network mask length, it returns the
186 * equivalent subnet prefix IP address Example: for ip = "172.28.30.254" and
187 * maskLen = 25 it will return "172.28.30.128"
190 * the IP address in InetAddress form
192 * the length of the prefix network mask
193 * @return the subnet prefix IP address in InetAddress form
195 public static InetAddress getSubnetPrefix(InetAddress ip, int maskLen) {
196 int bytes = maskLen / 8;
197 int bits = maskLen % 8;
199 byte[] sn = ip.getAddress();
201 modifiedByte = (byte) (sn[bytes] >> (8 - bits));
202 sn[bytes] = (byte) (modifiedByte << (8 - bits));
205 for (; bytes < sn.length; bytes++) {
206 sn[bytes] = (byte) (0);
209 return InetAddress.getByAddress(sn);
210 } catch (UnknownHostException e) {
216 * Checks if the test address and mask conflicts with the filter address and
219 * For example: testAddress: 172.28.2.23 testMask: 255.255.255.0
220 * filtAddress: 172.28.1.10 testMask: 255.255.255.0 conflict
222 * testAddress: 172.28.2.23 testMask: 255.255.255.0 filtAddress: 172.28.1.10
223 * testMask: 255.255.0.0 do not conflict
225 * Null parameters are permitted
228 * @param filterAddress
233 public static boolean inetAddressConflict(InetAddress testAddress, InetAddress filterAddress, InetAddress testMask,
234 InetAddress filterMask) {
236 if ((testAddress == null) || (filterAddress == null)) {
241 if (isAny(testAddress) || isAny(filterAddress)) {
245 int testMaskLen = (testMask != null) ? NetUtils.getSubnetMaskLength(testMask.getAddress()) : 0;
246 int filterMaskLen = (filterMask != null) ? NetUtils.getSubnetMaskLength(filterMask.getAddress()) : 0;
248 int testPrefixLen = (testAddress instanceof Inet6Address) ? (128 - testMaskLen) : (32 - testMaskLen);
249 int filterPrefixLen = (filterAddress instanceof Inet6Address) ? (128 - filterMaskLen) : (32 - filterMaskLen);
251 // Mask length check. Test mask has to be more specific than filter one
252 if (testPrefixLen < filterPrefixLen) {
256 // Subnet Prefix on filter mask length must be the same
257 InetAddress prefix1 = getSubnetPrefix(testAddress, filterPrefixLen);
258 InetAddress prefix2 = getSubnetPrefix(filterAddress, filterPrefixLen);
259 return (!prefix1.equals(prefix2));
263 * Returns true if the passed MAC address is all zero
266 * the byte array representing the MAC address
267 * @return true if all MAC bytes are zero
269 public static boolean isZeroMAC(byte[] mac) {
270 for (short i = 0; i < 6; i++) {
279 * Returns true if the passed InetAddress contains all zero
282 * the IP address to test
283 * @return true if the address is all zero
285 public static boolean isAny(InetAddress ip) {
286 for (byte b : ip.getAddress()) {
294 public static boolean fieldsConflict(int field1, int field2) {
295 if ((field1 == 0) || (field2 == 0) || (field1 == field2)) {
301 public static InetAddress parseInetAddress(String addressString) {
302 InetAddress address = null;
304 address = InetAddress.getByName(addressString);
305 } catch (UnknownHostException e) {
312 * Checks if the passed IP v4 address in string form is valid The address
313 * may specify a mask at the end as "/MM"
316 * the v4 address as A.B.C.D/MM
319 public static boolean isIPv4AddressValid(String cidr) {
324 String values[] = cidr.split("/");
325 Pattern ipv4Pattern = Pattern
326 .compile("(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])");
327 Matcher mm = ipv4Pattern.matcher(values[0]);
331 if (values.length >= 2) {
332 int prefix = Integer.valueOf(values[1]);
333 if ((prefix < 0) || (prefix > 32)) {
341 * Checks if the passed IP v6 address in string form is valid The address
342 * may specify a mask at the end as "/MMM"
345 * the v6 address as A::1/MMM
348 public static boolean isIPv6AddressValid(String cidr) {
353 String values[] = cidr.split("/");
355 // when given an IP address, InetAddress.getByName validates the ip
357 InetAddress addr = InetAddress.getByName(values[0]);
358 if (!(addr instanceof Inet6Address)) {
361 } catch (UnknownHostException ex) {
365 if (values.length >= 2) {
366 int prefix = Integer.valueOf(values[1]);
367 if ((prefix < 0) || (prefix > 128)) {
375 * Checks if the passed IP address in string form is a valid v4 or v6
376 * address. The address may specify a mask at the end as "/MMM"
379 * the v4 or v6 address as IP/MMM
382 public static boolean isIPAddressValid(String cidr) {
383 return NetUtils.isIPv4AddressValid(cidr) || NetUtils.isIPv6AddressValid(cidr);
387 * Following utilities are useful when you need to compare or bit shift java
388 * primitive type variable which are inerently signed
391 * Returns the unsigned value of the passed byte variable
395 * @return the int variable containing the unsigned byte value
397 public static int getUnsignedByte(byte b) {
398 return (b > 0) ? (int) b : (b & 0x7F | 0x80);
402 * Return the unsigned value of the passed short variable
406 * @return the int variable containing the unsigned short value
408 public static int getUnsignedShort(short s) {
409 return (s > 0) ? (int) s : (s & 0x7FFF | 0x8000);
413 * Returns the highest v4 or v6 InetAddress
416 * true for IPv6, false for Ipv4
417 * @return The highest IPv4 or IPv6 address
419 public static InetAddress gethighestIP(boolean v6) {
421 return (v6) ? InetAddress.getByName("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff") : InetAddress
422 .getByName("255.255.255.255");
423 } catch (UnknownHostException e) {