1 /* 2 * Copyright (c) 2000, 2018, 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 { AccessController.doPrivileged( new java.security.PrivilegedAction<Void>() { public Void run() { System.loadLibrary(R); return null; } })56 AccessController.doPrivileged( 57 new java.security.PrivilegedAction<Void>() { 58 public Void run() { 59 System.loadLibrary("net"); 60 return null; 61 } 62 }); 63 init()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 */ NetworkInterface()79 NetworkInterface() { 80 } 81 NetworkInterface(String name, int index, InetAddress[] addrs)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 */ getName()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} 102 * method is called for each InetAddress. Only InetAddresses where 103 * the {@code checkConnect} 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 */ getInetAddresses()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} 158 * of this network interface. 159 * <p> 160 * If there is a security manager, its {@code checkConnect} 161 * method is called with the InetAddress for each InterfaceAddress. 162 * Only InterfaceAddresses where the {@code checkConnect} doesn't throw 163 * a SecurityException will be returned in the List. 164 * 165 * @return a {@code List} object with all or a subset of the 166 * InterfaceAddresss of this network interface 167 * @since 1.6 168 */ getInterfaceAddresses()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 */ getSubInterfaces()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} if it is a physical 220 * (non virtual) interface or has no parent. 221 * 222 * @return The {@code NetworkInterface} this interface is attached to. 223 * @since 1.6 224 */ getParent()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 */ getIndex()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 */ getDisplayName()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 {@code NetworkInterface} with the specified name, 264 * or {@code null} 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 {@code null}. 272 */ getByName(String name)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 */ getByIndex(int index)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 {@code InetAddress} to search with. 307 * 308 * @return A {@code NetworkInterface} 309 * or {@code null} 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 {@code null}. 317 */ getByInetAddress(InetAddress addr)318 public static NetworkInterface getByInetAddress(InetAddress addr) throws SocketException { 319 if (addr == null) { 320 throw new NullPointerException(); 321 } 322 if (addr instanceof Inet4Address) { 323 Inet4Address inet4Address = (Inet4Address) addr; 324 if (inet4Address.holder.family != InetAddress.IPv4) { 325 throw new IllegalArgumentException("invalid family type: " 326 + inet4Address.holder.family); 327 } 328 } else if (addr instanceof Inet6Address) { 329 Inet6Address inet6Address = (Inet6Address) addr; 330 if (inet6Address.holder.family != InetAddress.IPv6) { 331 throw new IllegalArgumentException("invalid family type: " 332 + inet6Address.holder.family); 333 } 334 } else { 335 throw new IllegalArgumentException("invalid address type: " + addr); 336 } 337 return getByInetAddress0(addr); 338 } 339 340 /** 341 * Returns all the interfaces on this machine. The {@code Enumeration} 342 * contains at least one element, possibly representing a loopback 343 * interface that only supports communication between entities on 344 * this machine. 345 * 346 * NOTE: can use getNetworkInterfaces()+getInetAddresses() 347 * to obtain all IP addresses for this node 348 * 349 * @return an Enumeration of NetworkInterfaces found on this machine 350 * @exception SocketException if an I/O error occurs. 351 */ 352 getNetworkInterfaces()353 public static Enumeration<NetworkInterface> getNetworkInterfaces() 354 throws SocketException { 355 final NetworkInterface[] netifs = getAll(); 356 357 // specified to return null if no network interfaces 358 if (netifs == null) 359 return null; 360 361 return new Enumeration<NetworkInterface>() { 362 private int i = 0; 363 public NetworkInterface nextElement() { 364 if (netifs != null && i < netifs.length) { 365 NetworkInterface netif = netifs[i++]; 366 return netif; 367 } else { 368 throw new NoSuchElementException(); 369 } 370 } 371 372 public boolean hasMoreElements() { 373 return (netifs != null && i < netifs.length); 374 } 375 }; 376 } 377 getAll()378 private native static NetworkInterface[] getAll() 379 throws SocketException; 380 getByName0(String name)381 private native static NetworkInterface getByName0(String name) 382 throws SocketException; 383 getByIndex0(int index)384 private native static NetworkInterface getByIndex0(int index) 385 throws SocketException; 386 getByInetAddress0(InetAddress addr)387 private native static NetworkInterface getByInetAddress0(InetAddress addr) 388 throws SocketException; 389 390 /** 391 * Returns whether a network interface is up and running. 392 * 393 * @return {@code true} if the interface is up and running. 394 * @exception SocketException if an I/O error occurs. 395 * @since 1.6 396 */ 397 isUp()398 public boolean isUp() throws SocketException { 399 return isUp0(name, index); 400 } 401 402 /** 403 * Returns whether a network interface is a loopback interface. 404 * 405 * @return {@code true} if the interface is a loopback interface. 406 * @exception SocketException if an I/O error occurs. 407 * @since 1.6 408 */ 409 isLoopback()410 public boolean isLoopback() throws SocketException { 411 return isLoopback0(name, index); 412 } 413 414 /** 415 * Returns whether a network interface is a point to point interface. 416 * A typical point to point interface would be a PPP connection through 417 * a modem. 418 * 419 * @return {@code true} if the interface is a point to point 420 * interface. 421 * @exception SocketException if an I/O error occurs. 422 * @since 1.6 423 */ 424 isPointToPoint()425 public boolean isPointToPoint() throws SocketException { 426 return isP2P0(name, index); 427 } 428 429 /** 430 * Returns whether a network interface supports multicasting or not. 431 * 432 * @return {@code true} if the interface supports Multicasting. 433 * @exception SocketException if an I/O error occurs. 434 * @since 1.6 435 */ 436 supportsMulticast()437 public boolean supportsMulticast() throws SocketException { 438 return supportsMulticast0(name, index); 439 } 440 441 /** 442 * Returns the hardware address (usually MAC) of the interface if it 443 * has one and if it can be accessed given the current privileges. 444 * If a security manager is set, then the caller must have 445 * the permission {@link NetPermission}("getNetworkInformation"). 446 * 447 * @return a byte array containing the address, or {@code null} if 448 * the address doesn't exist, is not accessible or a security 449 * manager is set and the caller does not have the permission 450 * NetPermission("getNetworkInformation") 451 * 452 * @exception SocketException if an I/O error occurs. 453 * @since 1.6 454 */ getHardwareAddress()455 public byte[] getHardwareAddress() throws SocketException { 456 SecurityManager sec = System.getSecurityManager(); 457 if (sec != null) { 458 try { 459 sec.checkPermission(new NetPermission("getNetworkInformation")); 460 } catch (SecurityException e) { 461 if (!getInetAddresses().hasMoreElements()) { 462 // don't have connect permission to any local address 463 return null; 464 } 465 } 466 } 467 for (InetAddress addr : addrs) { 468 if (addr instanceof Inet4Address) { 469 return getMacAddr0(((Inet4Address)addr).getAddress(), name, index); 470 } 471 } 472 return getMacAddr0(null, name, index); 473 } 474 475 /** 476 * Returns the Maximum Transmission Unit (MTU) of this interface. 477 * 478 * @return the value of the MTU for that interface. 479 * @exception SocketException if an I/O error occurs. 480 * @since 1.6 481 */ getMTU()482 public int getMTU() throws SocketException { 483 return getMTU0(name, index); 484 } 485 486 /** 487 * Returns whether this interface is a virtual interface (also called 488 * subinterface). 489 * Virtual interfaces are, on some systems, interfaces created as a child 490 * of a physical interface and given different settings (like address or 491 * MTU). Usually the name of the interface will the name of the parent 492 * followed by a colon (:) and a number identifying the child since there 493 * can be several virtual interfaces attached to a single physical 494 * interface. 495 * 496 * @return {@code true} if this interface is a virtual interface. 497 * @since 1.6 498 */ isVirtual()499 public boolean isVirtual() { 500 return virtual; 501 } 502 isUp0(String name, int ind)503 private native static boolean isUp0(String name, int ind) throws SocketException; isLoopback0(String name, int ind)504 private native static boolean isLoopback0(String name, int ind) throws SocketException; supportsMulticast0(String name, int ind)505 private native static boolean supportsMulticast0(String name, int ind) throws SocketException; isP2P0(String name, int ind)506 private native static boolean isP2P0(String name, int ind) throws SocketException; getMacAddr0(byte[] inAddr, String name, int ind)507 private native static byte[] getMacAddr0(byte[] inAddr, String name, int ind) throws SocketException; getMTU0(String name, int ind)508 private native static int getMTU0(String name, int ind) throws SocketException; 509 510 /** 511 * Compares this object against the specified object. 512 * The result is {@code true} if and only if the argument is 513 * not {@code null} and it represents the same NetworkInterface 514 * as this object. 515 * <p> 516 * Two instances of {@code NetworkInterface} represent the same 517 * NetworkInterface if both name and addrs are the same for both. 518 * 519 * @param obj the object to compare against. 520 * @return {@code true} if the objects are the same; 521 * {@code false} otherwise. 522 * @see java.net.InetAddress#getAddress() 523 */ equals(Object obj)524 public boolean equals(Object obj) { 525 if (!(obj instanceof NetworkInterface)) { 526 return false; 527 } 528 NetworkInterface that = (NetworkInterface)obj; 529 if (this.name != null ) { 530 if (!this.name.equals(that.name)) { 531 return false; 532 } 533 } else { 534 if (that.name != null) { 535 return false; 536 } 537 } 538 539 if (this.addrs == null) { 540 return that.addrs == null; 541 } else if (that.addrs == null) { 542 return false; 543 } 544 545 /* Both addrs not null. Compare number of addresses */ 546 547 if (this.addrs.length != that.addrs.length) { 548 return false; 549 } 550 551 InetAddress[] thatAddrs = that.addrs; 552 int count = thatAddrs.length; 553 554 for (int i=0; i<count; i++) { 555 boolean found = false; 556 for (int j=0; j<count; j++) { 557 if (addrs[i].equals(thatAddrs[j])) { 558 found = true; 559 break; 560 } 561 } 562 if (!found) { 563 return false; 564 } 565 } 566 return true; 567 } 568 hashCode()569 public int hashCode() { 570 return name == null? 0: name.hashCode(); 571 } 572 toString()573 public String toString() { 574 String result = "name:"; 575 result += name == null? "null": name; 576 if (displayName != null) { 577 result += " (" + displayName + ")"; 578 } 579 return result; 580 } 581 init()582 private static native void init(); 583 584 /** 585 * Returns the default network interface of this system 586 * 587 * @return the default interface 588 */ getDefault()589 static NetworkInterface getDefault() { 590 return defaultInterface; 591 } 592 } 593