• Main Page
  • Related Pages
  • Classes
  • Files
  • File List

RawIpAddress.java

Go to the documentation of this file.
00001 import java.net.InetAddress;
00002 import java.net.UnknownHostException;
00003 
00004 /**
00005  *  Encapsulates arithmetics on raw IP addresses (see RawIpAddress.addr).
00006  *  
00007  *  @author Mikica B Kocic
00008  *
00009  */
00010 public class RawIpAddress
00011 {
00012     /**
00013      *  Raw IP address (IPv4 or IPv6) in network byte (MSB) order where
00014      *  the highest order byte of the address is in addr[0].
00015      *  
00016      *  IPv4 address byte array must be 4 bytes long and IPv6 byte array must be 
00017      *  16 bytes long.
00018      *
00019      *  See: <code>InetAddress.getByAddress()</code>
00020      *  in http://download.oracle.com/javase/6/docs/api/java/net/InetAddress.html
00021      */
00022     private byte[] addr = null;
00023 
00024     /**
00025      *  Creates instance from a copy of the existing IP address. 
00026      */
00027     public RawIpAddress( RawIpAddress original )
00028     {
00029         this.addr = new byte[ original.addr.length ];
00030         this.set( original );
00031     }
00032 
00033     /**
00034      *  Creates instance from the determined IP address of a host, given the host's name. 
00035      *
00036      *  See: <code>InetAddress.getByName()</code>
00037      *  in http://download.oracle.com/javase/6/docs/api/java/net/InetAddress.html
00038      *
00039      *  @throws UnknownHostException if no IP address for the host could be found,
00040      *                    or if a scope_id was specified for a global IPv6 address. 
00041      */
00042     public RawIpAddress( String hostname ) throws UnknownHostException
00043     {
00044         this.addr = InetAddress.getByName( hostname ).getAddress ();
00045     }
00046     
00047     /**
00048      *  Returns a new instance of <code>InetAddress</code> given the raw IP address. 
00049      *  This method doesn't block, i.e. no reverse name service lookup is performed.
00050      *  
00051      *  @throws UnknownHostException  if IP address is of illegal length
00052      */
00053     public InetAddress getInetAddress () throws UnknownHostException
00054     {
00055         return InetAddress.getByAddress( this.addr );
00056     }
00057 
00058     /**
00059      *  Returns true if two IP addresses belongs to the same version
00060      */
00061     public boolean isSameVersion( RawIpAddress a2 )
00062     {
00063         return this.addr.length == a2.addr.length;
00064     }
00065     
00066     /**
00067      *  Sets the IP address from the value of other IP address. 
00068      */
00069     public void set( RawIpAddress a2 )
00070     {
00071         assert ! isSameVersion( a2 ) 
00072             : "We can do arithmetics only with addresses of the same IP version!";
00073 
00074         System.arraycopy( a2.addr, 0, this.addr, 0, a2.addr.length );
00075     }
00076 
00077     /**
00078      *  Increases the IP address by one. 
00079      */
00080     public void increase ()
00081     {
00082         int carry = 1; // initial carry is 1 meaning increment by one
00083         
00084         for ( int i = addr.length - 1; i >= 0 && carry > 0; --i )
00085         {
00086             int sum = ( ( addr[i] + 0x100 ) & 0xFF ) + carry; // add carry to current
00087             carry = sum >> 8; // carry is overflow over 0x100
00088             addr[i] = (byte)( ( sum & 0xFF ) - 0x100 ); 
00089         }
00090     }
00091     
00092     /**
00093      *  Returns difference of two IP addresses. 
00094      *  
00095      *  \warning { Caveats:
00096      *  
00097      *  IPv6 addresses are 16 octets long, but this function returns
00098      *  primitive type <code>long</code> that is 8 octets long, so
00099      *  it will give wrong result if upper 8 octets of two IPv6 addresses
00100      *  are different.
00101      *  
00102      *  However, the meaning of this procedure was to calculate the span
00103      *  of the range between two IP addresses that will be scanned, so it
00104      *  will actually fail if we wanted to scan more than 2^64 hosts.
00105      *  
00106      *  Maybe it would be better to specify <em>start IP address</em> 
00107      *  and <em>count of IP addresses</em> instead of start and stop IP addresses as
00108      *  input parameters? }
00109      *  
00110      *  @param a2   the second IP address
00111      */
00112     public long subtract( RawIpAddress a2 )
00113     {
00114         assert ! isSameVersion( a2 ) 
00115             : "We can do arithmetics only with addresses of the same IP version!";
00116 
00117         long delta = 0;
00118         
00119         for ( int i = 0; i < this.addr.length; ++i ) 
00120         {
00121             int b1 = ( this.addr[i] + 0x100 ) & 0xFF;
00122             int b2 = ( a2.addr[i] + 0x100 ) & 0xFF;
00123 
00124             delta <<= 8;
00125             delta += ( b1 - b2 );
00126         }
00127 
00128         return delta;
00129     }
00130     
00131     /**
00132      *  Compares two IP addresses. 
00133      *  
00134      *  @param a2   the second IP address
00135      *  @return -1 if first < second, 0 if first == second, 1 if first > second address
00136      */
00137     public int compare( RawIpAddress a2 )
00138     {
00139         assert ! isSameVersion( a2 ) 
00140             : "We can do arithmetics only with addresses of the same IP version!";
00141 
00142         for ( int i = 0; i < this.addr.length; ++i )
00143         {
00144             int b1 = ( this.addr[i] + 0x100 ) & 0xFF;
00145             int b2 = ( a2.addr[i] + 0x100 ) & 0xFF;
00146 
00147             if ( b1 < b2 ) {
00148                 return -1;
00149             } else if ( b1 > b2 ) {
00150                 return +1;
00151             } else {
00152                 /* equal; continue */
00153             }
00154         }
00155         
00156         return 0;
00157     }
00158     
00159     /**
00160      *  Returns standard decimal dotted representation of the IP address  
00161      */
00162     public String toString () 
00163     {
00164         StringBuffer result = new StringBuffer ();
00165 
00166         for( int i = 0; i < this.addr.length; i++ )
00167         {
00168             if ( i != 0 ) {
00169                 result.append( "." );
00170             }
00171             result.append( ( this.addr[i] + 0x100 ) & 0xFF );
00172         }
00173 
00174         return result.toString ();
00175     }
00176 }

Generated on Thu Dec 16 2010 12:29:37 for Port Scanner by  doxygen 1.7.2