Source for java.net.Inet6Address

   1: /* Inet6Address.java --
   2:    Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package java.net;
  40: 
  41: import java.util.Arrays;
  42: import java.io.ObjectInputStream;
  43: import java.io.ObjectOutputStream;
  44: import java.io.IOException;
  45: 
  46: /*
  47:  * Written using on-line Java Platform 1.4 API Specification and
  48:  * RFC 1884 (http://www.ietf.org/rfc/rfc1884.txt)
  49:  * 
  50:  * @author Michael Koch
  51:  * @status Updated to 1.5. Serialization compatibility is tested.
  52:  */
  53: public final class Inet6Address extends InetAddress
  54: {
  55:   static final long serialVersionUID = 6880410070516793377L;
  56: 
  57:   /**
  58:    * Needed for serialization
  59:    */
  60:   byte[] ipaddress;
  61: 
  62:   /**
  63:    * The scope ID, if any. 
  64:    * @since 1.5
  65:    * @serial 
  66:    */
  67:   private int scope_id;
  68: 
  69:   /**
  70:    * The scope ID, if any. 
  71:    * @since 1.5
  72:    * @serial 
  73:    */
  74:   private boolean scope_id_set;
  75: 
  76:   /**
  77:    * Whether ifname is set or not.
  78:    * @since 1.5
  79:    * @serial 
  80:    */
  81:   private boolean scope_ifname_set;
  82: 
  83:   /**
  84:    * Name of the network interface, used only by the serialization methods
  85:    * @since 1.5
  86:    * @serial 
  87:    */
  88:   private String ifname;
  89: 
  90:   /**
  91:    * Scope network interface, or <code>null</code>.
  92:    */
  93:   private transient NetworkInterface nif; 
  94: 
  95:   /**
  96:    * The address family of these addresses (used for serialization).
  97:    */
  98:   private static final int AF_INET6 = 10;
  99: 
 100:   /**
 101:    * Create an Inet6Address object
 102:    *
 103:    * @param addr The IP address
 104:    * @param host The hostname
 105:    */
 106:   Inet6Address(byte[] addr, String host)
 107:   {
 108:     super(addr, host, AF_INET6);
 109:     // Super constructor clones the addr.  Get a reference to the clone.
 110:     this.ipaddress = this.addr;
 111:     ifname = null;
 112:     scope_ifname_set = scope_id_set = false;
 113:     scope_id = 0;
 114:     nif = null;
 115:   }
 116: 
 117:   /**
 118:    * Utility routine to check if the InetAddress is an IP multicast address
 119:    *
 120:    * @since 1.1
 121:    */
 122:   public boolean isMulticastAddress()
 123:   {
 124:     return ipaddress[0] == (byte) 0xFF;
 125:   }
 126: 
 127:   /**
 128:    * Utility routine to check if the InetAddress in a wildcard address
 129:    *
 130:    * @since 1.4
 131:    */
 132:   public boolean isAnyLocalAddress()
 133:   {
 134:     byte[] anylocal = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 135: 
 136:     return Arrays.equals(ipaddress, anylocal);
 137:   }
 138: 
 139:   /**
 140:    * Utility routine to check if the InetAddress is a loopback address
 141:    *
 142:    * @since 1.4
 143:    */
 144:   public boolean isLoopbackAddress()
 145:   {
 146:     byte[] loopback = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
 147: 
 148:     return Arrays.equals(ipaddress, loopback);
 149:   }
 150: 
 151:   /**
 152:    * Utility routine to check if the InetAddress is an link local address
 153:    *
 154:    * @since 1.4
 155:    */
 156:   public boolean isLinkLocalAddress()
 157:   {
 158:     return ipaddress[0] == 0xFA;
 159:   }
 160: 
 161:   /**
 162:    * Utility routine to check if the InetAddress is a site local address
 163:    *
 164:    * @since 1.4
 165:    */
 166:   public boolean isSiteLocalAddress()
 167:   {
 168:     return ipaddress[0] == 0xFB;
 169:   }
 170: 
 171:   /**
 172:    * Utility routine to check if the multicast address has global scope
 173:    *
 174:    * @since 1.4
 175:    */
 176:   public boolean isMCGlobal()
 177:   {
 178:     if (! isMulticastAddress())
 179:       return false;
 180: 
 181:     return (ipaddress[1] & 0x0F) == 0xE;
 182:   }
 183: 
 184:   /**
 185:    * Utility routine to check if the multicast address has node scope
 186:    *
 187:    * @since 1.4
 188:    */
 189:   public boolean isMCNodeLocal()
 190:   {
 191:     if (! isMulticastAddress())
 192:       return false;
 193: 
 194:     return (ipaddress[1] & 0x0F) == 0x1;
 195:   }
 196: 
 197:   /**
 198:    * Utility routine to check if the multicast address has link scope
 199:    *
 200:    * @since 1.4
 201:    */
 202:   public boolean isMCLinkLocal()
 203:   {
 204:     if (! isMulticastAddress())
 205:       return false;
 206: 
 207:     return (ipaddress[1] & 0x0F) == 0x2;
 208:   }
 209: 
 210:   /**
 211:    * Utility routine to check if the multicast address has site scope
 212:    *
 213:    * @since 1.4
 214:    */
 215:   public boolean isMCSiteLocal()
 216:   {
 217:     if (! isMulticastAddress())
 218:       return false;
 219: 
 220:     return (ipaddress[1] & 0x0F) == 0x5;
 221:   }
 222: 
 223:   /**
 224:    * Utility routine to check if the multicast address has organization scope
 225:    *
 226:    * @since 1.4
 227:    */
 228:   public boolean isMCOrgLocal()
 229:   {
 230:     if (! isMulticastAddress())
 231:       return false;
 232: 
 233:     return (ipaddress[1] & 0x0F) == 0x8;
 234:   }
 235: 
 236:   /**
 237:    * Returns the raw IP address of this InetAddress object. The result is in
 238:    * network byte order: the highest order byte of the address is i
 239:    * n getAddress()[0]
 240:    */
 241:   public byte[] getAddress()
 242:   {
 243:     return (byte[]) ipaddress.clone();
 244:   }
 245: 
 246:   /**
 247:    * Creates a scoped Inet6Address where the scope has an integer id.
 248:    *
 249:    * @throws UnkownHostException if the address is an invalid number of bytes.
 250:    * @since 1.5
 251:    */  
 252:   public static Inet6Address getByAddress(String host, byte[] addr, 
 253:                       int scopeId)
 254:     throws UnknownHostException
 255:   {
 256:     if( addr.length != 16 )
 257:       throw new UnknownHostException("Illegal address length: " + addr.length
 258:                      + " bytes.");
 259:     Inet6Address ip = new Inet6Address( addr, host );
 260:     ip.scope_id = scopeId;
 261:     ip.scope_id_set = true;
 262:     return ip;
 263:   }
 264: 
 265:   /**
 266:    * Creates a scoped Inet6Address where the scope is a given
 267:    * NetworkInterface.
 268:    *
 269:    * @throws UnkownHostException if the address is an invalid number of bytes.
 270:    * @since 1.5
 271:    */  
 272:   public static Inet6Address getByAddress(String host, byte[] addr, 
 273:                       NetworkInterface nif)
 274:     throws UnknownHostException
 275:   {
 276:     if( addr.length != 16 )
 277:       throw new UnknownHostException("Illegal address length: " + addr.length
 278:                      + " bytes.");
 279:     Inet6Address ip = new Inet6Address( addr, host );
 280:     ip.nif = nif;
 281: 
 282:     return ip;
 283:   }
 284: 
 285:   /**
 286:    * Returns the <code>NetworkInterface</code> of the address scope
 287:    * if it is a scoped address and the scope is given in the form of a
 288:    * NetworkInterface. 
 289:    * (I.e. the address was created using  the 
 290:    * getByAddress(String, byte[], NetworkInterface) method)
 291:    * Otherwise this method returns <code>null</code>.
 292:    * @since 1.5
 293:    */
 294:   public NetworkInterface getScopedInterface()
 295:   {
 296:     return nif;
 297:   }
 298: 
 299:   /**
 300:    * Returns the scope ID of the address scope if it is a scoped adress using
 301:    * an integer to identify the scope.
 302:    *
 303:    * Otherwise this method returns 0.
 304:    * @since 1.5
 305:    */
 306:   public int getScopeId()
 307:   {
 308:     // check scope_id_set because some JDK-serialized objects seem to have
 309:     // scope_id set to a nonzero value even when scope_id_set == false
 310:     if( scope_id_set )
 311:       return scope_id; 
 312:     return 0;
 313:   }
 314: 
 315:   /**
 316:    * Returns the IP address string in textual presentation
 317:    */
 318:   public String getHostAddress()
 319:   {
 320:     StringBuffer sbuf = new StringBuffer(40);
 321: 
 322:     for (int i = 0; i < 16; i += 2)
 323:       {
 324:     int x = ((ipaddress[i] & 0xFF) << 8) | (ipaddress[i + 1] & 0xFF);
 325: 
 326:     if (i > 0)
 327:       sbuf.append(':');
 328: 
 329:     sbuf.append(Integer.toHexString(x));
 330:       }
 331:     if( nif != null )
 332:       sbuf.append( "%" + nif.getName() );
 333:     else if( scope_id_set )
 334:       sbuf.append( "%" + scope_id );
 335: 
 336:     return sbuf.toString();
 337:   }
 338: 
 339:   /**
 340:    * Returns a hashcode for this IP address
 341:    * (The hashcode is independent of scope)
 342:    */
 343:   public int hashCode()
 344:   {
 345:     return super.hashCode();
 346:   }
 347: 
 348:   /**
 349:    * Compares this object against the specified object
 350:    */
 351:   public boolean equals(Object obj)
 352:   {
 353:     if (! (obj instanceof Inet6Address))
 354:       return false;
 355: 
 356:     Inet6Address ip = (Inet6Address)obj;
 357:     if (ipaddress.length != ip.ipaddress.length)
 358:       return false;
 359: 
 360:     for (int i = 0; i < ip.ipaddress.length; i++)
 361:       if (ipaddress[i] != ip.ipaddress[i])
 362:     return false;
 363: 
 364:     if( ip.nif != null && nif != null )
 365:       return nif.equals( ip.nif );
 366:     if( ip.nif != nif )
 367:       return false;
 368:     if( ip.scope_id_set != scope_id_set )
 369:       return false;
 370:     if( scope_id_set )
 371:       return (scope_id == ip.scope_id);
 372:     return true;
 373:   }
 374: 
 375:   /**
 376:    * Utility routine to check if the InetAddress is an
 377:    * IPv4 compatible IPv6 address
 378:    *
 379:    * @since 1.4
 380:    */
 381:   public boolean isIPv4CompatibleAddress()
 382:   {
 383:     if (ipaddress[0] != 0x00 || ipaddress[1] != 0x00 || ipaddress[2] != 0x00
 384:         || ipaddress[3] != 0x00 || ipaddress[4] != 0x00
 385:         || ipaddress[5] != 0x00 || ipaddress[6] != 0x00
 386:         || ipaddress[7] != 0x00 || ipaddress[8] != 0x00
 387:         || ipaddress[9] != 0x00 || ipaddress[10] != 0x00
 388:         || ipaddress[11] != 0x00)
 389:       return false;
 390: 
 391:     return true;
 392:   }
 393: 
 394:   /**
 395:    * Required for 1.5-compatible serialization.
 396:    * @since 1.5
 397:    */
 398:   private void readObject(ObjectInputStream s)
 399:     throws IOException, ClassNotFoundException
 400:   {  
 401:     s.defaultReadObject();
 402:     try
 403:       {
 404:     if( scope_ifname_set )
 405:       nif = NetworkInterface.getByName( ifname );
 406:       }
 407:     catch( SocketException se )
 408:       {
 409:     // FIXME: Ignore this? or throw an IOException?
 410:       }
 411:   }
 412: 
 413:   /**
 414:    * Required for 1.5-compatible serialization.
 415:    * @since 1.5
 416:    */
 417:   private void writeObject(ObjectOutputStream s)
 418:     throws IOException
 419:   {
 420:     if( nif != null )
 421:       {
 422:     ifname = nif.getName();
 423:     scope_ifname_set = true;
 424:       }
 425:     s.defaultWriteObject();
 426:   }
 427: }