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