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