1 /* 2 * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.net; 27 28 import android.system.ErrnoException; 29 30 import java.io.FileDescriptor; 31 import java.util.ArrayList; 32 import java.util.Arrays; 33 import java.util.Collections; 34 import java.util.Enumeration; 35 import java.util.HashMap; 36 import java.util.List; 37 import java.util.Map; 38 import java.util.NoSuchElementException; 39 40 import android.system.StructIfaddrs; 41 import libcore.io.IoUtils; 42 import libcore.io.Libcore; 43 import sun.security.action.*; 44 import java.security.AccessController; 45 46 import static android.system.OsConstants.*; 47 48 // Android-note: NetworkInterface has been rewritten to avoid native code. 49 // Fix upstream bug not returning link-down interfaces. http://b/26238832 50 // Android-added: Document restrictions for targetSdkVersion >= R. http://b/141455849 51 /** 52 * This class represents a Network Interface made up of a name, 53 * and a list of IP addresses assigned to this interface. 54 * It is used to identify the local interface on which a multicast group 55 * is joined. 56 * 57 * Interfaces are normally known by names such as "le0". 58 * <p> 59 * <a name="access-restrictions"></a>Note that information about 60 * {@link NetworkInterface}s may be restricted. For example, non-system apps 61 * with {@code targetSdkVersion >= android.os.Build.VERSION_CODES.R} will only 62 * have access to information about {@link NetworkInterface}s that are 63 * associated with an {@link InetAddress}. 64 * 65 * @since 1.4 66 */ 67 public final class NetworkInterface { 68 private String name; 69 private String displayName; 70 private int index; 71 private InetAddress addrs[]; 72 private InterfaceAddress bindings[]; 73 // Android-changed: Rewrote NetworkInterface on top of Libcore.io. 74 // private NetworkInterface childs[]; 75 private List<NetworkInterface> childs; 76 private NetworkInterface parent = null; 77 private boolean virtual = false; 78 private static final NetworkInterface defaultInterface; 79 private static final int defaultIndex; /* index of defaultInterface */ 80 81 // Android-changed: Fix upstream bug not returning link-down interfaces. http://b/26238832 82 private byte[] hardwareAddr; 83 84 static { 85 // Android-removed: Android doesn't need to call native init. 86 /* 87 AccessController.doPrivileged( 88 new java.security.PrivilegedAction<Void>() { 89 public Void run() { 90 System.loadLibrary("net"); 91 return null; 92 } 93 }); 94 95 init(); 96 */ 97 defaultInterface = DefaultInterface.getDefault(); 98 if (defaultInterface != null) { 99 defaultIndex = defaultInterface.getIndex(); 100 } else { 101 defaultIndex = 0; 102 } 103 } 104 105 /** 106 * Returns an NetworkInterface object with index set to 0 and name to null. 107 * Setting such an interface on a MulticastSocket will cause the 108 * kernel to choose one interface for sending multicast packets. 109 * 110 */ NetworkInterface()111 NetworkInterface() { 112 } 113 NetworkInterface(String name, int index, InetAddress[] addrs)114 NetworkInterface(String name, int index, InetAddress[] addrs) { 115 this.name = name; 116 this.index = index; 117 this.addrs = addrs; 118 } 119 120 /** 121 * Get the name of this network interface. 122 * 123 * @return the name of this network interface 124 */ getName()125 public String getName() { 126 return name; 127 } 128 129 /** 130 * Convenience method to return an Enumeration with all or a 131 * subset of the InetAddresses bound to this network interface. 132 * <p> 133 * If there is a security manager, its {@code checkConnect} 134 * method is called for each InetAddress. Only InetAddresses where 135 * the {@code checkConnect} doesn't throw a SecurityException 136 * will be returned in the Enumeration. However, if the caller has the 137 * {@link NetPermission}("getNetworkInformation") permission, then all 138 * InetAddresses are returned. 139 * @return an Enumeration object with all or a subset of the InetAddresses 140 * bound to this network interface 141 */ getInetAddresses()142 public Enumeration<InetAddress> getInetAddresses() { 143 144 class checkedAddresses implements Enumeration<InetAddress> { 145 146 private int i=0, count=0; 147 private InetAddress local_addrs[]; 148 149 checkedAddresses() { 150 local_addrs = new InetAddress[addrs.length]; 151 boolean trusted = true; 152 153 SecurityManager sec = System.getSecurityManager(); 154 if (sec != null) { 155 try { 156 sec.checkPermission(new NetPermission("getNetworkInformation")); 157 } catch (SecurityException e) { 158 trusted = false; 159 } 160 } 161 for (int j=0; j<addrs.length; j++) { 162 try { 163 if (sec != null && !trusted) { 164 sec.checkConnect(addrs[j].getHostAddress(), -1); 165 } 166 local_addrs[count++] = addrs[j]; 167 } catch (SecurityException e) { } 168 } 169 170 } 171 172 public InetAddress nextElement() { 173 if (i < count) { 174 return local_addrs[i++]; 175 } else { 176 throw new NoSuchElementException(); 177 } 178 } 179 180 public boolean hasMoreElements() { 181 return (i < count); 182 } 183 } 184 return new checkedAddresses(); 185 186 } 187 188 /** 189 * Get a List of all or a subset of the {@code InterfaceAddresses} 190 * of this network interface. 191 * <p> 192 * If there is a security manager, its {@code checkConnect} 193 * method is called with the InetAddress for each InterfaceAddress. 194 * Only InterfaceAddresses where the {@code checkConnect} doesn't throw 195 * a SecurityException will be returned in the List. 196 * 197 * @return a {@code List} object with all or a subset of the 198 * InterfaceAddresss of this network interface 199 * @since 1.6 200 */ getInterfaceAddresses()201 public java.util.List<InterfaceAddress> getInterfaceAddresses() { 202 java.util.List<InterfaceAddress> lst = new java.util.ArrayList<InterfaceAddress>(1); 203 // BEGIN Android-changed: Cherry-picked upstream OpenJDK9 change rev 59a110a38cea 204 // http://b/30628919 205 if (bindings != null) { 206 SecurityManager sec = System.getSecurityManager(); 207 for (int j=0; j<bindings.length; j++) { 208 try { 209 if (sec != null) { 210 sec.checkConnect(bindings[j].getAddress().getHostAddress(), -1); 211 } 212 lst.add(bindings[j]); 213 } catch (SecurityException e) { } 214 } 215 } 216 // END Android-changed: Cherry-picked upstream OpenJDK9 change rev 59a110a38cea 217 return lst; 218 } 219 220 /** 221 * Get an Enumeration with all the subinterfaces (also known as virtual 222 * interfaces) attached to this network interface. 223 * <p> 224 * For instance eth0:1 will be a subinterface to eth0. 225 * 226 * @return an Enumeration object with all of the subinterfaces 227 * of this network interface 228 * @since 1.6 229 */ getSubInterfaces()230 public Enumeration<NetworkInterface> getSubInterfaces() { 231 // Android-changed: Rewrote NetworkInterface on top of Libcore.io. 232 return Collections.enumeration(childs); 233 } 234 235 /** 236 * Returns the parent NetworkInterface of this interface if this is 237 * a subinterface, or {@code null} if it is a physical 238 * (non virtual) interface or has no parent. 239 * 240 * @return The {@code NetworkInterface} this interface is attached to. 241 * @since 1.6 242 */ getParent()243 public NetworkInterface getParent() { 244 return parent; 245 } 246 247 /** 248 * Returns the index of this network interface. The index is an integer greater 249 * or equal to zero, or {@code -1} for unknown. This is a system specific value 250 * and interfaces with the same name can have different indexes on different 251 * machines. 252 * 253 * @return the index of this network interface or {@code -1} if the index is 254 * unknown 255 * @see #getByIndex(int) 256 * @since 1.7 257 */ getIndex()258 public int getIndex() { 259 return index; 260 } 261 262 /** 263 * Get the display name of this network interface. 264 * A display name is a human readable String describing the network 265 * device. 266 * 267 * @return a non-empty string representing the display name of this network 268 * interface, or null if no display name is available. 269 */ getDisplayName()270 public String getDisplayName() { 271 /* strict TCK conformance */ 272 return "".equals(displayName) ? null : displayName; 273 } 274 275 // Android-added: Document restrictions for targetSdkVersion >= R. http://b/141455849 276 /** 277 * Searches for the network interface with the specified name. 278 * 279 * @param name 280 * The name of the network interface. 281 * 282 * @return A {@code NetworkInterface} with the specified name, 283 * or {@code null} if the network interface with the specified 284 * name does not exist or <a href="#access-restrictions">can't be 285 * accessed</a>. 286 * 287 * @throws SocketException 288 * If an I/O error occurs. 289 * 290 * @throws NullPointerException 291 * If the specified name is {@code null}. 292 */ getByName(String name)293 public static NetworkInterface getByName(String name) throws SocketException { 294 if (name == null) 295 throw new NullPointerException(); 296 297 // Android-changed: Rewrote NetworkInterface on top of Libcore.io. 298 NetworkInterface[] nis = getAll(); 299 for (NetworkInterface ni : nis) { 300 if (ni.getName().equals(name)) { 301 return ni; 302 } 303 } 304 return null; 305 } 306 307 // Android-added: Document restrictions for targetSdkVersion >= R. http://b/141455849 308 /** 309 * Get a network interface given its index. 310 * 311 * @param index an integer, the index of the interface 312 * @return the NetworkInterface obtained from its index, or {@code null} if 313 * an interface with the specified index does not exist or 314 * <a href="#access-restrictions">can't be accessed</a>. 315 * @throws SocketException if an I/O error occurs. 316 * @throws IllegalArgumentException if index has a negative value 317 * @see #getIndex() 318 * @since 1.7 319 */ getByIndex(int index)320 public static NetworkInterface getByIndex(int index) throws SocketException { 321 if (index < 0) 322 throw new IllegalArgumentException("Interface index can't be negative"); 323 324 // Android-changed: Rewrote NetworkInterface on top of Libcore.io. 325 NetworkInterface[] nis = getAll(); 326 for (NetworkInterface ni : nis) { 327 if (ni.getIndex() == index) { 328 return ni; 329 } 330 } 331 return null; 332 } 333 334 /** 335 * Convenience method to search for a network interface that 336 * has the specified Internet Protocol (IP) address bound to 337 * it. 338 * <p> 339 * If the specified IP address is bound to multiple network 340 * interfaces it is not defined which network interface is 341 * returned. 342 * 343 * @param addr 344 * The {@code InetAddress} to search with. 345 * 346 * @return A {@code NetworkInterface} 347 * or {@code null} if there is no network interface 348 * with the specified IP address. 349 * 350 * @throws SocketException 351 * If an I/O error occurs. 352 * 353 * @throws NullPointerException 354 * If the specified address is {@code null}. 355 */ getByInetAddress(InetAddress addr)356 public static NetworkInterface getByInetAddress(InetAddress addr) throws SocketException { 357 if (addr == null) { 358 throw new NullPointerException(); 359 } 360 if (!(addr instanceof Inet4Address || addr instanceof Inet6Address)) { 361 throw new IllegalArgumentException ("invalid address type"); 362 } 363 364 // Android-changed: Rewrote NetworkInterface on top of Libcore.io. 365 NetworkInterface[] nis = getAll(); 366 for (NetworkInterface ni : nis) { 367 for (InetAddress inetAddress : Collections.list(ni.getInetAddresses())) { 368 if (inetAddress.equals(addr)) { 369 return ni; 370 } 371 } 372 } 373 return null; 374 } 375 376 // Android-added: Document restrictions for targetSdkVersion >= R. http://b/141455849 377 /** 378 * Returns all the interfaces on this machine. The {@code Enumeration} 379 * contains at least one element, possibly representing a loopback 380 * interface that only supports communication between entities on 381 * this machine. 382 * 383 * NOTE: can use getNetworkInterfaces()+getInetAddresses() 384 * to obtain all IP addresses for this node 385 * <p> 386 * For non-system apps with 387 * {@code targetSdkVersion >= android.os.Build.VERSION_CODES.R}, this 388 * method will only return information for {@link NetworkInterface}s that 389 * are associated with an {@link InetAddress}. 390 * 391 * @return an Enumeration of NetworkInterfaces found on this machine 392 * that <a href="#access-restrictions">are accessible</a>. 393 * @exception SocketException if an I/O error occurs. 394 */ 395 getNetworkInterfaces()396 public static Enumeration<NetworkInterface> getNetworkInterfaces() 397 throws SocketException { 398 final NetworkInterface[] netifs = getAll(); 399 // Android-changed: Rewrote NetworkInterface on top of Libcore.io. 400 // // specified to return null if no network interfaces 401 // if (netifs == null) 402 if (netifs.length == 0) 403 return null; 404 405 // Android-changed: Rewrote NetworkInterface on top of Libcore.io. 406 /* 407 return new Enumeration<NetworkInterface>() { 408 private int i = 0; 409 public NetworkInterface nextElement() { 410 if (netifs != null && i < netifs.length) { 411 NetworkInterface netif = netifs[i++]; 412 return netif; 413 } else { 414 throw new NoSuchElementException(); 415 } 416 } 417 418 public boolean hasMoreElements() { 419 return (netifs != null && i < netifs.length); 420 } 421 }; 422 */ 423 return Collections.enumeration(Arrays.asList(netifs)); 424 } 425 426 // BEGIN Android-changed: Rewrote NetworkInterface on top of Libcore.io. 427 // private native static NetworkInterface[] getAll() 428 // throws SocketException; getAll()429 private static NetworkInterface[] getAll() throws SocketException { 430 // Group Ifaddrs by interface name. 431 Map<String, List<StructIfaddrs>> inetMap = new HashMap<>(); 432 433 StructIfaddrs[] ifaddrs; 434 try { 435 ifaddrs = Libcore.os.getifaddrs(); 436 } catch (ErrnoException e) { 437 throw e.rethrowAsSocketException(); 438 } 439 440 for (StructIfaddrs ifa : ifaddrs) { 441 String name = ifa.ifa_name; 442 443 List<StructIfaddrs> ifas; 444 if ((ifas = inetMap.get(name)) == null) { 445 ifas = new ArrayList<>(); 446 inetMap.put(name, ifas); 447 } 448 449 ifas.add(ifa); 450 } 451 452 // Populate NetworkInterface instances. 453 Map<String, NetworkInterface> nis = new HashMap<>(inetMap.size()); 454 for (Map.Entry<String, List<StructIfaddrs>> e : inetMap.entrySet()) { 455 String name = e.getKey(); 456 int index = Libcore.os.if_nametoindex(e.getKey()); 457 if (index == 0) { 458 // This interface has gone away between getifaddrs and if_nametoindex 459 continue; 460 } 461 462 NetworkInterface ni = new NetworkInterface(name, index, null); 463 ni.displayName = name; 464 465 List<InetAddress> addrs = new ArrayList<>(); 466 List<InterfaceAddress> binds = new ArrayList<>(); 467 468 for (StructIfaddrs ifa : e.getValue()) { 469 if (ifa.ifa_addr != null) { 470 addrs.add(ifa.ifa_addr); 471 binds.add(new InterfaceAddress(ifa.ifa_addr, (Inet4Address) ifa.ifa_broadaddr, 472 ifa.ifa_netmask)); 473 } 474 475 if (ifa.hwaddr != null) { 476 ni.hardwareAddr = ifa.hwaddr; 477 } 478 } 479 480 ni.addrs = addrs.toArray(new InetAddress[addrs.size()]); 481 ni.bindings = binds.toArray(new InterfaceAddress[binds.size()]); 482 ni.childs = new ArrayList<>(0); 483 nis.put(name, ni); 484 } 485 486 // Populate childs/parent. 487 for (Map.Entry<String, NetworkInterface> e : nis.entrySet()) { 488 NetworkInterface ni = e.getValue(); 489 String niName = ni.getName(); 490 int colonIdx = niName.indexOf(':'); 491 if (colonIdx != -1) { 492 // This is a virtual interface. 493 String parentName = niName.substring(0, colonIdx); 494 NetworkInterface parent = nis.get(parentName); 495 496 ni.virtual = true; 497 498 if (parent != null) { 499 ni.parent = parent; 500 parent.childs.add(ni); 501 } 502 } 503 } 504 505 return nis.values().toArray(new NetworkInterface[nis.size()]); 506 } 507 // END Android-changed: Rewrote NetworkInterface on top of Libcore.io. 508 509 /** 510 * Returns whether a network interface is up and running. 511 * 512 * @return {@code true} if the interface is up and running. 513 * @exception SocketException if an I/O error occurs. 514 * @since 1.6 515 */ 516 isUp()517 public boolean isUp() throws SocketException { 518 // Android-changed: Rewrote NetworkInterface on top of Libcore.io. 519 final int mask = IFF_UP | IFF_RUNNING; 520 return (getFlags() & mask) == mask; 521 } 522 523 /** 524 * Returns whether a network interface is a loopback interface. 525 * 526 * @return {@code true} if the interface is a loopback interface. 527 * @exception SocketException if an I/O error occurs. 528 * @since 1.6 529 */ 530 isLoopback()531 public boolean isLoopback() throws SocketException { 532 // Android-changed: Rewrote NetworkInterface on top of Libcore.io. 533 return (getFlags() & IFF_LOOPBACK) != 0; 534 } 535 536 /** 537 * Returns whether a network interface is a point to point interface. 538 * A typical point to point interface would be a PPP connection through 539 * a modem. 540 * 541 * @return {@code true} if the interface is a point to point 542 * interface. 543 * @exception SocketException if an I/O error occurs. 544 * @since 1.6 545 */ 546 isPointToPoint()547 public boolean isPointToPoint() throws SocketException { 548 // Android-changed: Rewrote NetworkInterface on top of Libcore.io. 549 return (getFlags() & IFF_POINTOPOINT) != 0; 550 } 551 552 /** 553 * Returns whether a network interface supports multicasting or not. 554 * 555 * @return {@code true} if the interface supports Multicasting. 556 * @exception SocketException if an I/O error occurs. 557 * @since 1.6 558 */ 559 supportsMulticast()560 public boolean supportsMulticast() throws SocketException { 561 // Android-changed: Rewrote NetworkInterface on top of Libcore.io. 562 return (getFlags() & IFF_MULTICAST) != 0; 563 } 564 565 // Android-added: Document restrictions for targetSdkVersion >= R. http://b/141455849 566 /** 567 * Returns the hardware address (usually MAC) of the interface if it 568 * has one and if it can be accessed given the current privileges. 569 * If a security manager is set, then the caller must have 570 * the permission {@link NetPermission}("getNetworkInformation"). 571 * 572 * @return a byte array containing the address, or {@code null} if 573 * the address doesn't exist, is not accessible or a security 574 * manager is set and the caller does not have the permission 575 * NetPermission("getNetworkInformation"). For example, this 576 * method will generally return {@code null} when called by 577 * non-system apps having 578 * {@code targetSdkVersion >= android.os.Build.VERSION_CODES.R}. 579 * 580 * @exception SocketException if an I/O error occurs. 581 * @since 1.6 582 */ getHardwareAddress()583 public byte[] getHardwareAddress() throws SocketException { 584 // BEGIN Android-changed: Fix upstream not returning link-down interfaces. http://b/26238832 585 /* 586 for (InetAddress addr : addrs) { 587 if (addr instanceof Inet4Address) { 588 return getMacAddr0(((Inet4Address)addr).getAddress(), name, index); 589 } 590 } 591 return getMacAddr0(null, name, index); 592 */ 593 NetworkInterface ni = getByName(name); 594 if (ni == null) { 595 throw new SocketException("NetworkInterface doesn't exist anymore"); 596 } 597 return ni.hardwareAddr; 598 // END Android-changed: Fix upstream not returning link-down interfaces. http://b/26238832 599 } 600 601 /** 602 * Returns the Maximum Transmission Unit (MTU) of this interface. 603 * 604 * @return the value of the MTU for that interface. 605 * @exception SocketException if an I/O error occurs. 606 * @since 1.6 607 */ getMTU()608 public int getMTU() throws SocketException { 609 // Android-changed: Rewrote NetworkInterface on top of Libcore.io. 610 // return getMTU0(name, index); 611 FileDescriptor fd = null; 612 try { 613 fd = Libcore.rawOs.socket(AF_INET, SOCK_DGRAM, 0); 614 return Libcore.rawOs.ioctlMTU(fd, name); 615 } catch (ErrnoException e) { 616 throw e.rethrowAsSocketException(); 617 } catch (Exception ex) { 618 throw new SocketException(ex); 619 } finally { 620 IoUtils.closeQuietly(fd); 621 } 622 } 623 624 /** 625 * Returns whether this interface is a virtual interface (also called 626 * subinterface). 627 * Virtual interfaces are, on some systems, interfaces created as a child 628 * of a physical interface and given different settings (like address or 629 * MTU). Usually the name of the interface will the name of the parent 630 * followed by a colon (:) and a number identifying the child since there 631 * can be several virtual interfaces attached to a single physical 632 * interface. 633 * 634 * @return {@code true} if this interface is a virtual interface. 635 * @since 1.6 636 */ isVirtual()637 public boolean isVirtual() { 638 return virtual; 639 } 640 641 // BEGIN Android-removed: Rewrote NetworkInterface on top of Libcore.io. 642 /* 643 private native static boolean isUp0(String name, int ind) throws SocketException; 644 private native static boolean isLoopback0(String name, int ind) throws SocketException; 645 private native static boolean supportsMulticast0(String name, int ind) throws SocketException; 646 private native static boolean isP2P0(String name, int ind) throws SocketException; 647 private native static byte[] getMacAddr0(byte[] inAddr, String name, int ind) throws SocketException; 648 private native static int getMTU0(String name, int ind) throws SocketException; 649 */ 650 // END Android-removed: Rewrote NetworkInterface on top of Libcore.io. 651 652 // BEGIN Android-added: Rewrote NetworkInterface on top of Libcore.io. getFlags()653 private int getFlags() throws SocketException { 654 FileDescriptor fd = null; 655 try { 656 fd = Libcore.rawOs.socket(AF_INET, SOCK_DGRAM, 0); 657 return Libcore.rawOs.ioctlFlags(fd, name); 658 } catch (ErrnoException e) { 659 throw e.rethrowAsSocketException(); 660 } catch (Exception ex) { 661 throw new SocketException(ex); 662 } finally { 663 IoUtils.closeQuietly(fd); 664 } 665 } 666 // END Android-added: Rewrote NetworkInterface on top of Libcore.io. 667 668 /** 669 * Compares this object against the specified object. 670 * The result is {@code true} if and only if the argument is 671 * not {@code null} and it represents the same NetworkInterface 672 * as this object. 673 * <p> 674 * Two instances of {@code NetworkInterface} represent the same 675 * NetworkInterface if both name and addrs are the same for both. 676 * 677 * @param obj the object to compare against. 678 * @return {@code true} if the objects are the same; 679 * {@code false} otherwise. 680 * @see java.net.InetAddress#getAddress() 681 */ equals(Object obj)682 public boolean equals(Object obj) { 683 if (!(obj instanceof NetworkInterface)) { 684 return false; 685 } 686 NetworkInterface that = (NetworkInterface)obj; 687 if (this.name != null ) { 688 if (!this.name.equals(that.name)) { 689 return false; 690 } 691 } else { 692 if (that.name != null) { 693 return false; 694 } 695 } 696 697 if (this.addrs == null) { 698 return that.addrs == null; 699 } else if (that.addrs == null) { 700 return false; 701 } 702 703 /* Both addrs not null. Compare number of addresses */ 704 705 if (this.addrs.length != that.addrs.length) { 706 return false; 707 } 708 709 InetAddress[] thatAddrs = that.addrs; 710 int count = thatAddrs.length; 711 712 for (int i=0; i<count; i++) { 713 boolean found = false; 714 for (int j=0; j<count; j++) { 715 if (addrs[i].equals(thatAddrs[j])) { 716 found = true; 717 break; 718 } 719 } 720 if (!found) { 721 return false; 722 } 723 } 724 return true; 725 } 726 hashCode()727 public int hashCode() { 728 return name == null? 0: name.hashCode(); 729 } 730 toString()731 public String toString() { 732 String result = "name:"; 733 result += name == null? "null": name; 734 if (displayName != null) { 735 result += " (" + displayName + ")"; 736 } 737 return result; 738 } 739 740 // Android-removed: Android doesn't need to call native init. 741 // private static native void init(); 742 743 /** 744 * Returns the default network interface of this system 745 * 746 * @return the default interface 747 */ getDefault()748 static NetworkInterface getDefault() { 749 return defaultInterface; 750 } 751 } 752