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