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