Mark AD-SAL interfaces as deprecated
[controller.git] / opendaylight / adsal / sal / api / src / main / java / org / opendaylight / controller / sal / utils / NetUtils.java
1 /*
2  * Copyright (c) 2013-2014 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.Inet4Address;
12 import java.net.Inet6Address;
13 import java.net.InetAddress;
14 import java.net.UnknownHostException;
15 import java.util.Arrays;
16 import java.util.regex.Matcher;
17 import java.util.regex.Pattern;
18
19 import org.slf4j.Logger;
20 import org.slf4j.LoggerFactory;
21
22 /**
23  * Utility class containing the common utility functions needed for operating on
24  * networking data structures
25  */
26 @Deprecated
27 public abstract class NetUtils {
28     protected static final Logger logger = LoggerFactory.getLogger(NetUtils.class);
29     /**
30      * Constant holding the number of bits in a byte
31      */
32     public static final int NumBitsInAByte = 8;
33
34     /**
35      * Constant holding the number of bytes in MAC Address
36      */
37     public static final int MACAddrLengthInBytes = 6;
38
39     /**
40      * Constant holding the number of words in MAC Address
41      */
42     public static final int MACAddrLengthInWords = 3;
43
44     /**
45      * Constant holding the broadcast MAC address
46      */
47     private static final byte[] BroadcastMACAddr = {-1, -1, -1, -1, -1, -1};
48
49     /**
50      * Converts a 4 bytes array into an integer number
51      *
52      * @param ba
53      *            the 4 bytes long byte array
54      * @return the integer number
55      */
56     public static int byteArray4ToInt(byte[] ba) {
57         if (ba == null || ba.length != 4) {
58             return 0;
59         }
60         return (0xff & ba[0]) << 24 | (0xff & ba[1]) << 16 | (0xff & ba[2]) << 8 | (0xff & ba[3]);
61     }
62
63     /**
64      * Converts a 6 bytes array into a long number MAC addresses.
65      *
66      * @param ba
67      *            The 6 bytes long byte array.
68      * @return The long number.
69      *         Zero is returned if {@code ba} is {@code null} or
70      *         the length of it is not six.
71      */
72     public static long byteArray6ToLong(byte[] ba) {
73         if (ba == null || ba.length != MACAddrLengthInBytes) {
74             return 0L;
75         }
76         long num = 0L;
77         int i = 0;
78         do {
79             num <<= NumBitsInAByte;
80             num |= 0xff & ba[i];
81             i++;
82         } while (i < MACAddrLengthInBytes);
83         return num;
84     }
85
86     /**
87      * Converts a long number to a 6 bytes array for MAC addresses.
88      *
89      * @param addr
90      *            The long number.
91      * @return The byte array.
92      */
93     public static byte[] longToByteArray6(long addr){
94         byte[] mac = new byte[MACAddrLengthInBytes];
95         int i = MACAddrLengthInBytes - 1;
96         do {
97             mac[i] = (byte) addr;
98             addr >>>= NumBitsInAByte;
99             i--;
100         } while (i >= 0);
101         return mac;
102     }
103
104     /**
105      * Converts an integer number into a 4 bytes array
106      *
107      * @param i
108      *            the integer number
109      * @return the byte array
110      */
111     public static byte[] intToByteArray4(int i) {
112         return new byte[] { (byte) ((i >> 24) & 0xff), (byte) ((i >> 16) & 0xff), (byte) ((i >> 8) & 0xff),
113                 (byte) (i & 0xff) };
114     }
115
116     /**
117      * Converts an IP address passed as integer value into the respective
118      * InetAddress object
119      *
120      * @param address
121      *            the IP address in integer form
122      * @return the IP address in InetAddress form
123      */
124     public static InetAddress getInetAddress(int address) {
125         InetAddress ip = null;
126         try {
127             ip = InetAddress.getByAddress(NetUtils.intToByteArray4(address));
128         } catch (UnknownHostException e) {
129             logger.error("", e);
130         }
131         return ip;
132     }
133
134     /**
135      * Return the InetAddress Network Mask given the length of the prefix bit
136      * mask. The prefix bit mask indicates the contiguous leading bits that are
137      * NOT masked out. Example: A prefix bit mask length of 8 will give an
138      * InetAddress Network Mask of 255.0.0.0
139      *
140      * @param prefixMaskLength
141      *            integer representing the length of the prefix network mask
142      * @param isV6
143      *            boolean representing the IP version of the returned address
144      * @return
145      */
146     public static InetAddress getInetNetworkMask(int prefixMaskLength, boolean isV6) {
147         if (prefixMaskLength < 0 || (!isV6 && prefixMaskLength > 32) || (isV6 && prefixMaskLength > 128)) {
148             return null;
149         }
150         byte v4Address[] = { 0, 0, 0, 0 };
151         byte v6Address[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
152         byte address[] = (isV6) ? v6Address : v4Address;
153         int numBytes = prefixMaskLength / 8;
154         int numBits = prefixMaskLength % 8;
155         int i = 0;
156         for (; i < numBytes; i++) {
157             address[i] = (byte) 0xff;
158         }
159         if (numBits > 0) {
160             int rem = 0;
161             for (int j = 0; j < numBits; j++) {
162                 rem |= 1 << (7 - j);
163             }
164             address[i] = (byte) rem;
165         }
166
167         try {
168             return InetAddress.getByAddress(address);
169         } catch (UnknownHostException e) {
170             logger.error("", e);
171         }
172         return null;
173     }
174
175     /**
176      * Returns the prefix size in bits of the specified subnet mask. Example:
177      * For the subnet mask ff.ff.ff.e0 it returns 25 while for ff.00.00.00 it
178      * returns 8. If the passed subnetMask array is null, 0 is returned.
179      *
180      * @param subnetMask
181      *            the subnet mask as byte array
182      * @return the prefix length as number of bits
183      */
184     public static int getSubnetMaskLength(byte[] subnetMask) {
185         int maskLength = 0;
186         if (subnetMask != null && (subnetMask.length == 4 || subnetMask.length == 16)) {
187             int index = 0;
188             while (index < subnetMask.length && subnetMask[index] == (byte) 0xFF) {
189                 maskLength += NetUtils.NumBitsInAByte;
190                 index++;
191             }
192             if (index != subnetMask.length) {
193                 int bits = NetUtils.NumBitsInAByte - 1;
194                 while (bits >= 0 && (subnetMask[index] & 1 << bits)  != 0) {
195                     bits--;
196                     maskLength++;
197                 }
198             }
199         }
200         return maskLength;
201     }
202
203     /**
204      * Returns the prefix size in bits of the specified subnet mask. Example:
205      * For the subnet mask 255.255.255.128 it returns 25 while for 255.0.0.0 it
206      * returns 8. If the passed subnetMask object is null, 0 is returned
207      *
208      * @param subnetMask
209      *            the subnet mask as InetAddress
210      * @return the prefix length as number of bits
211      */
212     public static int getSubnetMaskLength(InetAddress subnetMask) {
213         return subnetMask == null ? 0 : NetUtils.getSubnetMaskLength(subnetMask.getAddress());
214     }
215
216     /**
217      * Given an IP address and a prefix network mask length, it returns the
218      * equivalent subnet prefix IP address Example: for ip = "172.28.30.254" and
219      * maskLen = 25 it will return "172.28.30.128"
220      *
221      * @param ip
222      *            the IP address in InetAddress form
223      * @param maskLen
224      *            the length of the prefix network mask
225      * @return the subnet prefix IP address in InetAddress form
226      */
227     public static InetAddress getSubnetPrefix(InetAddress ip, int maskLen) {
228         int bytes = maskLen / 8;
229         int bits = maskLen % 8;
230         byte modifiedByte;
231         byte[] sn = ip.getAddress();
232         if (bits > 0) {
233             modifiedByte = (byte) (sn[bytes] >> (8 - bits));
234             sn[bytes] = (byte) (modifiedByte << (8 - bits));
235             bytes++;
236         }
237         for (; bytes < sn.length; bytes++) {
238             sn[bytes] = (byte) (0);
239         }
240         try {
241             return InetAddress.getByAddress(sn);
242         } catch (UnknownHostException e) {
243             return null;
244         }
245     }
246
247     /**
248      * Checks if the test address and mask conflicts with the filter address and
249      * mask
250      *
251      * For example:
252      * testAddress: 172.28.2.23
253      * testMask: 255.255.255.0
254      * filterAddress: 172.28.1.10
255      * testMask: 255.255.255.0
256      * do conflict
257      *
258      * testAddress: 172.28.2.23
259      * testMask: 255.255.255.0
260      * filterAddress: 172.28.1.10
261      * testMask: 255.255.0.0
262      * do not conflict
263      *
264      * Null parameters are permitted
265      *
266      * @param testAddress
267      * @param filterAddress
268      * @param testMask
269      * @param filterMask
270      * @return
271      */
272     public static boolean inetAddressConflict(InetAddress testAddress, InetAddress filterAddress, InetAddress testMask,
273             InetAddress filterMask) {
274         // Sanity check
275         if ((testAddress == null) || (filterAddress == null)) {
276             return false;
277         }
278
279         // Presence check
280         if (isAny(testAddress) || isAny(filterAddress)) {
281             return false;
282         }
283
284         int testMaskLen = (testMask == null) ? ((testAddress instanceof Inet4Address) ? 32 : 128) : NetUtils
285                 .getSubnetMaskLength(testMask);
286         int filterMaskLen = (filterMask == null) ? ((testAddress instanceof Inet4Address) ? 32 : 128) : NetUtils
287                 .getSubnetMaskLength(filterMask);
288
289         // Mask length check. Test mask has to be more specific than filter one
290         if (testMaskLen < filterMaskLen) {
291             return true;
292         }
293
294         // Subnet Prefix on filter mask length must be the same
295         InetAddress prefix1 = getSubnetPrefix(testAddress, filterMaskLen);
296         InetAddress prefix2 = getSubnetPrefix(filterAddress, filterMaskLen);
297         return (!prefix1.equals(prefix2));
298     }
299
300     /**
301      * Returns true if the passed MAC address is all zero
302      *
303      * @param mac
304      *            the byte array representing the MAC address
305      * @return true if all MAC bytes are zero
306      */
307     public static boolean isZeroMAC(byte[] mac) {
308         for (short i = 0; i < 6; i++) {
309             if (mac[i] != 0) {
310                 return false;
311             }
312         }
313         return true;
314     }
315
316     /**
317      * Returns true if the MAC address is the broadcast MAC address and false
318      * otherwise.
319      *
320      * @param MACAddress
321      * @return
322      */
323     public static boolean isBroadcastMACAddr(byte[] MACAddress) {
324         if (MACAddress.length == MACAddrLengthInBytes) {
325             for (int i = 0; i < 6; i++) {
326                 if (MACAddress[i] != BroadcastMACAddr[i]) {
327                     return false;
328                 }
329             }
330             return true;
331         }
332
333         return false;
334     }
335     /**
336      * Returns true if the MAC address is a unicast MAC address and false
337      * otherwise.
338      *
339      * @param MACAddress
340      * @return
341      */
342     public static boolean isUnicastMACAddr(byte[] MACAddress) {
343         if (MACAddress.length == MACAddrLengthInBytes) {
344             return (MACAddress[0] & 1) == 0;
345         }
346         return false;
347     }
348
349     /**
350      * Returns true if the MAC address is a multicast MAC address and false
351      * otherwise. Note that this explicitly returns false for the broadcast MAC
352      * address.
353      *
354      * @param MACAddress
355      * @return
356      */
357     public static boolean isMulticastMACAddr(byte[] MACAddress) {
358         if (MACAddress.length == MACAddrLengthInBytes && !isBroadcastMACAddr(MACAddress)) {
359             return (MACAddress[0] & 1) != 0;
360         }
361         return false;
362     }
363
364     /**
365      * Returns true if the passed InetAddress contains all zero
366      *
367      * @param ip
368      *            the IP address to test
369      * @return true if the address is all zero
370      */
371     public static boolean isAny(InetAddress ip) {
372         for (byte b : ip.getAddress()) {
373             if (b != 0) {
374                 return false;
375             }
376         }
377         return true;
378     }
379
380     public static boolean fieldsConflict(int field1, int field2) {
381         if ((field1 == 0) || (field2 == 0) || (field1 == field2)) {
382             return false;
383         }
384         return true;
385     }
386
387     public static InetAddress parseInetAddress(String addressString) {
388         InetAddress address = null;
389         try {
390             address = InetAddress.getByName(addressString);
391         } catch (UnknownHostException e) {
392             logger.error("", e);
393         }
394         return address;
395     }
396
397     /**
398      * Checks if the passed IP v4 address in string form is valid The address
399      * may specify a mask at the end as "/MM"
400      *
401      * @param cidr
402      *            the v4 address as A.B.C.D/MM
403      * @return
404      */
405     public static boolean isIPv4AddressValid(String cidr) {
406         if (cidr == null) {
407             return false;
408         }
409
410         String values[] = cidr.split("/");
411         Pattern ipv4Pattern = Pattern
412                 .compile("(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])");
413         Matcher mm = ipv4Pattern.matcher(values[0]);
414         if (!mm.matches()) {
415             return false;
416         }
417         if (values.length >= 2) {
418             int prefix = Integer.valueOf(values[1]);
419             if ((prefix < 0) || (prefix > 32)) {
420                 return false;
421             }
422         }
423         return true;
424     }
425
426     /**
427      * Checks if the passed IP v6 address in string form is valid The address
428      * may specify a mask at the end as "/MMM"
429      *
430      * @param cidr
431      *            the v6 address as A::1/MMM
432      * @return
433      */
434     public static boolean isIPv6AddressValid(String cidr) {
435         if (cidr == null) {
436             return false;
437         }
438
439         String values[] = cidr.split("/");
440         try {
441             // when given an IP address, InetAddress.getByName validates the ip
442             // address
443             InetAddress addr = InetAddress.getByName(values[0]);
444             if (!(addr instanceof Inet6Address)) {
445                 return false;
446             }
447         } catch (UnknownHostException ex) {
448             return false;
449         }
450
451         if (values.length >= 2) {
452             int prefix = Integer.valueOf(values[1]);
453             if ((prefix < 0) || (prefix > 128)) {
454                 return false;
455             }
456         }
457         return true;
458     }
459
460     /**
461      * Checks if the passed IP address in string form is a valid v4 or v6
462      * address. The address may specify a mask at the end as "/MMM"
463      *
464      * @param cidr
465      *            the v4 or v6 address as IP/MMM
466      * @return
467      */
468     public static boolean isIPAddressValid(String cidr) {
469         return NetUtils.isIPv4AddressValid(cidr) || NetUtils.isIPv6AddressValid(cidr);
470     }
471
472     /*
473      * Following utilities are useful when you need to compare or bit shift java
474      * primitive type variable which are inherently signed
475      */
476     /**
477      * Returns the unsigned value of the passed byte variable
478      *
479      * @param b
480      *            the byte value
481      * @return the int variable containing the unsigned byte value
482      */
483     public static int getUnsignedByte(byte b) {
484         return b & 0xFF;
485     }
486
487     /**
488      * Return the unsigned value of the passed short variable
489      *
490      * @param s
491      *            the short value
492      * @return the int variable containing the unsigned short value
493      */
494     public static int getUnsignedShort(short s) {
495         return s & 0xFFFF;
496     }
497
498     /**
499      * Returns the highest v4 or v6 InetAddress
500      *
501      * @param v6
502      *            true for IPv6, false for Ipv4
503      * @return The highest IPv4 or IPv6 address
504      */
505     public static InetAddress gethighestIP(boolean v6) {
506         try {
507             return (v6) ? InetAddress.getByName("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff") : InetAddress
508                     .getByName("255.255.255.255");
509         } catch (UnknownHostException e) {
510             return null;
511         }
512     }
513
514     /**
515      * Returns Broadcast MAC Address
516      *
517      * @return the byte array containing  broadcast mac address
518      */
519     public static byte[] getBroadcastMACAddr() {
520         return Arrays.copyOf(BroadcastMACAddr, BroadcastMACAddr.length);
521     }
522 }