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