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 ni.parent = parent; 498 parent.childs.add(ni); 499 } 500 } 501 502 return nis.values().toArray(new NetworkInterface[nis.size()]); 503 } 504 // END Android-changed: Rewrote NetworkInterface on top of Libcore.io. 505 506 /** 507 * Returns whether a network interface is up and running. 508 * 509 * @return {@code true} if the interface is up and running. 510 * @exception SocketException if an I/O error occurs. 511 * @since 1.6 512 */ 513 isUp()514 public boolean isUp() throws SocketException { 515 // Android-changed: Rewrote NetworkInterface on top of Libcore.io. 516 final int mask = IFF_UP | IFF_RUNNING; 517 return (getFlags() & mask) == mask; 518 } 519 520 /** 521 * Returns whether a network interface is a loopback interface. 522 * 523 * @return {@code true} if the interface is a loopback interface. 524 * @exception SocketException if an I/O error occurs. 525 * @since 1.6 526 */ 527 isLoopback()528 public boolean isLoopback() throws SocketException { 529 // Android-changed: Rewrote NetworkInterface on top of Libcore.io. 530 return (getFlags() & IFF_LOOPBACK) != 0; 531 } 532 533 /** 534 * Returns whether a network interface is a point to point interface. 535 * A typical point to point interface would be a PPP connection through 536 * a modem. 537 * 538 * @return {@code true} if the interface is a point to point 539 * interface. 540 * @exception SocketException if an I/O error occurs. 541 * @since 1.6 542 */ 543 isPointToPoint()544 public boolean isPointToPoint() throws SocketException { 545 // Android-changed: Rewrote NetworkInterface on top of Libcore.io. 546 return (getFlags() & IFF_POINTOPOINT) != 0; 547 } 548 549 /** 550 * Returns whether a network interface supports multicasting or not. 551 * 552 * @return {@code true} if the interface supports Multicasting. 553 * @exception SocketException if an I/O error occurs. 554 * @since 1.6 555 */ 556 supportsMulticast()557 public boolean supportsMulticast() throws SocketException { 558 // Android-changed: Rewrote NetworkInterface on top of Libcore.io. 559 return (getFlags() & IFF_MULTICAST) != 0; 560 } 561 562 // Android-added: Document restrictions for targetSdkVersion >= R. http://b/141455849 563 /** 564 * Returns the hardware address (usually MAC) of the interface if it 565 * has one and if it can be accessed given the current privileges. 566 * If a security manager is set, then the caller must have 567 * the permission {@link NetPermission}("getNetworkInformation"). 568 * 569 * @return a byte array containing the address, or {@code null} if 570 * the address doesn't exist, is not accessible or a security 571 * manager is set and the caller does not have the permission 572 * NetPermission("getNetworkInformation"). For example, this 573 * method will generally return {@code null} when called by 574 * non-system apps having 575 * {@code targetSdkVersion >= android.os.Build.VERSION_CODES.R}. 576 * 577 * @exception SocketException if an I/O error occurs. 578 * @since 1.6 579 */ getHardwareAddress()580 public byte[] getHardwareAddress() throws SocketException { 581 // BEGIN Android-changed: Fix upstream not returning link-down interfaces. http://b/26238832 582 /* 583 for (InetAddress addr : addrs) { 584 if (addr instanceof Inet4Address) { 585 return getMacAddr0(((Inet4Address)addr).getAddress(), name, index); 586 } 587 } 588 return getMacAddr0(null, name, index); 589 */ 590 NetworkInterface ni = getByName(name); 591 if (ni == null) { 592 throw new SocketException("NetworkInterface doesn't exist anymore"); 593 } 594 return ni.hardwareAddr; 595 // END Android-changed: Fix upstream not returning link-down interfaces. http://b/26238832 596 } 597 598 /** 599 * Returns the Maximum Transmission Unit (MTU) of this interface. 600 * 601 * @return the value of the MTU for that interface. 602 * @exception SocketException if an I/O error occurs. 603 * @since 1.6 604 */ getMTU()605 public int getMTU() throws SocketException { 606 // Android-changed: Rewrote NetworkInterface on top of Libcore.io. 607 // return getMTU0(name, index); 608 FileDescriptor fd = null; 609 try { 610 fd = Libcore.rawOs.socket(AF_INET, SOCK_DGRAM, 0); 611 return Libcore.rawOs.ioctlMTU(fd, name); 612 } catch (ErrnoException e) { 613 throw e.rethrowAsSocketException(); 614 } catch (Exception ex) { 615 throw new SocketException(ex); 616 } finally { 617 IoUtils.closeQuietly(fd); 618 } 619 } 620 621 /** 622 * Returns whether this interface is a virtual interface (also called 623 * subinterface). 624 * Virtual interfaces are, on some systems, interfaces created as a child 625 * of a physical interface and given different settings (like address or 626 * MTU). Usually the name of the interface will the name of the parent 627 * followed by a colon (:) and a number identifying the child since there 628 * can be several virtual interfaces attached to a single physical 629 * interface. 630 * 631 * @return {@code true} if this interface is a virtual interface. 632 * @since 1.6 633 */ isVirtual()634 public boolean isVirtual() { 635 return virtual; 636 } 637 638 // BEGIN Android-removed: Rewrote NetworkInterface on top of Libcore.io. 639 /* 640 private native static boolean isUp0(String name, int ind) throws SocketException; 641 private native static boolean isLoopback0(String name, int ind) throws SocketException; 642 private native static boolean supportsMulticast0(String name, int ind) throws SocketException; 643 private native static boolean isP2P0(String name, int ind) throws SocketException; 644 private native static byte[] getMacAddr0(byte[] inAddr, String name, int ind) throws SocketException; 645 private native static int getMTU0(String name, int ind) throws SocketException; 646 */ 647 // END Android-removed: Rewrote NetworkInterface on top of Libcore.io. 648 649 // BEGIN Android-added: Rewrote NetworkInterface on top of Libcore.io. getFlags()650 private int getFlags() throws SocketException { 651 FileDescriptor fd = null; 652 try { 653 fd = Libcore.rawOs.socket(AF_INET, SOCK_DGRAM, 0); 654 return Libcore.rawOs.ioctlFlags(fd, name); 655 } catch (ErrnoException e) { 656 throw e.rethrowAsSocketException(); 657 } catch (Exception ex) { 658 throw new SocketException(ex); 659 } finally { 660 IoUtils.closeQuietly(fd); 661 } 662 } 663 // END Android-added: Rewrote NetworkInterface on top of Libcore.io. 664 665 /** 666 * Compares this object against the specified object. 667 * The result is {@code true} if and only if the argument is 668 * not {@code null} and it represents the same NetworkInterface 669 * as this object. 670 * <p> 671 * Two instances of {@code NetworkInterface} represent the same 672 * NetworkInterface if both name and addrs are the same for both. 673 * 674 * @param obj the object to compare against. 675 * @return {@code true} if the objects are the same; 676 * {@code false} otherwise. 677 * @see java.net.InetAddress#getAddress() 678 */ equals(Object obj)679 public boolean equals(Object obj) { 680 if (!(obj instanceof NetworkInterface)) { 681 return false; 682 } 683 NetworkInterface that = (NetworkInterface)obj; 684 if (this.name != null ) { 685 if (!this.name.equals(that.name)) { 686 return false; 687 } 688 } else { 689 if (that.name != null) { 690 return false; 691 } 692 } 693 694 if (this.addrs == null) { 695 return that.addrs == null; 696 } else if (that.addrs == null) { 697 return false; 698 } 699 700 /* Both addrs not null. Compare number of addresses */ 701 702 if (this.addrs.length != that.addrs.length) { 703 return false; 704 } 705 706 InetAddress[] thatAddrs = that.addrs; 707 int count = thatAddrs.length; 708 709 for (int i=0; i<count; i++) { 710 boolean found = false; 711 for (int j=0; j<count; j++) { 712 if (addrs[i].equals(thatAddrs[j])) { 713 found = true; 714 break; 715 } 716 } 717 if (!found) { 718 return false; 719 } 720 } 721 return true; 722 } 723 hashCode()724 public int hashCode() { 725 return name == null? 0: name.hashCode(); 726 } 727 toString()728 public String toString() { 729 String result = "name:"; 730 result += name == null? "null": name; 731 if (displayName != null) { 732 result += " (" + displayName + ")"; 733 } 734 return result; 735 } 736 737 // Android-removed: Android doesn't need to call native init. 738 // private static native void init(); 739 740 /** 741 * Returns the default network interface of this system 742 * 743 * @return the default interface 744 */ getDefault()745 static NetworkInterface getDefault() { 746 return defaultInterface; 747 } 748 } 749