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