InetAddress.java revision ca8f5b66c546d8545e41f71b6fb852424c681881
1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package java.net; 19 20import java.io.FileDescriptor; 21import java.io.IOException; 22import java.io.ObjectInputStream; 23import java.io.ObjectOutputStream; 24import java.io.ObjectStreamException; 25import java.io.ObjectStreamField; 26import java.io.Serializable; 27import java.security.AccessController; 28import java.util.Arrays; 29import java.util.ArrayList; 30import java.util.Comparator; 31import java.util.Enumeration; 32import java.util.StringTokenizer; 33 34import org.apache.harmony.luni.net.NetUtil; 35import org.apache.harmony.luni.platform.INetworkSystem; 36import org.apache.harmony.luni.platform.Platform; 37import org.apache.harmony.luni.util.Inet6Util; 38import org.apache.harmony.luni.util.Msg; 39import org.apache.harmony.luni.util.PriviAction; 40 41/** 42 * The Internet Protocol (IP) address representation class. This class 43 * encapsulates an IP address and provides name and reverse name resolution 44 * functions. The address is stored in network order, but as a signed (rather 45 * than unsigned) integer. 46 */ 47public class InetAddress extends Object implements Serializable { 48 49 final static byte[] any_bytes = { 0, 0, 0, 0 }; 50 51 final static byte[] localhost_bytes = { 127, 0, 0, 1 }; 52 53 static InetAddress ANY = new Inet4Address(any_bytes); 54 55 private final static INetworkSystem NETIMPL = Platform.getNetworkSystem(); 56 57 final static InetAddress LOOPBACK = new Inet4Address(localhost_bytes, 58 "localhost"); //$NON-NLS-1$ 59 60 private static final String ERRMSG_CONNECTION_REFUSED = "Connection refused"; //$NON-NLS-1$ 61 62 private static final long serialVersionUID = 3286316764910316507L; 63 64 // BEGIN android-added 65 /** 66 * default time-to-live for DNS cache entries; 600 seconds == 10 minutes 67 */ 68 private static final String DEFAULT_NETADDR_CACHE_TTL_SECS = "600"; 69 // END android-added 70 71 String hostName; 72 73 private static class WaitReachable { 74 } 75 76 private transient Object waitReachable = new WaitReachable(); 77 78 private boolean reached; 79 80 private int addrCount; 81 82 int family = 2; 83 84 byte[] ipaddress; 85 86 // BEGIN android-removed 87 // // Fill in the JNI id caches 88 // private static native void oneTimeInitialization(boolean supportsIPv6); 89 // 90 // static { 91 // oneTimeInitialization(true); 92 // } 93 // END android-removed 94 95 /** 96 * Constructs an InetAddress. 97 */ 98 InetAddress() { 99 super(); 100 } 101 102 /** 103 * Constructs an {@code InetAddress}, representing the {@code address} and 104 * {@code hostName}. 105 * 106 * @param address 107 * the network address. 108 */ 109 InetAddress(byte[] address) { 110 super(); 111 this.ipaddress = address; 112 } 113 114 /** 115 * Constructs an {@code InetAddress}, representing the {@code address} and 116 * {@code hostName}. 117 * 118 * @param address 119 * the network address. 120 */ 121 InetAddress(byte[] address, String hostName) { 122 super(); 123 this.ipaddress = address; 124 this.hostName = hostName; 125 } 126 127 // BEGIN android-removed 128 // CacheElement cacheElement() { 129 // return new CacheElement(); 130 // } 131 // END android-removed 132 133 /** 134 * Compares this {@code InetAddress} instance against the specified address 135 * in {@code obj}. Two addresses are equal if their address byte arrays have 136 * the same length and if the bytes in the arrays are equal. 137 * 138 * @param obj 139 * the object to be tested for equality. 140 * @return {@code true} if both objects are equal, {@code false} otherwise. 141 */ 142 @Override 143 public boolean equals(Object obj) { 144 // BEGIN android-changed 145 if (!(obj instanceof InetAddress)) { 146 return false; 147 } 148 // END android-changed 149 150 // now check if their byte arrays match... 151 byte[] objIPaddress = ((InetAddress) obj).ipaddress; 152 // BEGIN android-added 153 if (objIPaddress.length != ipaddress.length) { 154 return false; 155 } 156 // END android-added 157 for (int i = 0; i < objIPaddress.length; i++) { 158 if (objIPaddress[i] != this.ipaddress[i]) { 159 return false; 160 } 161 } 162 return true; 163 } 164 165 /** 166 * Returns the IP address represented by this {@code InetAddress} instance 167 * as a byte array. The elements are in network order (the highest order 168 * address byte is in the zeroth element). 169 * 170 * @return the address in form of a byte array. 171 */ 172 public byte[] getAddress() { 173 return ipaddress.clone(); 174 } 175 176 // BEGIN android-added 177 static final Comparator<byte[]> SHORTEST_FIRST = new Comparator<byte[]>() { 178 public int compare(byte[] a1, byte[] a2) { 179 return a1.length - a2.length; 180 } 181 }; 182 183 static final Comparator<byte[]> LONGEST_FIRST = new Comparator<byte[]>() { 184 public int compare(byte[] a1, byte[] a2) { 185 return a2.length - a1.length; 186 } 187 }; 188 189 /** 190 * Converts an array of byte arrays representing raw IP addresses of a host 191 * to an array of InetAddress objects, sorting to respect the value of the 192 * system preferIPv6Addresses preference. 193 * 194 * @param rawAddresses the raw addresses to convert. 195 * @param hostName the hostname corresponding to the IP address. 196 * @return the corresponding InetAddresses, appropriately sorted. 197 */ 198 static InetAddress[] bytesToInetAddresses(byte[][] rawAddresses, 199 String hostName) { 200 // Sort the raw byte arrays. 201 Comparator<byte[]> comparator = preferIPv6Addresses() 202 ? LONGEST_FIRST : SHORTEST_FIRST; 203 Arrays.sort(rawAddresses, comparator); 204 205 // Convert the byte arrays to InetAddresses. 206 InetAddress[] returnedAddresses = new InetAddress[rawAddresses.length]; 207 for (int i = 0; i < rawAddresses.length; i++) { 208 byte[] rawAddress = rawAddresses[i]; 209 if (rawAddress.length == 16) { 210 returnedAddresses[i] = new Inet6Address(rawAddress, hostName); 211 } else if (rawAddress.length == 4) { 212 returnedAddresses[i] = new Inet4Address(rawAddress, hostName); 213 } else { 214 // Cannot happen, because the underlying code only returns 215 // addresses that are 4 or 16 bytes long. 216 throw new AssertionError("Impossible address length " + 217 rawAddress.length); 218 } 219 } 220 return returnedAddresses; 221 } 222 // END android-added 223 224 /** 225 * Gets all IP addresses associated with the given {@code host} identified 226 * by name or literal IP address. The IP address is resolved by the 227 * configured name service. If the host name is empty or {@code null} an 228 * {@code UnknownHostException} is thrown. If the host name is a literal IP 229 * address string an array with the corresponding single {@code InetAddress} 230 * is returned. 231 * 232 * @param host the hostname or literal IP string to be resolved. 233 * @return the array of addresses associated with the specified host. 234 * @throws UnknownHostException if the address lookup fails. 235 */ 236 public static InetAddress[] getAllByName(String host) 237 throws UnknownHostException { 238 // BEGIN android-changed 239 return getAllByNameImpl(host, true); 240 // END android-changed 241 } 242 243 // BEGIN android-added 244 /** 245 * Implementation of getAllByName. 246 * 247 * @param host the hostname or literal IP string to be resolved. 248 * @param returnUnshared requests a result that is modifiable by the caller. 249 * @return the array of addresses associated with the specified host. 250 * @throws UnknownHostException if the address lookup fails. 251 */ 252 static InetAddress[] getAllByNameImpl(String host, boolean returnUnshared) 253 throws UnknownHostException { 254 if (host == null || 0 == host.length()) { 255 if (preferIPv6Addresses()) { 256 return new InetAddress[] { Inet6Address.LOOPBACK, LOOPBACK }; 257 } else { 258 return new InetAddress[] { LOOPBACK, Inet6Address.LOOPBACK }; 259 } 260 } 261 262 // Special-case "0" for legacy IPv4 applications. 263 if (host.equals("0")) { //$NON-NLS-1$ 264 return new InetAddress[] { InetAddress.ANY }; 265 } 266 267 if (isHostName(host)) { 268 SecurityManager security = System.getSecurityManager(); 269 if (security != null) { 270 security.checkConnect(host, -1); 271 } 272 if (returnUnshared) { 273 return lookupHostByName(host).clone(); 274 } else { 275 return lookupHostByName(host); 276 } 277 } 278 279 byte[] hBytes = Inet6Util.createByteArrayFromIPAddressString(host); 280 if (hBytes.length == 4) { 281 return (new InetAddress[] { new Inet4Address(hBytes) }); 282 } else if (hBytes.length == 16) { 283 return (new InetAddress[] { new Inet6Address(hBytes) }); 284 } 285 return (new InetAddress[] { new InetAddress(hBytes) }); 286 } 287 // END android-added 288 289 /** 290 * Returns the address of a host according to the given host string name 291 * {@code host}. The host string may be either a machine name or a dotted 292 * string IP address. If the latter, the {@code hostName} field is 293 * determined upon demand. {@code host} can be {@code null} which means that 294 * an address of the loopback interface is returned. 295 * 296 * @param host 297 * the hostName to be resolved to an address or {@code null}. 298 * @return the {@code InetAddress} instance representing the host. 299 * @throws UnknownHostException 300 * if the address lookup fails. 301 */ 302 public static InetAddress getByName(String host) throws UnknownHostException { 303 return getAllByNameImpl(host, false)[0]; 304 } 305 306 /** 307 * Gets the textual representation of this IP address. 308 * 309 * @return the textual representation of this host address in form of a 310 * dotted string. 311 */ 312 public String getHostAddress() { 313 return inetNtoaImpl(bytesToInt(ipaddress, 0)); 314 } 315 316 /** 317 * Gets the host name of this IP address. If the IP address could not be 318 * resolved, the textual representation in a dotted-quad-notation is 319 * returned. 320 * 321 * @return the corresponding string name of this IP address. 322 */ 323 public String getHostName() { 324 try { 325 if (hostName == null) { 326 int address = 0; 327 if (ipaddress.length == 4) { 328 address = bytesToInt(ipaddress, 0); 329 if (address == 0) { 330 return hostName = inetNtoaImpl(address); 331 } 332 } 333 hostName = getHostByAddrImpl(ipaddress).hostName; 334 if (hostName.equals("localhost") && ipaddress.length == 4 //$NON-NLS-1$ 335 && address != 0x7f000001) { 336 return hostName = inetNtoaImpl(address); 337 } 338 } 339 } catch (UnknownHostException e) { 340 return hostName = Inet6Util 341 .createIPAddrStringFromByteArray(ipaddress); 342 } 343 SecurityManager security = System.getSecurityManager(); 344 try { 345 // Only check host names, not addresses 346 if (security != null && isHostName(hostName)) { 347 security.checkConnect(hostName, -1); 348 } 349 } catch (SecurityException e) { 350 return Inet6Util.createIPAddrStringFromByteArray(ipaddress); 351 } 352 return hostName; 353 } 354 355 /** 356 * Gets the fully qualified domain name for the host associated with this IP 357 * address. If a security manager is set, it is checked if the method caller 358 * is allowed to get the hostname. Otherwise, the textual representation in 359 * a dotted-quad-notation is returned. 360 * 361 * @return the fully qualified domain name of this IP address. 362 */ 363 public String getCanonicalHostName() { 364 String canonicalName; 365 try { 366 int address = 0; 367 if (ipaddress.length == 4) { 368 address = bytesToInt(ipaddress, 0); 369 if (address == 0) { 370 return inetNtoaImpl(address); 371 } 372 } 373 canonicalName = getHostByAddrImpl(ipaddress).hostName; 374 } catch (UnknownHostException e) { 375 return Inet6Util.createIPAddrStringFromByteArray(ipaddress); 376 } 377 SecurityManager security = System.getSecurityManager(); 378 try { 379 // Only check host names, not addresses 380 if (security != null && isHostName(canonicalName)) { 381 security.checkConnect(canonicalName, -1); 382 } 383 } catch (SecurityException e) { 384 return Inet6Util.createIPAddrStringFromByteArray(ipaddress); 385 } 386 return canonicalName; 387 } 388 389 /** 390 * Gets the local host address if the security policy allows this. 391 * Otherwise, gets the loopback address which allows this machine to be 392 * contacted. 393 * 394 * @return the {@code InetAddress} representing the local host. 395 * @throws UnknownHostException 396 * if the address lookup fails. 397 */ 398 public static InetAddress getLocalHost() throws UnknownHostException { 399 String host = getHostNameImpl(); 400 SecurityManager security = System.getSecurityManager(); 401 try { 402 if (security != null) { 403 security.checkConnect(host, -1); 404 } 405 } catch (SecurityException e) { 406 return InetAddress.LOOPBACK; 407 } 408 return lookupHostByName(host)[0]; 409 } 410 411 /** 412 * Gets the hashcode of the represented IP address. 413 * 414 * @return the appropriate hashcode value. 415 */ 416 @Override 417 public int hashCode() { 418 return bytesToInt(ipaddress, 0); 419 } 420 421 /** 422 * Returns whether this address is an IP multicast address or not. 423 * 424 * @return {@code true} if this address is in the multicast group, {@code 425 * false} otherwise. 426 */ 427 public boolean isMulticastAddress() { 428 return ((ipaddress[0] & 255) >>> 4) == 0xE; 429 } 430 431 /** 432 * Resolves a hostname to its IP addresses using a cache for faster lookups. 433 * 434 * @param host the hostname to resolve. 435 * @return the IP addresses of the host. 436 */ 437 static synchronized InetAddress[] lookupHostByName(String host) 438 throws UnknownHostException { 439 int ttl = -1; 440 441 // BEGIN android-changed 442 String ttlValue = AccessController 443 .doPrivileged(new PriviAction<String>( 444 "networkaddress.cache.ttl", DEFAULT_NETADDR_CACHE_TTL_SECS)); //$NON-NLS-1$ 445 // END android-changed 446 try { 447 if (ttlValue != null) { 448 ttl = Integer.decode(ttlValue).intValue(); 449 } 450 } catch (NumberFormatException e) { 451 // Ignored 452 } 453 CacheElement element = null; 454 // BEGIN android-changed 455 if (ttl == 0) { 456 Cache.clear(); 457 } else { 458 element = Cache.get(host); 459 if (element != null && ttl > 0) { 460 long delta = System.nanoTime() - element.nanoTimeAdded; 461 if (delta > secondsToNanos(ttl)) { 462 element = null; 463 } 464 } 465 } 466 if (element != null) { 467 return element.addresses(); 468 } 469 // END android-changed 470 471 // TODO Clean up NegativeCache; there's no need to maintain the failure message 472 473 // now try the negative cache 474 String failedMessage = NegativeCache.getFailedMessage(host); 475 if (failedMessage != null) { 476 throw new UnknownHostException(host); 477 } 478 479 // BEGIN android-changed 480 // TODO: Avoid doing I/O from a static synchronized lock. 481 byte[][] rawAddresses; 482 try { 483 rawAddresses = getallbyname(host, Socket.preferIPv4Stack()); 484 } catch (UnknownHostException e) { 485 // put the entry in the negative cache 486 NegativeCache.put(host, e.getMessage()); 487 // use host for message to match RI, save the cause for giggles 488 throw (UnknownHostException)new UnknownHostException(host).initCause(e); 489 } 490 491 InetAddress[] addresses = bytesToInetAddresses(rawAddresses, host); 492 493 Cache.add(host, addresses); 494 return addresses; 495 // END android-changed 496 } 497 498 // BEGIN android-added 499 /** 500 * Multiplies value by 1 billion. 501 */ 502 private static long secondsToNanos(int ttl) { 503 return (long) ttl * 1000000000; 504 } 505 // END android-added 506 507 // BEGIN android-deleted 508 // static native InetAddress[] getAliasesByNameImpl(String name) 509 // throws UnknownHostException; 510 // END android-deleted 511 512 // BEGIN android-added 513 /** 514 * Resolves a host name to its IP addresses. Thread safe. 515 */ 516 private static native byte[][] getallbyname(String name, 517 boolean preferIPv4Stack) throws UnknownHostException; 518 // END android-added 519 520 /** 521 * Query the IP stack for the host address. The host is in address form. 522 * 523 * @param addr 524 * the host address to lookup. 525 * @throws UnknownHostException 526 * if an error occurs during lookup. 527 */ 528 // BEGIN android-changed 529 // static native InetAddress getHostByAddrImpl(byte[] addr) 530 // throws UnknownHostException; 531 static InetAddress getHostByAddrImpl(byte[] addr) 532 throws UnknownHostException { 533 return new InetAddress(addr, gethostbyaddr(addr)); 534 } 535 536 /** 537 * Resolves an IP address to a hostname. Thread safe. 538 */ 539 private static native String gethostbyaddr(byte[] addr); 540 // END android-changed 541 542 static int inetAddr(String host) throws UnknownHostException { 543 return (host.equals("255.255.255.255")) ? 0xFFFFFFFF //$NON-NLS-1$ 544 : inetAddrImpl(host); 545 } 546 547 /** 548 * Convert a string containing an IPv4 Internet Protocol dotted address into 549 * a binary address. Note, the special case of '255.255.255.255' throws an 550 * exception, so this value should not be used as an argument. See also 551 * inetAddr(String). 552 */ 553 // BEGIN android-changed 554 // static native int inetAddrImpl(String host) throws UnknownHostException; 555 static int inetAddrImpl(String host) throws UnknownHostException { 556 // TODO Probably not exactly what we want, and also inefficient. Provide native later. 557 try { 558 String[] args = host.split("\\."); 559 560 int a = Integer.parseInt(args[0]) << 24; 561 int b = Integer.parseInt(args[1]) << 16; 562 int c = Integer.parseInt(args[2]) << 8; 563 int d = Integer.parseInt(args[3]) ; 564 565 return a | b | c | d; 566 } catch (Exception ex) { 567 throw new UnknownHostException(host); 568 } 569 } 570 // END android-changed 571 572 /** 573 * Convert a binary address into a string containing an Ipv4 Internet 574 * Protocol dotted address. 575 */ 576 // BEGIN android-changed 577 // static native String inetNtoaImpl(int hipAddr); 578 static String inetNtoaImpl(int hipAddr) { 579 // TODO Inefficient and probably wrong. Provide proper (native?) implementation later. 580 int a = (hipAddr >> 24) & 0xFF; 581 int b = (hipAddr >> 16) & 0xFF; 582 int c = (hipAddr >> 8) & 0xFF; 583 int d = (hipAddr ) & 0xFF; 584 585 return "" + a + "." + b + "." + c + "." + d; 586 } 587 // END android-changed 588 589 // BEGIN android-removed 590 /** 591 * Query the IP stack for the host address. The host is in string name form. 592 * 593 * @param name 594 * the host name to lookup 595 * @param preferIPv6Address 596 * address preference if underlying platform is V4/V6 597 * @return InetAddress the host address 598 * @throws UnknownHostException 599 * if an error occurs during lookup 600 */ 601 // static native InetAddress getHostByNameImpl(String name, 602 // boolean preferIPv6Address) throws UnknownHostException; 603 // END android-removed 604 605 /** 606 * Gets the host name of the system. 607 * 608 * @return String the system hostname 609 */ 610 // BEGIN android-changed 611 static String getHostNameImpl() { 612 // TODO Mapped Harmony to Android native. Get rid of indirection later. 613 614 return gethostname(); 615 } 616 static native String gethostname(); 617 // END android-changed 618 619 static String getHostNameInternal(String host) throws UnknownHostException { 620 if (host == null || 0 == host.length()) { 621 return InetAddress.LOOPBACK.getHostAddress(); 622 } 623 if (isHostName(host)) { 624 return lookupHostByName(host)[0].getHostAddress(); 625 } 626 return host; 627 } 628 629 /** 630 * Returns a string containing a concise, human-readable description of this 631 * IP address. 632 * 633 * @return the description, as host/address. 634 */ 635 @Override 636 public String toString() { 637 return (hostName == null ? "" : hostName) + "/" + getHostAddress(); //$NON-NLS-1$ //$NON-NLS-2$ 638 } 639 640 // BEGIN android-changed 641 // Partly copied from a newer version of harmony 642 static class CacheElement { 643 final long nanoTimeAdded = System.nanoTime(); 644 645 CacheElement next; 646 final String hostName; 647 final InetAddress[] addresses; 648 649 CacheElement(String hostName, InetAddress[] addresses) { 650 this.addresses = addresses; 651 this.hostName = hostName; 652 } 653 654 String hostName() { 655 return hostName; 656 } 657 658 InetAddress[] addresses() { 659 return addresses; 660 } 661 // END android-changed 662 } 663 664 static class Cache { 665 private static int maxSize = 5; 666 667 private static int size = 0; 668 669 private static CacheElement head; 670 671 static synchronized void clear() { 672 size = 0; 673 head = null; 674 } 675 676 static synchronized void add(String hostName, InetAddress[] addresses) { 677 CacheElement newElement = new CacheElement(hostName, addresses); 678 if (size < maxSize) { 679 size++; 680 } else { 681 deleteTail(); 682 } 683 newElement.next = head; // If the head is null, this does no harm. 684 head = newElement; 685 } 686 687 static synchronized CacheElement get(String name) { 688 CacheElement previous = null; 689 CacheElement current = head; 690 boolean notFound = true; 691 while ((null != current) 692 && (notFound = !(name.equals(current.hostName())))) { 693 previous = current; 694 current = current.next; 695 } 696 if (notFound) { 697 return null; 698 } 699 moveToHead(current, previous); 700 return current; 701 } 702 703 private synchronized static void deleteTail() { 704 if (0 == size) { 705 return; 706 } 707 if (1 == size) { 708 head = null; 709 } 710 711 CacheElement previous = null; 712 CacheElement current = head; 713 while (null != current.next) { 714 previous = current; 715 current = current.next; 716 } 717 previous.next = null; 718 } 719 720 private synchronized static void moveToHead(CacheElement element, 721 CacheElement elementPredecessor) { 722 if (null == elementPredecessor) { 723 head = element; 724 } else { 725 elementPredecessor.next = element.next; 726 element.next = head; 727 head = element; 728 } 729 } 730 } 731 732 /** 733 * Returns true if the string is a host name, false if it is an IP Address. 734 */ 735 private static boolean isHostName(String value) { 736 return !(Inet6Util.isValidIPV4Address(value) || Inet6Util 737 .isValidIP6Address(value)); 738 } 739 740 /** 741 * Returns whether this address is a loopback address or not. This 742 * implementation returns always {@code false}. Valid IPv4 loopback 743 * addresses are 127.d.d.d The only valid IPv6 loopback address is ::1. 744 * 745 * @return {@code true} if this instance represents a loopback address, 746 * {@code false} otherwise. 747 */ 748 public boolean isLoopbackAddress() { 749 return false; 750 } 751 752 /** 753 * Returns whether this address is a link-local address or not. This 754 * implementation returns always {@code false}. 755 * <p> 756 * Valid IPv6 link-local addresses are FE80::0 through to 757 * FEBF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF. 758 * <p> 759 * There are no valid IPv4 link-local addresses. 760 * 761 * @return {@code true} if this instance represents a link-local address, 762 * {@code false} otherwise. 763 */ 764 public boolean isLinkLocalAddress() { 765 return false; 766 } 767 768 /** 769 * Returns whether this address is a site-local address or not. This 770 * implementation returns always {@code false}. 771 * <p> 772 * Valid IPv6 site-local addresses are FEC0::0 through to 773 * FEFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF. 774 * <p> 775 * There are no valid IPv4 site-local addresses. 776 * 777 * @return {@code true} if this instance represents a site-local address, 778 * {@code false} otherwise. 779 */ 780 public boolean isSiteLocalAddress() { 781 return false; 782 } 783 784 /** 785 * Returns whether this address is a global multicast address or not. This 786 * implementation returns always {@code false}. 787 * <p> 788 * Valid IPv6 link-global multicast addresses are FFxE:/112 where x is a set 789 * of flags, and the additional 112 bits make up the global multicast 790 * address space. 791 * <p> 792 * Valid IPv4 global multicast addresses are between: 224.0.1.0 to 793 * 238.255.255.255. 794 * 795 * @return {@code true} if this instance represents a global multicast 796 * address, {@code false} otherwise. 797 */ 798 public boolean isMCGlobal() { 799 return false; 800 } 801 802 /** 803 * Returns whether this address is a node-local multicast address or not. 804 * This implementation returns always {@code false}. 805 * <p> 806 * Valid IPv6 node-local multicast addresses are FFx1:/112 where x is a set 807 * of flags, and the additional 112 bits make up the node-local multicast 808 * address space. 809 * <p> 810 * There are no valid IPv4 node-local multicast addresses. 811 * 812 * @return {@code true} if this instance represents a node-local multicast 813 * address, {@code false} otherwise. 814 */ 815 public boolean isMCNodeLocal() { 816 return false; 817 } 818 819 /** 820 * Returns whether this address is a link-local multicast address or not. 821 * This implementation returns always {@code false}. 822 * <p> 823 * Valid IPv6 link-local multicast addresses are FFx2:/112 where x is a set 824 * of flags, and the additional 112 bits make up the link-local multicast 825 * address space. 826 * <p> 827 * Valid IPv4 link-local addresses are between: 224.0.0.0 to 224.0.0.255 828 * 829 * @return {@code true} if this instance represents a link-local multicast 830 * address, {@code false} otherwise. 831 */ 832 public boolean isMCLinkLocal() { 833 return false; 834 } 835 836 /** 837 * Returns whether this address is a site-local multicast address or not. 838 * This implementation returns always {@code false}. 839 * <p> 840 * Valid IPv6 site-local multicast addresses are FFx5:/112 where x is a set 841 * of flags, and the additional 112 bits make up the site-local multicast 842 * address space. 843 * <p> 844 * Valid IPv4 site-local addresses are between: 239.252.0.0 to 845 * 239.255.255.255 846 * 847 * @return {@code true} if this instance represents a site-local multicast 848 * address, {@code false} otherwise. 849 */ 850 public boolean isMCSiteLocal() { 851 return false; 852 } 853 854 /** 855 * Returns whether this address is a organization-local multicast address or 856 * not. This implementation returns always {@code false}. 857 * <p> 858 * Valid IPv6 organization-local multicast addresses are FFx8:/112 where x 859 * is a set of flags, and the additional 112 bits make up the 860 * organization-local multicast address space. 861 * <p> 862 * Valid IPv4 organization-local addresses are between: 239.192.0.0 to 863 * 239.251.255.255 864 * 865 * @return {@code true} if this instance represents a organization-local 866 * multicast address, {@code false} otherwise. 867 */ 868 public boolean isMCOrgLocal() { 869 return false; 870 } 871 872 /** 873 * Returns whether this is a wildcard address or not. This implementation 874 * returns always {@code false}. 875 * 876 * @return {@code true} if this instance represents a wildcard address, 877 * {@code false} otherwise. 878 */ 879 public boolean isAnyLocalAddress() { 880 return false; 881 } 882 883 /** 884 * Tries to reach this {@code InetAddress}. This method first tries to use 885 * ICMP <i>(ICMP ECHO REQUEST)</i>. When first step fails, a TCP connection 886 * on port 7 (Echo) of the remote host is established. 887 * 888 * @param timeout 889 * timeout in milliseconds before the test fails if no connection 890 * could be established. 891 * @return {@code true} if this address is reachable, {@code false} 892 * otherwise. 893 * @throws IOException 894 * if an error occurs during an I/O operation. 895 * @throws IllegalArgumentException 896 * if timeout is less than zero. 897 */ 898 public boolean isReachable(int timeout) throws IOException { 899 return isReachable(null, 0, timeout); 900 } 901 902 /** 903 * Tries to reach this {@code InetAddress}. This method first tries to use 904 * ICMP <i>(ICMP ECHO REQUEST)</i>. When first step fails, a TCP connection 905 * on port 7 (Echo) of the remote host is established. 906 * 907 * @param netif 908 * the network interface on which to connection should be 909 * established. 910 * @param ttl 911 * the maximum count of hops (time-to-live). 912 * @param timeout 913 * timeout in milliseconds before the test fails if no connection 914 * could be established. 915 * @return {@code true} if this address is reachable, {@code false} 916 * otherwise. 917 * @throws IOException 918 * if an error occurs during an I/O operation. 919 * @throws IllegalArgumentException 920 * if ttl or timeout is less than zero. 921 */ 922 public boolean isReachable(NetworkInterface netif, final int ttl, 923 final int timeout) throws IOException { 924 if (0 > ttl || 0 > timeout) { 925 throw new IllegalArgumentException(Msg.getString("K0051")); //$NON-NLS-1$ 926 } 927 boolean reachable = false; 928 if (null == netif) { 929 // network interface is null, binds to no address 930 // BEGIN android-changed 931 // reachable = NETIMPL.isReachableByICMP(this, null, ttl, timeout); 932 // if (!reachable) { 933 reachable = isReachableByTCP(this, null, timeout); 934 // } 935 // END android-changed 936 } else { 937 // Not Bind to any address 938 if (null == netif.addresses) { 939 return false; 940 } 941 // binds to all address on this NetworkInterface, tries ICMP ping 942 // first 943 // BEGIN android-changed 944 // reachable = isReachableByICMPUseMultiThread(netif, ttl, timeout); 945 // if (!reachable) { 946 // tries TCP echo if ICMP ping fails 947 reachable = isReachableByMultiThread(netif, ttl, timeout); 948 // } 949 // END adnroid-changed 950 } 951 return reachable; 952 } 953 954 /* 955 * Uses multi-Thread to try if isReachable, returns true if any of threads 956 * returns in time 957 */ 958 // BEGIN android-changed 959 private boolean isReachableByMultiThread(NetworkInterface netif, 960 final int ttl, final int timeout) 961 // END android-changed 962 throws IOException { 963 if (null == netif.addresses) { 964 return false; 965 } 966 Enumeration<InetAddress> addresses = netif.getInetAddresses(); 967 reached = false; 968 addrCount = netif.addresses.length; 969 boolean needWait = false; 970 while (addresses.hasMoreElements()) { 971 final InetAddress addr = addresses.nextElement(); 972 973 // loopback interface can only reach to local addresses 974 if (addr.isLoopbackAddress()) { 975 Enumeration<NetworkInterface> NetworkInterfaces = NetworkInterface 976 .getNetworkInterfaces(); 977 while (NetworkInterfaces.hasMoreElements()) { 978 NetworkInterface networkInterface = NetworkInterfaces 979 .nextElement(); 980 Enumeration<InetAddress> localAddresses = networkInterface 981 .getInetAddresses(); 982 while (localAddresses.hasMoreElements()) { 983 if (InetAddress.this.equals(localAddresses 984 .nextElement())) { 985 return true; 986 } 987 } 988 } 989 990 synchronized (waitReachable) { 991 addrCount--; 992 993 if (addrCount == 0) { 994 // if count equals zero, all thread 995 // expired,notifies main thread 996 waitReachable.notifyAll(); 997 } 998 } 999 continue; 1000 } 1001 1002 needWait = true; 1003 new Thread() { 1004 @Override 1005 public void run() { 1006 boolean threadReached = false; 1007 // BEGIN android-changed 1008 // if isICMP, tries ICMP ping, else TCP echo 1009 // if (isICMP) { 1010 // threadReached = NETIMPL.isReachableByICMP( 1011 // InetAddress.this, addr, ttl, timeout); 1012 // } else { 1013 try { 1014 threadReached = isReachableByTCP(addr, 1015 InetAddress.this, timeout); 1016 } catch (IOException e) { 1017 // do nothing 1018 } 1019 // } 1020 // END android-changed 1021 1022 synchronized (waitReachable) { 1023 if (threadReached) { 1024 // if thread reached this address, sets reached to 1025 // true and notifies main thread 1026 reached = true; 1027 waitReachable.notifyAll(); 1028 } else { 1029 addrCount--; 1030 if (0 == addrCount) { 1031 // if count equals zero, all thread 1032 // expired,notifies main thread 1033 waitReachable.notifyAll(); 1034 } 1035 } 1036 } 1037 } 1038 }.start(); 1039 } 1040 1041 if (needWait) { 1042 synchronized (waitReachable) { 1043 try { 1044 while (!reached && (addrCount != 0)) { 1045 // wait for notification 1046 waitReachable.wait(1000); 1047 } 1048 } catch (InterruptedException e) { 1049 // do nothing 1050 } 1051 return reached; 1052 } 1053 } 1054 1055 return false; 1056 } 1057 1058 // BEGIN android-removed 1059 // private boolean isReachableByICMPUseMultiThread(NetworkInterface netif, 1060 // int ttl, int timeout) throws IOException { 1061 // return isReachableByMultiThread(netif, ttl, timeout, true); 1062 // } 1063 // 1064 // private boolean isReachableByTCPUseMultiThread(NetworkInterface netif, 1065 // int ttl, int timeout) throws IOException { 1066 // return isReachableByMultiThread(netif, ttl, timeout, false); 1067 // } 1068 // END android-removed 1069 1070 private boolean isReachableByTCP(InetAddress dest, InetAddress source, 1071 int timeout) throws IOException { 1072 FileDescriptor fd = new FileDescriptor(); 1073 // define traffic only for parameter 1074 int traffic = 0; 1075 boolean reached = false; 1076 NETIMPL.createStreamSocket(fd, NetUtil.preferIPv4Stack()); 1077 try { 1078 if (null != source) { 1079 NETIMPL.bind(fd, source, 0); 1080 } 1081 NETIMPL.connectStreamWithTimeoutSocket(fd, 7, timeout, traffic, 1082 dest); 1083 reached = true; 1084 } catch (IOException e) { 1085 if (ERRMSG_CONNECTION_REFUSED.equals(e.getMessage())) { 1086 // Connection refused means the IP is reachable 1087 reached = true; 1088 } 1089 } 1090 1091 NETIMPL.socketClose(fd); 1092 1093 return reached; 1094 } 1095 1096 /** 1097 * Returns the {@code InetAddress} corresponding to the array of bytes. In 1098 * the case of an IPv4 address there must be exactly 4 bytes and for IPv6 1099 * exactly 16 bytes. If not, an {@code UnknownHostException} is thrown. 1100 * <p> 1101 * The IP address is not validated by a name service. 1102 * <p> 1103 * The high order byte is {@code ipAddress[0]}. 1104 * 1105 * @param ipAddress 1106 * is either a 4 (IPv4) or 16 (IPv6) byte long array. 1107 * @return an {@code InetAddress} instance representing the given IP address 1108 * {@code ipAddress}. 1109 * @throws UnknownHostException 1110 * if the given byte array has no valid length. 1111 */ 1112 public static InetAddress getByAddress(byte[] ipAddress) 1113 throws UnknownHostException { 1114 // simply call the method by the same name specifying the default scope 1115 // id of 0 1116 return getByAddress(ipAddress, 0); 1117 } 1118 1119 /** 1120 * Returns the {@code InetAddress} corresponding to the array of bytes. In 1121 * the case of an IPv4 address there must be exactly 4 bytes and for IPv6 1122 * exactly 16 bytes. If not, an {@code UnknownHostException} is thrown. The 1123 * IP address is not validated by a name service. The high order byte is 1124 * {@code ipAddress[0]}. 1125 * 1126 * @param ipAddress 1127 * either a 4 (IPv4) or 16 (IPv6) byte array. 1128 * @param scope_id 1129 * the scope id for an IPV6 scoped address. If not a scoped 1130 * address just pass in 0. 1131 * @return the InetAddress 1132 * @throws UnknownHostException 1133 */ 1134 static InetAddress getByAddress(byte[] ipAddress, int scope_id) 1135 throws UnknownHostException { 1136 byte[] copy_address; 1137 if (ipAddress != null && ipAddress.length == 4) { 1138 copy_address = new byte[4]; 1139 for (int i = 0; i < 4; i++) { 1140 copy_address[i] = ipAddress[i]; 1141 } 1142 return new Inet4Address(copy_address); 1143 } 1144 1145 if (ipAddress != null && ipAddress.length == 16) { 1146 // First check to see if the address is an IPv6-mapped 1147 // IPv4 address. If it is, then we can make it a IPv4 1148 // address, otherwise, we'll create an IPv6 address. 1149 if (isIPv4MappedAddress(ipAddress)) { 1150 copy_address = new byte[4]; 1151 for (int i = 0; i < 4; i++) { 1152 copy_address[i] = ipAddress[12 + i]; 1153 } 1154 return new Inet4Address(copy_address); 1155 } 1156 copy_address = ipAddress.clone(); 1157 return new Inet6Address(copy_address, scope_id); 1158 } 1159 1160 // K0339=Invalid IP Address is neither 4 or 16 bytes 1161 throw new UnknownHostException(Msg.getString("K0339")); //$NON-NLS-1$ 1162 } 1163 1164 private static boolean isIPv4MappedAddress(byte ipAddress[]) { 1165 // Check if the address matches ::FFFF:d.d.d.d 1166 // The first 10 bytes are 0. The next to are -1 (FF). 1167 // The last 4 bytes are varied. 1168 for (int i = 0; i < 10; i++) { 1169 if (ipAddress[i] != 0) { 1170 return false; 1171 } 1172 } 1173 1174 if (ipAddress[10] != -1 || ipAddress[11] != -1) { 1175 return false; 1176 } 1177 1178 return true; 1179 } 1180 1181 /** 1182 * Returns the {@code InetAddress} corresponding to the array of bytes, and 1183 * the given hostname. In the case of an IPv4 address there must be exactly 1184 * 4 bytes and for IPv6 exactly 16 bytes. If not, an {@code 1185 * UnknownHostException} will be thrown. 1186 * <p> 1187 * The host name and IP address are not validated. 1188 * <p> 1189 * The hostname either be a machine alias or a valid IPv6 or IPv4 address 1190 * format. 1191 * <p> 1192 * The high order byte is {@code ipAddress[0]}. 1193 * 1194 * @param hostName 1195 * the string representation of hostname or IP address. 1196 * @param ipAddress 1197 * either a 4 (IPv4) or 16 (IPv6) byte long array. 1198 * @return an {@code InetAddress} instance representing the given IP address 1199 * and hostname. 1200 * @throws UnknownHostException 1201 * if the given byte array has no valid length. 1202 */ 1203 public static InetAddress getByAddress(String hostName, byte[] ipAddress) 1204 throws UnknownHostException { 1205 // just call the method by the same name passing in a default scope id 1206 // of 0 1207 return getByAddressInternal(hostName, ipAddress, 0); 1208 } 1209 1210 /** 1211 * Returns the {@code InetAddress} corresponding to the array of bytes, and 1212 * the given hostname. In the case of an IPv4 address there must be exactly 1213 * 4 bytes and for IPv6 exactly 16 bytes. If not, an {@code 1214 * UnknownHostException} is thrown. The host name and IP address are not 1215 * validated. The hostname either be a machine alias or a valid IPv6 or IPv4 1216 * address format. The high order byte is {@code ipAddress[0]}. 1217 * 1218 * @param hostName 1219 * string representation of hostname or IP address. 1220 * @param ipAddress 1221 * either a 4 (IPv4) or 16 (IPv6) byte array. 1222 * @param scope_id 1223 * the scope id for a scoped address. If not a scoped address 1224 * just pass in 0. 1225 * @return the InetAddress 1226 * @throws UnknownHostException 1227 */ 1228 static InetAddress getByAddressInternal(String hostName, byte[] ipAddress, 1229 int scope_id) throws UnknownHostException { 1230 byte[] copy_address; 1231 if (ipAddress != null && ipAddress.length == 4) { 1232 copy_address = new byte[4]; 1233 for (int i = 0; i < 4; i++) { 1234 copy_address[i] = ipAddress[i]; 1235 } 1236 return new Inet4Address(ipAddress, hostName); 1237 } 1238 1239 if (ipAddress != null && ipAddress.length == 16) { 1240 // First check to see if the address is an IPv6-mapped 1241 // IPv4 address. If it is, then we can make it a IPv4 1242 // address, otherwise, we'll create an IPv6 address. 1243 if (isIPv4MappedAddress(ipAddress)) { 1244 copy_address = new byte[4]; 1245 for (int i = 0; i < 4; i++) { 1246 copy_address[i] = ipAddress[12 + i]; 1247 } 1248 return new Inet4Address(ipAddress, hostName); 1249 } 1250 1251 copy_address = new byte[16]; 1252 for (int i = 0; i < 16; i++) { 1253 copy_address[i] = ipAddress[i]; 1254 } 1255 1256 return new Inet6Address(ipAddress, hostName, scope_id); 1257 } 1258 1259 throw new UnknownHostException(Msg.getString("K0332", hostName)); //$NON-NLS-1$ 1260 } 1261 1262 /** 1263 * Takes the integer and chops it into 4 bytes, putting it into the byte 1264 * array starting with the high order byte at the index start. This method 1265 * makes no checks on the validity of the parameters. 1266 */ 1267 static void intToBytes(int value, byte bytes[], int start) { 1268 // Shift the int so the current byte is right-most 1269 // Use a byte mask of 255 to single out the last byte. 1270 bytes[start] = (byte) ((value >> 24) & 255); 1271 bytes[start + 1] = (byte) ((value >> 16) & 255); 1272 bytes[start + 2] = (byte) ((value >> 8) & 255); 1273 bytes[start + 3] = (byte) (value & 255); 1274 } 1275 1276 /** 1277 * Takes the byte array and creates an integer out of four bytes starting at 1278 * start as the high-order byte. This method makes no checks on the validity 1279 * of the parameters. 1280 */ 1281 static int bytesToInt(byte bytes[], int start) { 1282 // First mask the byte with 255, as when a negative 1283 // signed byte converts to an integer, it has bits 1284 // on in the first 3 bytes, we are only concerned 1285 // about the right-most 8 bits. 1286 // Then shift the rightmost byte to align with its 1287 // position in the integer. 1288 int value = ((bytes[start + 3] & 255)) 1289 | ((bytes[start + 2] & 255) << 8) 1290 | ((bytes[start + 1] & 255) << 16) 1291 | ((bytes[start] & 255) << 24); 1292 return value; 1293 } 1294 1295 /** 1296 * Creates an InetAddress based on the {@code ipAddressString}. No error 1297 * handling is performed here. 1298 */ 1299 static InetAddress createHostNameFromIPAddress(String ipAddressString) 1300 throws UnknownHostException { 1301 1302 InetAddress address = null; 1303 1304 if (Inet6Util.isValidIPV4Address(ipAddressString)) { 1305 byte[] byteAddress = new byte[4]; 1306 String[] parts = ipAddressString.split("\\."); //$NON-NLS-1$ 1307 int length = parts.length; 1308 if (length == 1) { 1309 long value = Long.parseLong(parts[0]); 1310 for (int i = 0; i < 4; i++) { 1311 byteAddress[i] = (byte) (value >> ((3 - i) * 8)); 1312 } 1313 } else { 1314 for (int i = 0; i < length; i++) { 1315 byteAddress[i] = (byte) Integer.parseInt(parts[i]); 1316 } 1317 } 1318 1319 // adjust for 2/3 parts address 1320 if (length == 2) { 1321 byteAddress[3] = byteAddress[1]; 1322 byteAddress[1] = 0; 1323 } 1324 if (length == 3) { 1325 byteAddress[3] = byteAddress[2]; 1326 byteAddress[2] = 0; 1327 } 1328 1329 address = new Inet4Address(byteAddress); 1330 } else { // otherwise it must be ipv6 1331 1332 if (ipAddressString.charAt(0) == '[') { 1333 ipAddressString = ipAddressString.substring(1, ipAddressString 1334 .length() - 1); 1335 } 1336 1337 StringTokenizer tokenizer = new StringTokenizer(ipAddressString, 1338 ":.%", true); //$NON-NLS-1$ 1339 ArrayList<String> hexStrings = new ArrayList<String>(); 1340 ArrayList<String> decStrings = new ArrayList<String>(); 1341 String scopeString = null; 1342 String token = ""; //$NON-NLS-1$ 1343 String prevToken = ""; //$NON-NLS-1$ 1344 String prevPrevToken = ""; //$NON-NLS-1$ 1345 int doubleColonIndex = -1; // If a double colon exists, we need to 1346 // insert 0s. 1347 1348 // Go through the tokens, including the separators ':' and '.' 1349 // When we hit a : or . the previous token will be added to either 1350 // the hex list or decimal list. In the case where we hit a :: 1351 // we will save the index of the hexStrings so we can add zeros 1352 // in to fill out the string 1353 while (tokenizer.hasMoreTokens()) { 1354 prevPrevToken = prevToken; 1355 prevToken = token; 1356 token = tokenizer.nextToken(); 1357 1358 if (token.equals(":")) { //$NON-NLS-1$ 1359 if (prevToken.equals(":")) { //$NON-NLS-1$ 1360 doubleColonIndex = hexStrings.size(); 1361 } else if (!prevToken.equals("")) { //$NON-NLS-1$ 1362 hexStrings.add(prevToken); 1363 } 1364 } else if (token.equals(".")) { //$NON-NLS-1$ 1365 decStrings.add(prevToken); 1366 } else if (token.equals("%")) { //$NON-NLS-1$ 1367 // add the last word before the % properly 1368 if (!prevToken.equals(":") && !prevToken.equals(".")) { //$NON-NLS-1$ //$NON-NLS-2$ 1369 if (prevPrevToken.equals(":")) { //$NON-NLS-1$ 1370 hexStrings.add(prevToken); 1371 } else if (prevPrevToken.equals(".")) { //$NON-NLS-1$ 1372 decStrings.add(prevToken); 1373 } 1374 } 1375 1376 // the rest should be the scope string 1377 scopeString = tokenizer.nextToken(); 1378 while (tokenizer.hasMoreTokens()) { 1379 scopeString = scopeString + tokenizer.nextToken(); 1380 } 1381 } 1382 } 1383 1384 if (prevToken.equals(":")) { //$NON-NLS-1$ 1385 if (token.equals(":")) { //$NON-NLS-1$ 1386 doubleColonIndex = hexStrings.size(); 1387 } else { 1388 hexStrings.add(token); 1389 } 1390 } else if (prevToken.equals(".")) { //$NON-NLS-1$ 1391 decStrings.add(token); 1392 } 1393 1394 // figure out how many hexStrings we should have 1395 // also check if it is a IPv4 address 1396 int hexStringsLength = 8; 1397 1398 // If we have an IPv4 address tagged on at the end, subtract 1399 // 4 bytes, or 2 hex words from the total 1400 if (decStrings.size() > 0) { 1401 hexStringsLength -= 2; 1402 } 1403 1404 // if we hit a double Colon add the appropriate hex strings 1405 if (doubleColonIndex != -1) { 1406 int numberToInsert = hexStringsLength - hexStrings.size(); 1407 for (int i = 0; i < numberToInsert; i++) { 1408 hexStrings.add(doubleColonIndex, "0"); //$NON-NLS-1$ 1409 } 1410 } 1411 1412 byte ipByteArray[] = new byte[16]; 1413 1414 // Finally convert these strings to bytes... 1415 for (int i = 0; i < hexStrings.size(); i++) { 1416 Inet6Util.convertToBytes(hexStrings.get(i), ipByteArray, i * 2); 1417 } 1418 1419 // Now if there are any decimal values, we know where they go... 1420 for (int i = 0; i < decStrings.size(); i++) { 1421 ipByteArray[i + 12] = (byte) (Integer.parseInt(decStrings 1422 .get(i)) & 255); 1423 } 1424 1425 // now check to see if this guy is actually and IPv4 address 1426 // an ipV4 address is ::FFFF:d.d.d.d 1427 boolean ipV4 = true; 1428 for (int i = 0; i < 10; i++) { 1429 if (ipByteArray[i] != 0) { 1430 ipV4 = false; 1431 break; 1432 } 1433 } 1434 1435 if (ipByteArray[10] != -1 || ipByteArray[11] != -1) { 1436 ipV4 = false; 1437 } 1438 1439 if (ipV4) { 1440 byte ipv4ByteArray[] = new byte[4]; 1441 for (int i = 0; i < 4; i++) { 1442 ipv4ByteArray[i] = ipByteArray[i + 12]; 1443 } 1444 address = InetAddress.getByAddress(ipv4ByteArray); 1445 } else { 1446 int scopeId = 0; 1447 if (scopeString != null) { 1448 try { 1449 scopeId = Integer.parseInt(scopeString); 1450 } catch (Exception e) { 1451 // this should not occur as we should not get into this 1452 // function unless the address is in a valid format 1453 } 1454 } 1455 address = InetAddress.getByAddress(ipByteArray, scopeId); 1456 } 1457 } 1458 1459 return address; 1460 } 1461 1462 static boolean preferIPv6Addresses() { 1463 String result = AccessController.doPrivileged(new PriviAction<String>( 1464 "java.net.preferIPv6Addresses")); //$NON-NLS-1$ 1465 return "true".equals(result); //$NON-NLS-1$ 1466 } 1467 1468 private static final ObjectStreamField[] serialPersistentFields = { 1469 new ObjectStreamField("address", Integer.TYPE), //$NON-NLS-1$ 1470 new ObjectStreamField("family", Integer.TYPE), //$NON-NLS-1$ 1471 new ObjectStreamField("hostName", String.class) }; //$NON-NLS-1$ 1472 1473 private void writeObject(ObjectOutputStream stream) throws IOException { 1474 ObjectOutputStream.PutField fields = stream.putFields(); 1475 if (ipaddress == null) { 1476 fields.put("address", 0); //$NON-NLS-1$ 1477 } else { 1478 fields.put("address", bytesToInt(ipaddress, 0)); //$NON-NLS-1$ 1479 } 1480 fields.put("family", family); //$NON-NLS-1$ 1481 fields.put("hostName", hostName); //$NON-NLS-1$ 1482 1483 stream.writeFields(); 1484 } 1485 1486 private void readObject(ObjectInputStream stream) throws IOException, 1487 ClassNotFoundException { 1488 ObjectInputStream.GetField fields = stream.readFields(); 1489 int addr = fields.get("address", 0); //$NON-NLS-1$ 1490 ipaddress = new byte[4]; 1491 intToBytes(addr, ipaddress, 0); 1492 hostName = (String) fields.get("hostName", null); //$NON-NLS-1$ 1493 family = fields.get("family", 2); //$NON-NLS-1$ 1494 } 1495 1496 private Object readResolve() throws ObjectStreamException { 1497 return new Inet4Address(ipaddress, hostName); 1498 } 1499} 1500