1 package org.opendaylight.controller.packetcable.provider;
2 import java.math.BigInteger;
3 import java.net.InetAddress;
4 import java.net.UnknownHostException;
7 * @author c3oe.de, based on snippets from Scott Plante, John Kugelmann
11 final private int bytesSubnetCount;
12 final private BigInteger bigMask;
13 final private BigInteger bigSubnetMasked;
14 final private int prefixLen;
16 /** For use via format "192.168.0.0/24" or "2001:db8:85a3:880:0:0:0:0/57" */
17 public Subnet( final InetAddress subnetAddress, final int bits )
19 this.prefixLen = bits;
20 this.bytesSubnetCount = subnetAddress.getAddress().length; // 4 or 16
21 this.bigMask = BigInteger.valueOf( -1 ).shiftLeft( this.bytesSubnetCount*8 - bits ); // mask = -1 << 32 - bits
22 this.bigSubnetMasked = new BigInteger( subnetAddress.getAddress() ).and( this.bigMask );
25 /** For use via format "192.168.0.0/255.255.255.0" or single address */
26 public Subnet( final InetAddress subnetAddress, final InetAddress mask )
28 this.bytesSubnetCount = subnetAddress.getAddress().length;
29 this.bigMask = null == mask ? BigInteger.valueOf( -1 ) : new BigInteger( mask.getAddress() ); // no mask given case is handled here.
30 this.bigSubnetMasked = new BigInteger( subnetAddress.getAddress() ).and( this.bigMask );
31 int lowestSetBit = bigMask.getLowestSetBit();
32 this.prefixLen = lowestSetBit == -1 ? 0 : 32 - lowestSetBit;
36 * Subnet factory method.
37 * @param subnetMask format: "192.168.0.0/24" or "192.168.0.0/255.255.255.0"
38 * or single address or "2001:db8:85a3:880:0:0:0:0/57"
39 * @return a new instance
40 * @throws UnknownHostException thrown if unsupported subnet mask.
42 public static Subnet createInstance( final String subnetMask )
43 throws UnknownHostException
45 final String[] stringArr = subnetMask.split("/");
46 if ( 2 > stringArr.length )
47 return new Subnet( InetAddress.getByName( stringArr[ 0 ] ), null);
48 else if ( stringArr[ 1 ].contains(".") || stringArr[ 1 ].contains(":") )
49 return new Subnet( InetAddress.getByName( stringArr[ 0 ] ), InetAddress.getByName( stringArr[ 1 ] ) );
51 return new Subnet( InetAddress.getByName( stringArr[ 0 ] ), Integer.parseInt( stringArr[ 1 ] ) );
54 public int getPrefixLen() {
58 public boolean isInNet( final InetAddress address )
60 final byte[] bytesAddress = address.getAddress();
61 if ( this.bytesSubnetCount != bytesAddress.length )
63 final BigInteger bigAddress = new BigInteger( bytesAddress );
64 return bigAddress.and( this.bigMask ).equals( this.bigSubnetMasked );
68 final public boolean equals( Object obj )
70 if ( ! (obj instanceof Subnet) )
72 final Subnet other = (Subnet)obj;
73 return this.bigSubnetMasked.equals( other.bigSubnetMasked ) &&
74 this.bigMask.equals( other.bigMask ) &&
75 this.bytesSubnetCount == other.bytesSubnetCount;
79 final public int hashCode()
81 return this.bytesSubnetCount;
85 public String toString()
87 final StringBuilder buf = new StringBuilder();
88 bigInteger2IpString( buf, this.bigSubnetMasked, this.bytesSubnetCount );
90 bigInteger2IpString( buf, this.bigMask, this.bytesSubnetCount );
91 return buf.toString();
94 static private void bigInteger2IpString( final StringBuilder buf, final BigInteger bigInteger, final int displayBytes )
96 final boolean isIPv4 = 4 == displayBytes;
97 byte[] bytes = bigInteger.toByteArray();
98 int diffLen = displayBytes - bytes.length;
99 final byte fillByte = 0 > (int)bytes[ 0 ] ? (byte)0xFF : (byte)0x00;
102 for ( int i = 0; i < displayBytes; i++ )
104 if ( 0 < i && ! isIPv4 && i % 2 == 0 )
106 else if ( 0 < i && isIPv4 )
108 integer = 0xFF & (i < diffLen ? fillByte : bytes[ i - diffLen ]);
109 if ( ! isIPv4 && 0x10 > integer )
111 buf.append( isIPv4 ? integer : Integer.toHexString( integer ) );