ISSUE:
[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 /**
19  * Utility class containing the common utility functions needed
20  * for operating on networking data structures
21  *
22  *
23  *
24  */
25 public abstract class NetUtils {
26     /**
27      * Constant holding the number of bits in a byte
28      */
29     public static final int NumBitsInAByte = 8;
30
31     /**
32      * Converts a 4 bytes array into an integer number
33      *
34      * @param ba        the 4 bytes long byte array
35      * @return      the integer number
36      */
37     public static int byteArray4ToInt(byte[] ba) {
38         if (ba == null || ba.length != 4)
39             return 0;
40         return (int) ((0xff & ba[0]) << 24 | (0xff & ba[1]) << 16
41                 | (0xff & ba[2]) << 8 | (0xff & ba[3]));
42     }
43
44     /**
45      * Converts an integer number into a 4 bytes array
46      *
47      * @param i the integer number
48      * @return  the byte array
49      */
50     public static byte[] intToByteArray4(int i) {
51         return new byte[] { (byte) ((i >> 24) & 0xff),
52                 (byte) ((i >> 16) & 0xff), (byte) ((i >> 8) & 0xff),
53                 (byte) (i & 0xff) };
54     }
55
56     /**
57      * Converts an IP address passed as integer value into the
58      * respective InetAddress object
59      *
60      * @param address   the IP address in integer form
61      * @return                  the IP address in InetAddress form
62      */
63     public static InetAddress getInetAddress(int address) {
64         InetAddress ip = null;
65         try {
66             ip = InetAddress.getByAddress(NetUtils.intToByteArray4(address));
67         } catch (UnknownHostException e) {
68             e.printStackTrace();
69         }
70         return ip;
71     }
72
73     /**
74      * Return the InetAddress Network Mask given the length of the prefix bit mask.
75      * The prefix bit mask indicates the contiguous leading bits that are NOT masked out.
76      * Example: A prefix bit mask length of 8 will give an InetAddress Network Mask of 255.0.0.0
77      *
78      * @param prefixMaskLength  integer representing the length of the prefix network mask
79      * @param isV6                              boolean representing the IP version of the returned address
80      * @return
81      */
82     public static InetAddress getInetNetworkMask(int prefixMaskLength,
83             boolean isV6) {
84         if (prefixMaskLength < 0 || (!isV6 && prefixMaskLength > 32)
85                 || (isV6 && prefixMaskLength > 128)) {
86             return null;
87         }
88         byte v4Address[] = { 0, 0, 0, 0 };
89         byte v6Address[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
90         byte address[] = (isV6) ? v6Address : v4Address;
91         int numBytes = prefixMaskLength / 8;
92         int numBits = prefixMaskLength % 8;
93         int i = 0;
94         for (; i < numBytes; i++) {
95             address[i] = (byte) 0xff;
96         }
97         if (numBits > 0) {
98             int rem = 0;
99             for (int j = 0; j < numBits; j++) {
100                 rem |= 1 << (7 - j);
101             }
102             address[i] = (byte) rem;
103         }
104
105         try {
106             return InetAddress.getByAddress(address);
107         } catch (UnknownHostException e) {
108             e.printStackTrace();
109         }
110         return null;
111     }
112
113     /**
114      * Returns the number of contiguous bits belonging to the subnet, that have to be masked out
115      * Example: A prefix network byte mask of ff.ff.ff.00 will give a subnet mask length of 8,
116      * while ff.00.00.00 will return a subnet mask length of 24.
117      * If the passed prefixMask object is null, 0 is returned
118      *
119      * @param prefixMask        the prefix mask as byte array
120      * @return                          the length of the prefix network mask
121      */
122     public static int getSubnetMaskLength(byte[] prefixMask) {
123         int maskLength = 0;
124         if (prefixMask != null) {
125             // Create bit mask
126             int intMask = 0;
127             int numBytes = prefixMask.length;
128             for (int i = 0; i < numBytes; i++) {
129                 intMask |= ((int) prefixMask[i] & 0xff) << (8 * (numBytes - 1 - i));
130             }
131
132             int bit = 1;
133             while (((intMask & bit) == 0) && (maskLength <= (numBytes * 8))) {
134                 maskLength += 1;
135                 bit = bit << 1;
136             }
137         }
138         return maskLength;
139     }
140
141     /**
142      * Returns the number of contiguous bits belonging to the subnet, that have to be masked out
143      * Example: A prefix network byte mask of ff.ff.ff.00 will give a subnet mask length of 8,
144      * while ff.00.00.00 will return a subnet mask length of 24
145      * If the passed prefixMask object is null, 0 is returned
146      *
147      * @param prefixMask        the prefix mask as InetAddress
148      * @return                          the length of the prefix network mask
149      */
150     public static int getSubnetMaskLength(InetAddress prefixMask) {
151         return (prefixMask == null) ? 0 : NetUtils
152                 .getSubnetMaskLength(prefixMask.getAddress());
153     }
154
155     /**
156      * Given an IP address and a prefix network mask length, it returns
157      * the equivalent subnet prefix IP address
158      * Example: for ip = "172.28.30.254" and maskLen = 25 it will return "172.28.30.128"
159      *
160      * @param ip                the IP address in InetAddress form
161      * @param maskLen   the length of the prefix network mask
162      * @return                  the subnet prefix IP address in InetAddress form
163      */
164     public static InetAddress getSubnetPrefix(InetAddress ip, int maskLen) {
165         int bytes = maskLen / 8;
166         int bits = maskLen % 8;
167         byte modifiedByte;
168         byte[] sn = ip.getAddress();
169         if (bits > 0) {
170             modifiedByte = (byte) (sn[bytes] >> (8 - bits));
171             sn[bytes] = (byte) (modifiedByte << (8 - bits));
172             bytes++;
173         }
174         for (; bytes < sn.length; bytes++) {
175             sn[bytes] = (byte) (0);
176         }
177         try {
178             return InetAddress.getByAddress(sn);
179         } catch (UnknownHostException e) {
180             return null;
181         }
182     }
183
184     /**
185      * Checks if the test address and mask conflicts with
186      * the filter address and mask
187      *
188      * For example:
189      * testAddress: 172.28.2.23 testMask: 255.255.255.0
190      * filtAddress: 172.28.1.10 testMask: 255.255.255.0
191      * conflict
192      *
193      * testAddress: 172.28.2.23 testMask: 255.255.255.0
194      * filtAddress: 172.28.1.10 testMask: 255.255.0.0
195      * do not conflict
196      *
197      * Null parameters are permitted
198      *
199      * @param testAddress
200      * @param filterAddress
201      * @param testMask
202      * @param filterMask
203      * @return
204      */
205     public static boolean inetAddressConflict(InetAddress testAddress,
206             InetAddress filterAddress, InetAddress testMask,
207             InetAddress filterMask) {
208         // Sanity check
209         if ((testAddress == null) || (filterAddress == null)) {
210             return false;
211         }
212
213         // Presence check
214         if (isAny(testAddress) || isAny(filterAddress)) {
215             return false;
216         }
217
218         // Derive the masks length. A null mask means a full mask
219         int testMaskLen = (testMask != null) ? NetUtils
220                 .getSubnetMaskLength(testMask.getAddress())
221                 : (testAddress instanceof Inet6Address) ? 128 : 32;
222         int filterMaskLen = (filterMask != null) ? NetUtils
223                 .getSubnetMaskLength(filterMask.getAddress())
224                 : (filterAddress instanceof Inet6Address) ? 128 : 32;
225
226         // Mask length check. Test mask has to be more generic than filter one
227         if (testMaskLen < filterMaskLen) {
228             return true;
229         }
230
231         // Subnet Prefix on filter mask length must be the same
232         InetAddress prefix1 = getSubnetPrefix(testAddress, filterMaskLen);
233         InetAddress prefix2 = getSubnetPrefix(filterAddress, filterMaskLen);
234         return (!prefix1.equals(prefix2));
235     }
236
237     /**
238      * Returns true if the passed MAC address is all zero
239      *
240      * @param mac       the byte array representing the MAC address
241      * @return          true if all MAC bytes are zero
242      */
243     public static boolean isZeroMAC(byte[] mac) {
244         for (short i = 0; i < 6; i++) {
245             if (mac[i] != 0) {
246                 return false;
247             }
248         }
249         return true;
250     }
251
252     /**
253      * Returns true if the passed InetAddress contains all zero
254      *
255      * @param ip        the IP address to test
256      * @return          true if the address is all zero
257      */
258     public static boolean isAny(InetAddress ip) {
259         for (byte b : ip.getAddress()) {
260             if (b != 0) {
261                 return false;
262             }
263         }
264         return true;
265     }
266
267     public static boolean fieldsConflict(int field1, int field2) {
268         if ((field1 == 0) || (field2 == 0) || (field1 == field2)) {
269             return false;
270         }
271         return true;
272     }
273
274     public static InetAddress parseInetAddress(String addressString) {
275         InetAddress address = null;
276         try {
277             address = InetAddress.getByName(addressString);
278         } catch (UnknownHostException e) {
279             e.printStackTrace();
280         }
281         return address;
282     }
283
284     /**
285      * Checks if the passed IP v4 address in string form is valid
286      * The address may specify a mask at the end as "/MM"
287      *
288      * @param cidr the v4 address as A.B.C.D/MM
289      * @return
290      */
291     public static boolean isIPv4AddressValid(String cidr) {
292         if (cidr == null)
293             return false;
294
295         String values[] = cidr.split("/");
296         Pattern ipv4Pattern = Pattern
297                 .compile("(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])");
298         Matcher mm = ipv4Pattern.matcher(values[0]);
299         if (!mm.matches()) {
300             return false;
301         }
302         if (values.length >= 2) {
303             int prefix = Integer.valueOf(values[1]);
304             if ((prefix < 0) || (prefix > 32)) {
305                 return false;
306             }
307         }
308         return true;
309     }
310
311     /**
312      * Checks if the passed IP v6 address in string form is valid
313      * The address may specify a mask at the end as "/MMM"
314      *
315      * @param cidr the v6 address as A::1/MMM
316      * @return
317      */
318     public static boolean isIPv6AddressValid(String cidr) {
319         if (cidr == null)
320             return false;
321
322         String values[] = cidr.split("/");
323         try {
324             //when given an IP address, InetAddress.getByName validates the ip address
325             InetAddress addr = InetAddress.getByName(values[0]);
326             if (!(addr instanceof Inet6Address)) {
327                 return false;
328             }
329         } catch (UnknownHostException ex) {
330             return false;
331         }
332
333         if (values.length >= 2) {
334             int prefix = Integer.valueOf(values[1]);
335             if ((prefix < 0) || (prefix > 128)) {
336                 return false;
337             }
338         }
339         return true;
340     }
341     
342     /*
343      * Following utilities are useful when you need to 
344      * compare or bit shift java primitive type variable
345      * which are inerently signed
346      */
347     /**
348      * Returns the unsigned value of the passed byte variable
349      * 
350      * @param b the byte value
351      * @return the int variable containing the unsigned byte value
352      */
353     public static int getUnsignedByte(byte b) {
354                 return (b > 0)? (int)b : ((int)b & 0x7F | 0x80);
355         }
356         
357     /**
358      * Return the unsigned value of the passed short variable
359      * 
360      * @param s the short value
361      * @return the int variable containing the unsigned short value
362      */
363         public static int getUnsignedShort(short s) {
364                 return (s > 0)? (int)s : ((int)s & 0x7FFF | 0x8000);
365         }
366 }