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 gnu.java.lang.CPStringBuilder; 042 043 import java.util.Arrays; 044 import java.io.ObjectInputStream; 045 import java.io.ObjectOutputStream; 046 import java.io.IOException; 047 048 /* 049 * Written using on-line Java Platform 1.4 API Specification and 050 * RFC 1884 (http://www.ietf.org/rfc/rfc1884.txt) 051 * 052 * @author Michael Koch 053 * @status Updated to 1.5. Serialization compatibility is tested. 054 */ 055 public final class Inet6Address extends InetAddress 056 { 057 static final long serialVersionUID = 6880410070516793377L; 058 059 /** 060 * Needed for serialization 061 */ 062 byte[] ipaddress; 063 064 /** 065 * The scope ID, if any. 066 * @since 1.5 067 * @serial 068 */ 069 private int scope_id; 070 071 /** 072 * The scope ID, if any. 073 * @since 1.5 074 * @serial 075 */ 076 private boolean scope_id_set; 077 078 /** 079 * Whether ifname is set or not. 080 * @since 1.5 081 * @serial 082 */ 083 private boolean scope_ifname_set; 084 085 /** 086 * Name of the network interface, used only by the serialization methods 087 * @since 1.5 088 * @serial 089 */ 090 private String ifname; 091 092 /** 093 * Scope network interface, or <code>null</code>. 094 */ 095 private transient NetworkInterface nif; 096 097 /** 098 * The address family of these addresses (used for serialization). 099 */ 100 private static final int AF_INET6 = 10; 101 102 /** 103 * Create an Inet6Address object 104 * 105 * @param addr The IP address 106 * @param host The hostname 107 */ 108 Inet6Address(byte[] addr, String host) 109 { 110 super(addr, host, AF_INET6); 111 // Super constructor clones the addr. Get a reference to the clone. 112 this.ipaddress = this.addr; 113 ifname = null; 114 scope_ifname_set = scope_id_set = false; 115 scope_id = 0; 116 nif = null; 117 } 118 119 /** 120 * Utility routine to check if the InetAddress is an IP multicast address 121 * 122 * @since 1.1 123 */ 124 public boolean isMulticastAddress() 125 { 126 return ipaddress[0] == (byte) 0xFF; 127 } 128 129 /** 130 * Utility routine to check if the InetAddress in a wildcard address 131 * 132 * @since 1.4 133 */ 134 public boolean isAnyLocalAddress() 135 { 136 byte[] anylocal = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 137 138 return Arrays.equals(ipaddress, anylocal); 139 } 140 141 /** 142 * Utility routine to check if the InetAddress is a loopback address 143 * 144 * @since 1.4 145 */ 146 public boolean isLoopbackAddress() 147 { 148 byte[] loopback = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; 149 150 return Arrays.equals(ipaddress, loopback); 151 } 152 153 /** 154 * Utility routine to check if the InetAddress is an link local address 155 * 156 * @since 1.4 157 */ 158 public boolean isLinkLocalAddress() 159 { 160 return ipaddress[0] == 0xFA; 161 } 162 163 /** 164 * Utility routine to check if the InetAddress is a site local address 165 * 166 * @since 1.4 167 */ 168 public boolean isSiteLocalAddress() 169 { 170 return ipaddress[0] == 0xFB; 171 } 172 173 /** 174 * Utility routine to check if the multicast address has global scope 175 * 176 * @since 1.4 177 */ 178 public boolean isMCGlobal() 179 { 180 if (! isMulticastAddress()) 181 return false; 182 183 return (ipaddress[1] & 0x0F) == 0xE; 184 } 185 186 /** 187 * Utility routine to check if the multicast address has node scope 188 * 189 * @since 1.4 190 */ 191 public boolean isMCNodeLocal() 192 { 193 if (! isMulticastAddress()) 194 return false; 195 196 return (ipaddress[1] & 0x0F) == 0x1; 197 } 198 199 /** 200 * Utility routine to check if the multicast address has link scope 201 * 202 * @since 1.4 203 */ 204 public boolean isMCLinkLocal() 205 { 206 if (! isMulticastAddress()) 207 return false; 208 209 return (ipaddress[1] & 0x0F) == 0x2; 210 } 211 212 /** 213 * Utility routine to check if the multicast address has site scope 214 * 215 * @since 1.4 216 */ 217 public boolean isMCSiteLocal() 218 { 219 if (! isMulticastAddress()) 220 return false; 221 222 return (ipaddress[1] & 0x0F) == 0x5; 223 } 224 225 /** 226 * Utility routine to check if the multicast address has organization scope 227 * 228 * @since 1.4 229 */ 230 public boolean isMCOrgLocal() 231 { 232 if (! isMulticastAddress()) 233 return false; 234 235 return (ipaddress[1] & 0x0F) == 0x8; 236 } 237 238 /** 239 * Returns the raw IP address of this InetAddress object. The result is in 240 * network byte order: the highest order byte of the address is i 241 * n getAddress()[0] 242 */ 243 public byte[] getAddress() 244 { 245 return (byte[]) ipaddress.clone(); 246 } 247 248 /** 249 * Creates a scoped Inet6Address where the scope has an integer id. 250 * 251 * @throws UnkownHostException if the address is an invalid number of bytes. 252 * @since 1.5 253 */ 254 public static Inet6Address getByAddress(String host, byte[] addr, 255 int scopeId) 256 throws UnknownHostException 257 { 258 if( addr.length != 16 ) 259 throw new UnknownHostException("Illegal address length: " + addr.length 260 + " bytes."); 261 Inet6Address ip = new Inet6Address( addr, host ); 262 ip.scope_id = scopeId; 263 ip.scope_id_set = true; 264 return ip; 265 } 266 267 /** 268 * Creates a scoped Inet6Address where the scope is a given 269 * NetworkInterface. 270 * 271 * @throws UnkownHostException if the address is an invalid number of bytes. 272 * @since 1.5 273 */ 274 public static Inet6Address getByAddress(String host, byte[] addr, 275 NetworkInterface nif) 276 throws UnknownHostException 277 { 278 if( addr.length != 16 ) 279 throw new UnknownHostException("Illegal address length: " + addr.length 280 + " bytes."); 281 Inet6Address ip = new Inet6Address( addr, host ); 282 ip.nif = nif; 283 284 return ip; 285 } 286 287 /** 288 * Returns the <code>NetworkInterface</code> of the address scope 289 * if it is a scoped address and the scope is given in the form of a 290 * NetworkInterface. 291 * (I.e. the address was created using the 292 * getByAddress(String, byte[], NetworkInterface) method) 293 * Otherwise this method returns <code>null</code>. 294 * @since 1.5 295 */ 296 public NetworkInterface getScopedInterface() 297 { 298 return nif; 299 } 300 301 /** 302 * Returns the scope ID of the address scope if it is a scoped adress using 303 * an integer to identify the scope. 304 * 305 * Otherwise this method returns 0. 306 * @since 1.5 307 */ 308 public int getScopeId() 309 { 310 // check scope_id_set because some JDK-serialized objects seem to have 311 // scope_id set to a nonzero value even when scope_id_set == false 312 if( scope_id_set ) 313 return scope_id; 314 return 0; 315 } 316 317 /** 318 * Returns the IP address string in textual presentation 319 */ 320 public String getHostAddress() 321 { 322 CPStringBuilder sbuf = new CPStringBuilder(40); 323 324 for (int i = 0; i < 16; i += 2) 325 { 326 int x = ((ipaddress[i] & 0xFF) << 8) | (ipaddress[i + 1] & 0xFF); 327 328 if (i > 0) 329 sbuf.append(':'); 330 331 sbuf.append(Integer.toHexString(x)); 332 } 333 if( nif != null ) 334 sbuf.append( "%" + nif.getName() ); 335 else if( scope_id_set ) 336 sbuf.append( "%" + scope_id ); 337 338 return sbuf.toString(); 339 } 340 341 /** 342 * Returns a hashcode for this IP address 343 * (The hashcode is independent of scope) 344 */ 345 public int hashCode() 346 { 347 return super.hashCode(); 348 } 349 350 /** 351 * Compares this object against the specified object 352 */ 353 public boolean equals(Object obj) 354 { 355 if (! (obj instanceof Inet6Address)) 356 return false; 357 358 Inet6Address ip = (Inet6Address)obj; 359 if (ipaddress.length != ip.ipaddress.length) 360 return false; 361 362 for (int i = 0; i < ip.ipaddress.length; i++) 363 if (ipaddress[i] != ip.ipaddress[i]) 364 return false; 365 366 if( ip.nif != null && nif != null ) 367 return nif.equals( ip.nif ); 368 if( ip.nif != nif ) 369 return false; 370 if( ip.scope_id_set != scope_id_set ) 371 return false; 372 if( scope_id_set ) 373 return (scope_id == ip.scope_id); 374 return true; 375 } 376 377 /** 378 * Utility routine to check if the InetAddress is an 379 * IPv4 compatible IPv6 address 380 * 381 * @since 1.4 382 */ 383 public boolean isIPv4CompatibleAddress() 384 { 385 if (ipaddress[0] != 0x00 || ipaddress[1] != 0x00 || ipaddress[2] != 0x00 386 || ipaddress[3] != 0x00 || ipaddress[4] != 0x00 387 || ipaddress[5] != 0x00 || ipaddress[6] != 0x00 388 || ipaddress[7] != 0x00 || ipaddress[8] != 0x00 389 || ipaddress[9] != 0x00 || ipaddress[10] != 0x00 390 || ipaddress[11] != 0x00) 391 return false; 392 393 return true; 394 } 395 396 /** 397 * Required for 1.5-compatible serialization. 398 * @since 1.5 399 */ 400 private void readObject(ObjectInputStream s) 401 throws IOException, ClassNotFoundException 402 { 403 s.defaultReadObject(); 404 try 405 { 406 if( scope_ifname_set ) 407 nif = NetworkInterface.getByName( ifname ); 408 } 409 catch( SocketException se ) 410 { 411 // FIXME: Ignore this? or throw an IOException? 412 } 413 } 414 415 /** 416 * Required for 1.5-compatible serialization. 417 * @since 1.5 418 */ 419 private void writeObject(ObjectOutputStream s) 420 throws IOException 421 { 422 if( nif != null ) 423 { 424 ifname = nif.getName(); 425 scope_ifname_set = true; 426 } 427 s.defaultWriteObject(); 428 } 429 }