Merge "Added support to generate types from Choices and Cases added by augmentation."
[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      * Constant holding the number of bytes in MAC Address
33      */
34     public static final int MACAddrLengthInBytes = 6;
35
36     /**
37      * Constant holding the number of words in MAC Address
38      */
39     public static final int MACAddrLengthInWords = 3;
40
41     /**
42      * Converts a 4 bytes array into an integer number
43      *
44      * @param ba
45      *            the 4 bytes long byte array
46      * @return the integer number
47      */
48     public static int byteArray4ToInt(byte[] ba) {
49         if (ba == null || ba.length != 4) {
50             return 0;
51         }
52         return (0xff & ba[0]) << 24 | (0xff & ba[1]) << 16 | (0xff & ba[2]) << 8 | (0xff & ba[3]);
53     }
54
55     /**
56      * Converts a long to 6 bytes array for mac addresses
57      * @param addr
58      * @return
59      */
60
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));
65         }
66         return mac;
67     }
68
69
70     /**
71      * Converts an integer number into a 4 bytes array
72      *
73      * @param i
74      *            the integer number
75      * @return the byte array
76      */
77     public static byte[] intToByteArray4(int i) {
78         return new byte[] { (byte) ((i >> 24) & 0xff), (byte) ((i >> 16) & 0xff), (byte) ((i >> 8) & 0xff),
79                 (byte) (i & 0xff) };
80     }
81
82     /**
83      * Converts an IP address passed as integer value into the respective
84      * InetAddress object
85      *
86      * @param address
87      *            the IP address in integer form
88      * @return the IP address in InetAddress form
89      */
90     public static InetAddress getInetAddress(int address) {
91         InetAddress ip = null;
92         try {
93             ip = InetAddress.getByAddress(NetUtils.intToByteArray4(address));
94         } catch (UnknownHostException e) {
95             logger.error("", e);
96         }
97         return ip;
98     }
99
100     /**
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
105      *
106      * @param prefixMaskLength
107      *            integer representing the length of the prefix network mask
108      * @param isV6
109      *            boolean representing the IP version of the returned address
110      * @return
111      */
112     public static InetAddress getInetNetworkMask(int prefixMaskLength, boolean isV6) {
113         if (prefixMaskLength < 0 || (!isV6 && prefixMaskLength > 32) || (isV6 && prefixMaskLength > 128)) {
114             return null;
115         }
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;
121         int i = 0;
122         for (; i < numBytes; i++) {
123             address[i] = (byte) 0xff;
124         }
125         if (numBits > 0) {
126             int rem = 0;
127             for (int j = 0; j < numBits; j++) {
128                 rem |= 1 << (7 - j);
129             }
130             address[i] = (byte) rem;
131         }
132
133         try {
134             return InetAddress.getByAddress(address);
135         } catch (UnknownHostException e) {
136             logger.error("", e);
137         }
138         return null;
139     }
140
141     /**
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
146      *
147      * @param prefixMask
148      *            the prefix mask as byte array
149      * @return the length of the prefix network mask
150      */
151     public static int getSubnetMaskLength(byte[] prefixMask) {
152         int maskLength = 0;
153         if (prefixMask != null) {
154             // Create bit mask
155             int intMask = 0;
156             int numBytes = prefixMask.length;
157             for (int i = 0; i < numBytes; i++) {
158                 intMask |= (prefixMask[i] & 0xff) << (8 * (numBytes - 1 - i));
159             }
160
161             int bit = 1;
162             while (((intMask & bit) == 0) && (maskLength <= (numBytes * 8))) {
163                 maskLength += 1;
164                 bit = bit << 1;
165             }
166         }
167         return maskLength;
168     }
169
170     /**
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
175      *
176      * @param prefixMask
177      *            the prefix mask as InetAddress
178      * @return the length of the prefix network mask
179      */
180     public static int getSubnetMaskLength(InetAddress prefixMask) {
181         return (prefixMask == null) ? 0 : NetUtils.getSubnetMaskLength(prefixMask.getAddress());
182     }
183
184     /**
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"
188      *
189      * @param ip
190      *            the IP address in InetAddress form
191      * @param maskLen
192      *            the length of the prefix network mask
193      * @return the subnet prefix IP address in InetAddress form
194      */
195     public static InetAddress getSubnetPrefix(InetAddress ip, int maskLen) {
196         int bytes = maskLen / 8;
197         int bits = maskLen % 8;
198         byte modifiedByte;
199         byte[] sn = ip.getAddress();
200         if (bits > 0) {
201             modifiedByte = (byte) (sn[bytes] >> (8 - bits));
202             sn[bytes] = (byte) (modifiedByte << (8 - bits));
203             bytes++;
204         }
205         for (; bytes < sn.length; bytes++) {
206             sn[bytes] = (byte) (0);
207         }
208         try {
209             return InetAddress.getByAddress(sn);
210         } catch (UnknownHostException e) {
211             return null;
212         }
213     }
214
215     /**
216      * Checks if the test address and mask conflicts with the filter address and
217      * mask
218      *
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
221      *
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
224      *
225      * Null parameters are permitted
226      *
227      * @param testAddress
228      * @param filterAddress
229      * @param testMask
230      * @param filterMask
231      * @return
232      */
233     public static boolean inetAddressConflict(InetAddress testAddress, InetAddress filterAddress, InetAddress testMask,
234             InetAddress filterMask) {
235         // Sanity check
236         if ((testAddress == null) || (filterAddress == null)) {
237             return false;
238         }
239
240         // Presence check
241         if (isAny(testAddress) || isAny(filterAddress)) {
242             return false;
243         }
244
245         int testMaskLen = (testMask != null) ? NetUtils.getSubnetMaskLength(testMask.getAddress()) : 0;
246         int filterMaskLen = (filterMask != null) ? NetUtils.getSubnetMaskLength(filterMask.getAddress()) : 0;
247
248         int testPrefixLen = (testAddress instanceof Inet6Address) ? (128 - testMaskLen) : (32 - testMaskLen);
249         int filterPrefixLen = (filterAddress instanceof Inet6Address) ? (128 - filterMaskLen) : (32 - filterMaskLen);
250
251         // Mask length check. Test mask has to be more specific than filter one
252         if (testPrefixLen < filterPrefixLen) {
253             return true;
254         }
255
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));
260     }
261
262     /**
263      * Returns true if the passed MAC address is all zero
264      *
265      * @param mac
266      *            the byte array representing the MAC address
267      * @return true if all MAC bytes are zero
268      */
269     public static boolean isZeroMAC(byte[] mac) {
270         for (short i = 0; i < 6; i++) {
271             if (mac[i] != 0) {
272                 return false;
273             }
274         }
275         return true;
276     }
277
278     /**
279      * Returns true if the passed InetAddress contains all zero
280      *
281      * @param ip
282      *            the IP address to test
283      * @return true if the address is all zero
284      */
285     public static boolean isAny(InetAddress ip) {
286         for (byte b : ip.getAddress()) {
287             if (b != 0) {
288                 return false;
289             }
290         }
291         return true;
292     }
293
294     public static boolean fieldsConflict(int field1, int field2) {
295         if ((field1 == 0) || (field2 == 0) || (field1 == field2)) {
296             return false;
297         }
298         return true;
299     }
300
301     public static InetAddress parseInetAddress(String addressString) {
302         InetAddress address = null;
303         try {
304             address = InetAddress.getByName(addressString);
305         } catch (UnknownHostException e) {
306             logger.error("", e);
307         }
308         return address;
309     }
310
311     /**
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"
314      *
315      * @param cidr
316      *            the v4 address as A.B.C.D/MM
317      * @return
318      */
319     public static boolean isIPv4AddressValid(String cidr) {
320         if (cidr == null) {
321             return false;
322         }
323
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]);
328         if (!mm.matches()) {
329             return false;
330         }
331         if (values.length >= 2) {
332             int prefix = Integer.valueOf(values[1]);
333             if ((prefix < 0) || (prefix > 32)) {
334                 return false;
335             }
336         }
337         return true;
338     }
339
340     /**
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"
343      *
344      * @param cidr
345      *            the v6 address as A::1/MMM
346      * @return
347      */
348     public static boolean isIPv6AddressValid(String cidr) {
349         if (cidr == null) {
350             return false;
351         }
352
353         String values[] = cidr.split("/");
354         try {
355             // when given an IP address, InetAddress.getByName validates the ip
356             // address
357             InetAddress addr = InetAddress.getByName(values[0]);
358             if (!(addr instanceof Inet6Address)) {
359                 return false;
360             }
361         } catch (UnknownHostException ex) {
362             return false;
363         }
364
365         if (values.length >= 2) {
366             int prefix = Integer.valueOf(values[1]);
367             if ((prefix < 0) || (prefix > 128)) {
368                 return false;
369             }
370         }
371         return true;
372     }
373
374     /**
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"
377      *
378      * @param cidr
379      *            the v4 or v6 address as IP/MMM
380      * @return
381      */
382     public static boolean isIPAddressValid(String cidr) {
383         return NetUtils.isIPv4AddressValid(cidr) || NetUtils.isIPv6AddressValid(cidr);
384     }
385
386     /*
387      * Following utilities are useful when you need to compare or bit shift java
388      * primitive type variable which are inerently signed
389      */
390     /**
391      * Returns the unsigned value of the passed byte variable
392      *
393      * @param b
394      *            the byte value
395      * @return the int variable containing the unsigned byte value
396      */
397     public static int getUnsignedByte(byte b) {
398         return (b > 0) ? (int) b : (b & 0x7F | 0x80);
399     }
400
401     /**
402      * Return the unsigned value of the passed short variable
403      *
404      * @param s
405      *            the short value
406      * @return the int variable containing the unsigned short value
407      */
408     public static int getUnsignedShort(short s) {
409         return (s > 0) ? (int) s : (s & 0x7FFF | 0x8000);
410     }
411
412     /**
413      * Returns the highest v4 or v6 InetAddress
414      *
415      * @param v6
416      *            true for IPv6, false for Ipv4
417      * @return The highest IPv4 or IPv6 address
418      */
419     public static InetAddress gethighestIP(boolean v6) {
420         try {
421             return (v6) ? InetAddress.getByName("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff") : InetAddress
422                     .getByName("255.255.255.255");
423         } catch (UnknownHostException e) {
424             return null;
425         }
426     }
427 }