Home | History | Annotate | Download | only in net
      1 /*
      2  * Copyright (c) 2000, 2011, 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 java.util.Enumeration;
     29 import java.util.NoSuchElementException;
     30 import sun.security.action.*;
     31 import java.security.AccessController;
     32 
     33 /**
     34  * This class represents a Network Interface made up of a name,
     35  * and a list of IP addresses assigned to this interface.
     36  * It is used to identify the local interface on which a multicast group
     37  * is joined.
     38  *
     39  * Interfaces are normally known by names such as "le0".
     40  *
     41  * @since 1.4
     42  */
     43 public final class NetworkInterface {
     44     private String name;
     45     private String displayName;
     46     private int index;
     47     private InetAddress addrs[];
     48     private InterfaceAddress bindings[];
     49     private NetworkInterface childs[];
     50     private NetworkInterface parent = null;
     51     private boolean virtual = false;
     52     private byte[] hardwareAddr;
     53     private static final NetworkInterface defaultInterface;
     54     private static final int defaultIndex; /* index of defaultInterface */
     55 
     56     static {
     57         defaultInterface = DefaultInterface.getDefault();
     58         if (defaultInterface != null) {
     59             defaultIndex = defaultInterface.getIndex();
     60         } else {
     61             defaultIndex = 0;
     62         }
     63     }
     64 
     65     /**
     66      * Returns an NetworkInterface object with index set to 0 and name to null.
     67      * Setting such an interface on a MulticastSocket will cause the
     68      * kernel to choose one interface for sending multicast packets.
     69      *
     70      */
     71     NetworkInterface() {
     72     }
     73 
     74     NetworkInterface(String name, int index, InetAddress[] addrs) {
     75         this.name = name;
     76         this.index = index;
     77         this.addrs = addrs;
     78     }
     79 
     80     /**
     81      * Get the name of this network interface.
     82      *
     83      * @return the name of this network interface
     84      */
     85     public String getName() {
     86             return name;
     87     }
     88 
     89     /**
     90      * Convenience method to return an Enumeration with all or a
     91      * subset of the InetAddresses bound to this network interface.
     92      * <p>
     93      * If there is a security manager, its <code>checkConnect</code>
     94      * method is called for each InetAddress. Only InetAddresses where
     95      * the <code>checkConnect</code> doesn't throw a SecurityException
     96      * will be returned in the Enumeration. However, if the caller has the
     97      * {@link NetPermission}("getNetworkInformation") permission, then all
     98      * InetAddresses are returned.
     99      * @return an Enumeration object with all or a subset of the InetAddresses
    100      * bound to this network interface
    101      */
    102     public Enumeration<InetAddress> getInetAddresses() {
    103 
    104         class checkedAddresses implements Enumeration<InetAddress> {
    105 
    106             private int i=0, count=0;
    107             private InetAddress local_addrs[];
    108 
    109             checkedAddresses() {
    110                 local_addrs = new InetAddress[addrs.length];
    111                 boolean trusted = true;
    112 
    113                 SecurityManager sec = System.getSecurityManager();
    114                 if (sec != null) {
    115                     try {
    116                         sec.checkPermission(new NetPermission("getNetworkInformation"));
    117                     } catch (SecurityException e) {
    118                         trusted = false;
    119                     }
    120                 }
    121                 for (int j=0; j<addrs.length; j++) {
    122                     try {
    123                         if (sec != null && !trusted) {
    124                             sec.checkConnect(addrs[j].getHostAddress(), -1);
    125                         }
    126                         local_addrs[count++] = addrs[j];
    127                     } catch (SecurityException e) { }
    128                 }
    129 
    130             }
    131 
    132             public InetAddress nextElement() {
    133                 if (i < count) {
    134                     return local_addrs[i++];
    135                 } else {
    136                     throw new NoSuchElementException();
    137                 }
    138             }
    139 
    140             public boolean hasMoreElements() {
    141                 return (i < count);
    142             }
    143         }
    144         return new checkedAddresses();
    145 
    146     }
    147 
    148     /**
    149      * Get a List of all or a subset of the <code>InterfaceAddresses</code>
    150      * of this network interface.
    151      * <p>
    152      * If there is a security manager, its <code>checkConnect</code>
    153      * method is called with the InetAddress for each InterfaceAddress.
    154      * Only InterfaceAddresses where the <code>checkConnect</code> doesn't throw
    155      * a SecurityException will be returned in the List.
    156      *
    157      * @return a <code>List</code> object with all or a subset of the
    158      *         InterfaceAddresss of this network interface
    159      * @since 1.6
    160      */
    161     public java.util.List<InterfaceAddress> getInterfaceAddresses() {
    162         java.util.List<InterfaceAddress> lst = new java.util.ArrayList<InterfaceAddress>(1);
    163         SecurityManager sec = System.getSecurityManager();
    164         for (int j=0; j<bindings.length; j++) {
    165             try {
    166                 if (sec != null) {
    167                     sec.checkConnect(bindings[j].getAddress().getHostAddress(), -1);
    168                 }
    169                 lst.add(bindings[j]);
    170             } catch (SecurityException e) { }
    171         }
    172         return lst;
    173     }
    174 
    175     /**
    176      * Get an Enumeration with all the subinterfaces (also known as virtual
    177      * interfaces) attached to this network interface.
    178      * <p>
    179      * For instance eth0:1 will be a subinterface to eth0.
    180      *
    181      * @return an Enumeration object with all of the subinterfaces
    182      * of this network interface
    183      * @since 1.6
    184      */
    185     public Enumeration<NetworkInterface> getSubInterfaces() {
    186         class subIFs implements Enumeration<NetworkInterface> {
    187 
    188             private int i=0;
    189 
    190             subIFs() {
    191             }
    192 
    193             public NetworkInterface nextElement() {
    194                 if (i < childs.length) {
    195                     return childs[i++];
    196                 } else {
    197                     throw new NoSuchElementException();
    198                 }
    199             }
    200 
    201             public boolean hasMoreElements() {
    202                 return (i < childs.length);
    203             }
    204         }
    205         return new subIFs();
    206 
    207     }
    208 
    209     /**
    210      * Returns the parent NetworkInterface of this interface if this is
    211      * a subinterface, or <code>null</code> if it is a physical
    212      * (non virtual) interface or has no parent.
    213      *
    214      * @return The <code>NetworkInterface</code> this interface is attached to.
    215      * @since 1.6
    216      */
    217     public NetworkInterface getParent() {
    218         return parent;
    219     }
    220 
    221     /**
    222      * Returns the index of this network interface. The index is an integer greater
    223      * or equal to zero, or {@code -1} for unknown. This is a system specific value
    224      * and interfaces with the same name can have different indexes on different
    225      * machines.
    226      *
    227      * @return the index of this network interface or {@code -1} if the index is
    228      *         unknown
    229      * @see #getByIndex(int)
    230      * @since 1.7
    231      */
    232     public int getIndex() {
    233         return index;
    234     }
    235 
    236     /**
    237      * Get the display name of this network interface.
    238      * A display name is a human readable String describing the network
    239      * device.
    240      *
    241      * @return a non-empty string representing the display name of this network
    242      *         interface, or null if no display name is available.
    243      */
    244     public String getDisplayName() {
    245         /* strict TCK conformance */
    246         return "".equals(displayName) ? null : displayName;
    247     }
    248 
    249     /**
    250      * Searches for the network interface with the specified name.
    251      *
    252      * @param   name
    253      *          The name of the network interface.
    254      *
    255      * @return  A <tt>NetworkInterface</tt> with the specified name,
    256      *          or <tt>null</tt> if there is no network interface
    257      *          with the specified name.
    258      *
    259      * @throws  SocketException
    260      *          If an I/O error occurs.
    261      *
    262      * @throws  NullPointerException
    263      *          If the specified name is <tt>null</tt>.
    264      */
    265     public static NetworkInterface getByName(String name) throws SocketException {
    266         if (name == null)
    267             throw new NullPointerException();
    268         return getByName0(name);
    269     }
    270 
    271     /**
    272      * Get a network interface given its index.
    273      *
    274      * @param index an integer, the index of the interface
    275      * @return the NetworkInterface obtained from its index, or {@code null} if
    276      *         there is no interface with such an index on the system
    277      * @throws  SocketException  if an I/O error occurs.
    278      * @throws  IllegalArgumentException if index has a negative value
    279      * @see #getIndex()
    280      * @since 1.7
    281      */
    282     public static NetworkInterface getByIndex(int index) throws SocketException {
    283         if (index < 0)
    284             throw new IllegalArgumentException("Interface index can't be negative");
    285         return getByIndex0(index);
    286     }
    287 
    288     /**
    289      * Convenience method to search for a network interface that
    290      * has the specified Internet Protocol (IP) address bound to
    291      * it.
    292      * <p>
    293      * If the specified IP address is bound to multiple network
    294      * interfaces it is not defined which network interface is
    295      * returned.
    296      *
    297      * @param   addr
    298      *          The <tt>InetAddress</tt> to search with.
    299      *
    300      * @return  A <tt>NetworkInterface</tt>
    301      *          or <tt>null</tt> if there is no network interface
    302      *          with the specified IP address.
    303      *
    304      * @throws  SocketException
    305      *          If an I/O error occurs.
    306      *
    307      * @throws  NullPointerException
    308      *          If the specified address is <tt>null</tt>.
    309      */
    310     public static NetworkInterface getByInetAddress(InetAddress addr) throws SocketException {
    311         if (addr == null) {
    312             throw new NullPointerException();
    313         }
    314         if (!(addr instanceof Inet4Address || addr instanceof Inet6Address)) {
    315             throw new IllegalArgumentException ("invalid address type");
    316         }
    317         return getByInetAddress0(addr);
    318     }
    319 
    320     /**
    321      * Returns all the interfaces on this machine. Returns null if no
    322      * network interfaces could be found on this machine.
    323      *
    324      * NOTE: can use getNetworkInterfaces()+getInetAddresses()
    325      *       to obtain all IP addresses for this node
    326      *
    327      * @return an Enumeration of NetworkInterfaces found on this machine
    328      * @exception  SocketException  if an I/O error occurs.
    329      */
    330 
    331     public static Enumeration<NetworkInterface> getNetworkInterfaces()
    332         throws SocketException {
    333         final NetworkInterface[] netifs = getAll();
    334 
    335         // specified to return null if no network interfaces
    336         if (netifs == null)
    337             return null;
    338 
    339         return new Enumeration<NetworkInterface>() {
    340             private int i = 0;
    341             public NetworkInterface nextElement() {
    342                 if (netifs != null && i < netifs.length) {
    343                     NetworkInterface netif = netifs[i++];
    344                     return netif;
    345                 } else {
    346                     throw new NoSuchElementException();
    347                 }
    348             }
    349 
    350             public boolean hasMoreElements() {
    351                 return (netifs != null && i < netifs.length);
    352             }
    353         };
    354     }
    355 
    356     private native static NetworkInterface[] getAll()
    357         throws SocketException;
    358 
    359     private native static NetworkInterface getByName0(String name)
    360         throws SocketException;
    361 
    362     private native static NetworkInterface getByIndex0(int index)
    363         throws SocketException;
    364 
    365     private native static NetworkInterface getByInetAddress0(InetAddress addr)
    366         throws SocketException;
    367 
    368     /**
    369      * Returns whether a network interface is up and running.
    370      *
    371      * @return  <code>true</code> if the interface is up and running.
    372      * @exception       SocketException if an I/O error occurs.
    373      * @since 1.6
    374      */
    375 
    376     public boolean isUp() throws SocketException {
    377         return isUp0(name, index);
    378     }
    379 
    380     /**
    381      * Returns whether a network interface is a loopback interface.
    382      *
    383      * @return  <code>true</code> if the interface is a loopback interface.
    384      * @exception       SocketException if an I/O error occurs.
    385      * @since 1.6
    386      */
    387 
    388     public boolean isLoopback() throws SocketException {
    389         return isLoopback0(name, index);
    390     }
    391 
    392     /**
    393      * Returns whether a network interface is a point to point interface.
    394      * A typical point to point interface would be a PPP connection through
    395      * a modem.
    396      *
    397      * @return  <code>true</code> if the interface is a point to point
    398      *          interface.
    399      * @exception       SocketException if an I/O error occurs.
    400      * @since 1.6
    401      */
    402 
    403     public boolean isPointToPoint() throws SocketException {
    404         return isP2P0(name, index);
    405     }
    406 
    407     /**
    408      * Returns whether a network interface supports multicasting or not.
    409      *
    410      * @return  <code>true</code> if the interface supports Multicasting.
    411      * @exception       SocketException if an I/O error occurs.
    412      * @since 1.6
    413      */
    414 
    415     public boolean supportsMulticast() throws SocketException {
    416         return supportsMulticast0(name, index);
    417     }
    418 
    419     /**
    420      * Returns the hardware address (usually MAC) of the interface if it
    421      * has one and if it can be accessed given the current privileges.
    422      * If a security manager is set, then the caller must have
    423      * the permission {@link NetPermission}("getNetworkInformation").
    424      *
    425      * @return  a byte array containing the address, or <code>null</code> if
    426      *          the address doesn't exist, is not accessible or a security
    427      *          manager is set and the caller does not have the permission
    428      *          NetPermission("getNetworkInformation")
    429      *
    430      * @exception       SocketException if an I/O error occurs.
    431      * @since 1.6
    432      */
    433     public byte[] getHardwareAddress() throws SocketException {
    434         // Android chage - do not use the cached address, fetch
    435         // the object again. NI might not be valid anymore.
    436         NetworkInterface ni = getByName0(name);
    437         if (ni == null) {
    438             throw new SocketException("NetworkInterface doesn't exist anymore");
    439         }
    440         return ni.hardwareAddr;
    441     }
    442 
    443     /**
    444      * Returns the Maximum Transmission Unit (MTU) of this interface.
    445      *
    446      * @return the value of the MTU for that interface.
    447      * @exception       SocketException if an I/O error occurs.
    448      * @since 1.6
    449      */
    450     public int getMTU() throws SocketException {
    451         return getMTU0(name, index);
    452     }
    453 
    454     /**
    455      * Returns whether this interface is a virtual interface (also called
    456      * subinterface).
    457      * Virtual interfaces are, on some systems, interfaces created as a child
    458      * of a physical interface and given different settings (like address or
    459      * MTU). Usually the name of the interface will the name of the parent
    460      * followed by a colon (:) and a number identifying the child since there
    461      * can be several virtual interfaces attached to a single physical
    462      * interface.
    463      *
    464      * @return <code>true</code> if this interface is a virtual interface.
    465      * @since 1.6
    466      */
    467     public boolean isVirtual() {
    468         return virtual;
    469     }
    470 
    471     private native static boolean isUp0(String name, int ind) throws SocketException;
    472     private native static boolean isLoopback0(String name, int ind) throws SocketException;
    473     private native static boolean supportsMulticast0(String name, int ind) throws SocketException;
    474     private native static boolean isP2P0(String name, int ind) throws SocketException;
    475     private native static int getMTU0(String name, int ind) throws SocketException;
    476 
    477     /**
    478      * Compares this object against the specified object.
    479      * The result is <code>true</code> if and only if the argument is
    480      * not <code>null</code> and it represents the same NetworkInterface
    481      * as this object.
    482      * <p>
    483      * Two instances of <code>NetworkInterface</code> represent the same
    484      * NetworkInterface if both name and addrs are the same for both.
    485      *
    486      * @param   obj   the object to compare against.
    487      * @return  <code>true</code> if the objects are the same;
    488      *          <code>false</code> otherwise.
    489      * @see     java.net.InetAddress#getAddress()
    490      */
    491     public boolean equals(Object obj) {
    492         if (!(obj instanceof NetworkInterface)) {
    493             return false;
    494         }
    495         NetworkInterface that = (NetworkInterface)obj;
    496         if (this.name != null ) {
    497             if (!this.name.equals(that.name)) {
    498                 return false;
    499             }
    500         } else {
    501             if (that.name != null) {
    502                 return false;
    503             }
    504         }
    505 
    506         if (this.addrs == null) {
    507             return that.addrs == null;
    508         } else if (that.addrs == null) {
    509             return false;
    510         }
    511 
    512         /* Both addrs not null. Compare number of addresses */
    513 
    514         if (this.addrs.length != that.addrs.length) {
    515             return false;
    516         }
    517 
    518         InetAddress[] thatAddrs = that.addrs;
    519         int count = thatAddrs.length;
    520 
    521         for (int i=0; i<count; i++) {
    522             boolean found = false;
    523             for (int j=0; j<count; j++) {
    524                 if (addrs[i].equals(thatAddrs[j])) {
    525                     found = true;
    526                     break;
    527                 }
    528             }
    529             if (!found) {
    530                 return false;
    531             }
    532         }
    533         return true;
    534     }
    535 
    536     public int hashCode() {
    537         return name == null? 0: name.hashCode();
    538     }
    539 
    540     public String toString() {
    541         String result = "name:";
    542         result += name == null? "null": name;
    543         if (displayName != null) {
    544             result += " (" + displayName + ")";
    545         }
    546         return result;
    547     }
    548 
    549     /**
    550      * Returns the default network interface of this system
    551      *
    552      * @return the default interface
    553      */
    554     static NetworkInterface getDefault() {
    555         return defaultInterface;
    556     }
    557 }
    558