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