001 /* Inet6Address.java -- 002 Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc. 003 004 This file is part of GNU Classpath. 005 006 GNU Classpath is free software; you can redistribute it and/or modify 007 it under the terms of the GNU General Public License as published by 008 the Free Software Foundation; either version 2, or (at your option) 009 any later version. 010 011 GNU Classpath is distributed in the hope that it will be useful, but 012 WITHOUT ANY WARRANTY; without even the implied warranty of 013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 General Public License for more details. 015 016 You should have received a copy of the GNU General Public License 017 along with GNU Classpath; see the file COPYING. If not, write to the 018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 019 02110-1301 USA. 020 021 Linking this library statically or dynamically with other modules is 022 making a combined work based on this library. Thus, the terms and 023 conditions of the GNU General Public License cover the whole 024 combination. 025 026 As a special exception, the copyright holders of this library give you 027 permission to link this library with independent modules to produce an 028 executable, regardless of the license terms of these independent 029 modules, and to copy and distribute the resulting executable under 030 terms of your choice, provided that you also meet, for each linked 031 independent module, the terms and conditions of the license of that 032 module. An independent module is a module which is not derived from 033 or based on this library. If you modify this library, you may extend 034 this exception to your version of the library, but you are not 035 obligated to do so. If you do not wish to do so, delete this 036 exception statement from your version. */ 037 038 039 package java.net; 040 041 import java.util.Arrays; 042 import java.io.ObjectInputStream; 043 import java.io.ObjectOutputStream; 044 import java.io.IOException; 045 046 /* 047 * Written using on-line Java Platform 1.4 API Specification and 048 * RFC 1884 (http://www.ietf.org/rfc/rfc1884.txt) 049 * 050 * @author Michael Koch 051 * @status Updated to 1.5. Serialization compatibility is tested. 052 */ 053 public final class Inet6Address extends InetAddress 054 { 055 static final long serialVersionUID = 6880410070516793377L; 056 057 /** 058 * Needed for serialization 059 */ 060 byte[] ipaddress; 061 062 /** 063 * The scope ID, if any. 064 * @since 1.5 065 * @serial 066 */ 067 private int scope_id; 068 069 /** 070 * The scope ID, if any. 071 * @since 1.5 072 * @serial 073 */ 074 private boolean scope_id_set; 075 076 /** 077 * Whether ifname is set or not. 078 * @since 1.5 079 * @serial 080 */ 081 private boolean scope_ifname_set; 082 083 /** 084 * Name of the network interface, used only by the serialization methods 085 * @since 1.5 086 * @serial 087 */ 088 private String ifname; 089 090 /** 091 * Scope network interface, or <code>null</code>. 092 */ 093 private transient NetworkInterface nif; 094 095 /** 096 * The address family of these addresses (used for serialization). 097 */ 098 private static final int AF_INET6 = 10; 099 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 }