Checkstyle enforcer
[controller.git] / opendaylight / sal / api / src / main / java / org / opendaylight / controller / sal / utils / NetUtils.java
1
2 /*
3  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
4  *
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
8  */
9
10 package org.opendaylight.controller.sal.utils;
11
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;
17
18 import org.slf4j.Logger;
19 import org.slf4j.LoggerFactory;
20
21 /**
22  * Utility class containing the common utility functions needed
23  * for operating on networking data structures
24  *
25  *
26  *
27  */
28 public abstract class NetUtils {
29     protected static final Logger logger = LoggerFactory
30     .getLogger(NetUtils.class);
31     /**
32      * Constant holding the number of bits in a byte
33      */
34     public static final int NumBitsInAByte = 8;
35
36     /**
37      * Converts a 4 bytes array into an integer number
38      *
39      * @param ba    the 4 bytes long byte array
40      * @return      the integer number
41      */
42     public static int byteArray4ToInt(byte[] ba) {
43         if (ba == null || ba.length != 4) {
44             return 0;
45         }
46         return (0xff & ba[0]) << 24 | (0xff & ba[1]) << 16
47                 | (0xff & ba[2]) << 8 | (0xff & ba[3]);
48     }
49
50     /**
51      * Converts an integer number into a 4 bytes array
52      *
53      * @param i the integer number
54      * @return  the byte array
55      */
56     public static byte[] intToByteArray4(int i) {
57         return new byte[] { (byte) ((i >> 24) & 0xff),
58                 (byte) ((i >> 16) & 0xff), (byte) ((i >> 8) & 0xff),
59                 (byte) (i & 0xff) };
60     }
61
62     /**
63      * Converts an IP address passed as integer value into the
64      * respective InetAddress object
65      *
66      * @param address   the IP address in integer form
67      * @return          the IP address in InetAddress form
68      */
69     public static InetAddress getInetAddress(int address) {
70         InetAddress ip = null;
71         try {
72             ip = InetAddress.getByAddress(NetUtils.intToByteArray4(address));
73         } catch (UnknownHostException e) {
74             logger.error("",e);
75         }
76         return ip;
77     }
78
79     /**
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
83      *
84      * @param prefixMaskLength  integer representing the length of the prefix network mask
85      * @param isV6              boolean representing the IP version of the returned address
86      * @return
87      */
88     public static InetAddress getInetNetworkMask(int prefixMaskLength,
89             boolean isV6) {
90         if (prefixMaskLength < 0 || (!isV6 && prefixMaskLength > 32)
91                 || (isV6 && prefixMaskLength > 128)) {
92             return null;
93         }
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;
99         int i = 0;
100         for (; i < numBytes; i++) {
101             address[i] = (byte) 0xff;
102         }
103         if (numBits > 0) {
104             int rem = 0;
105             for (int j = 0; j < numBits; j++) {
106                 rem |= 1 << (7 - j);
107             }
108             address[i] = (byte) rem;
109         }
110
111         try {
112             return InetAddress.getByAddress(address);
113         } catch (UnknownHostException e) {
114             logger.error("",e);
115         }
116         return null;
117     }
118
119     /**
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
124      *
125      * @param prefixMask    the prefix mask as byte array
126      * @return              the length of the prefix network mask
127      */
128     public static int getSubnetMaskLength(byte[] prefixMask) {
129         int maskLength = 0;
130         if (prefixMask != null) {
131             // Create bit mask
132             int intMask = 0;
133             int numBytes = prefixMask.length;
134             for (int i = 0; i < numBytes; i++) {
135                 intMask |= (prefixMask[i] & 0xff) << (8 * (numBytes - 1 - i));
136             }
137
138             int bit = 1;
139             while (((intMask & bit) == 0) && (maskLength <= (numBytes * 8))) {
140                 maskLength += 1;
141                 bit = bit << 1;
142             }
143         }
144         return maskLength;
145     }
146
147     /**
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
152      *
153      * @param prefixMask    the prefix mask as InetAddress
154      * @return              the length of the prefix network mask
155      */
156     public static int getSubnetMaskLength(InetAddress prefixMask) {
157         return (prefixMask == null) ? 0 : NetUtils
158                 .getSubnetMaskLength(prefixMask.getAddress());
159     }
160
161     /**
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"
165      *
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
169      */
170     public static InetAddress getSubnetPrefix(InetAddress ip, int maskLen) {
171         int bytes = maskLen / 8;
172         int bits = maskLen % 8;
173         byte modifiedByte;
174         byte[] sn = ip.getAddress();
175         if (bits > 0) {
176             modifiedByte = (byte) (sn[bytes] >> (8 - bits));
177             sn[bytes] = (byte) (modifiedByte << (8 - bits));
178             bytes++;
179         }
180         for (; bytes < sn.length; bytes++) {
181             sn[bytes] = (byte) (0);
182         }
183         try {
184             return InetAddress.getByAddress(sn);
185         } catch (UnknownHostException e) {
186             return null;
187         }
188     }
189
190     /**
191      * Checks if the test address and mask conflicts with
192      * the filter address and mask
193      *
194      * For example:
195      * testAddress: 172.28.2.23 testMask: 255.255.255.0
196      * filtAddress: 172.28.1.10 testMask: 255.255.255.0
197      * conflict
198      *
199      * testAddress: 172.28.2.23 testMask: 255.255.255.0
200      * filtAddress: 172.28.1.10 testMask: 255.255.0.0
201      * do not conflict
202      *
203      * Null parameters are permitted
204      *
205      * @param testAddress
206      * @param filterAddress
207      * @param testMask
208      * @param filterMask
209      * @return
210      */
211     public static boolean inetAddressConflict(InetAddress testAddress,
212             InetAddress filterAddress, InetAddress testMask,
213             InetAddress filterMask) {
214         // Sanity check
215         if ((testAddress == null) || (filterAddress == null)) {
216             return false;
217         }
218
219         // Presence check
220         if (isAny(testAddress) || isAny(filterAddress)) {
221             return false;
222         }
223
224         int testMaskLen = (testMask != null) ? NetUtils.getSubnetMaskLength(testMask.getAddress()) : 0;
225         int filterMaskLen = (filterMask != null) ? NetUtils.getSubnetMaskLength(filterMask.getAddress()) : 0;
226
227         int testPrefixLen = (testAddress instanceof Inet6Address) ? (128 - testMaskLen) : (32 - testMaskLen);
228         int filterPrefixLen = (filterAddress instanceof Inet6Address) ? (128 - filterMaskLen) : (32 - filterMaskLen);
229
230         // Mask length check. Test mask has to be more specific than filter one
231         if (testPrefixLen < filterPrefixLen) {
232             return true;
233         }
234
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));
239     }
240
241     /**
242      * Returns true if the passed MAC address is all zero
243      *
244      * @param mac   the byte array representing the MAC address
245      * @return      true if all MAC bytes are zero
246      */
247     public static boolean isZeroMAC(byte[] mac) {
248         for (short i = 0; i < 6; i++) {
249             if (mac[i] != 0) {
250                 return false;
251             }
252         }
253         return true;
254     }
255
256     /**
257      * Returns true if the passed InetAddress contains all zero
258      *
259      * @param ip    the IP address to test
260      * @return      true if the address is all zero
261      */
262     public static boolean isAny(InetAddress ip) {
263         for (byte b : ip.getAddress()) {
264             if (b != 0) {
265                 return false;
266             }
267         }
268         return true;
269     }
270
271     public static boolean fieldsConflict(int field1, int field2) {
272         if ((field1 == 0) || (field2 == 0) || (field1 == field2)) {
273             return false;
274         }
275         return true;
276     }
277
278     public static InetAddress parseInetAddress(String addressString) {
279         InetAddress address = null;
280         try {
281             address = InetAddress.getByName(addressString);
282         } catch (UnknownHostException e) {
283             logger.error("",e);
284         }
285         return address;
286     }
287
288     /**
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"
291      *
292      * @param cidr the v4 address as A.B.C.D/MM
293      * @return
294      */
295     public static boolean isIPv4AddressValid(String cidr) {
296         if (cidr == null) {
297             return false;
298         }
299
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]);
304         if (!mm.matches()) {
305             return false;
306         }
307         if (values.length >= 2) {
308             int prefix = Integer.valueOf(values[1]);
309             if ((prefix < 0) || (prefix > 32)) {
310                 return false;
311             }
312         }
313         return true;
314     }
315
316     /**
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"
319      *
320      * @param cidr the v6 address as A::1/MMM
321      * @return
322      */
323     public static boolean isIPv6AddressValid(String cidr) {
324         if (cidr == null) {
325             return false;
326         }
327
328         String values[] = cidr.split("/");
329         try {
330             //when given an IP address, InetAddress.getByName validates the ip address
331             InetAddress addr = InetAddress.getByName(values[0]);
332             if (!(addr instanceof Inet6Address)) {
333                 return false;
334             }
335         } catch (UnknownHostException ex) {
336             return false;
337         }
338
339         if (values.length >= 2) {
340             int prefix = Integer.valueOf(values[1]);
341             if ((prefix < 0) || (prefix > 128)) {
342                 return false;
343             }
344         }
345         return true;
346     }
347
348     /**
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"
351      *
352      * @param cidr
353      *            the v4 or v6 address as IP/MMM
354      * @return
355      */
356     public static boolean isIPAddressValid(String cidr) {
357         return NetUtils.isIPv4AddressValid(cidr)
358                 || NetUtils.isIPv6AddressValid(cidr);
359     }
360
361     /*
362      * Following utilities are useful when you need to
363      * compare or bit shift java primitive type variable
364      * which are inerently signed
365      */
366     /**
367      * Returns the unsigned value of the passed byte variable
368      *
369      * @param b the byte value
370      * @return the int variable containing the unsigned byte value
371      */
372     public static int getUnsignedByte(byte b) {
373         return (b > 0)? (int)b : (b & 0x7F | 0x80);
374     }
375
376     /**
377      * Return the unsigned value of the passed short variable
378      *
379      * @param s the short value
380      * @return the int variable containing the unsigned short value
381      */
382     public static int getUnsignedShort(short s) {
383         return (s > 0)? (int)s : (s & 0x7FFF | 0x8000);
384     }
385 }