NetworkInterface.java revision c3d19477189eafcdfec5735f9e5e13ffdeaf963d
1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package java.net; 19 20import java.util.ArrayList; 21import java.util.Collections; 22import java.util.Enumeration; 23import java.util.LinkedHashMap; 24import java.util.LinkedList; 25import java.util.List; 26import java.util.Map; 27import libcore.util.EmptyArray; 28 29/** 30 * This class is used to represent a network interface of the local device. An 31 * interface is defined by its address and a platform dependent name. The class 32 * provides methods to get all information about the available interfaces of the 33 * system or to identify the local interface of a joined multicast group. 34 */ 35public final class NetworkInterface extends Object { 36 37 private static final int CHECK_CONNECT_NO_PORT = -1; 38 39 private final String name; 40 private final String displayName; 41 private final List<InterfaceAddress> interfaceAddresses = new LinkedList<InterfaceAddress>(); 42 43 private final int interfaceIndex; 44 private final List<InetAddress> addresses = new LinkedList<InetAddress>(); 45 46 private final List<NetworkInterface> children = new LinkedList<NetworkInterface>(); 47 48 private NetworkInterface parent = null; 49 50 private static NetworkInterface[] getNetworkInterfacesImpl() throws SocketException { 51 Map<String, NetworkInterface> networkInterfaces = new LinkedHashMap<String, NetworkInterface>(); 52 for (InterfaceAddress ia : getAllInterfaceAddressesImpl()) { 53 if (ia != null) { // The array may contain harmless null elements. 54 String name = ia.name; 55 NetworkInterface ni = networkInterfaces.get(name); 56 if (ni == null) { 57 ni = new NetworkInterface(name, name, new InetAddress[] { ia.address }, ia.index); 58 ni.interfaceAddresses.add(ia); 59 networkInterfaces.put(name, ni); 60 } else { 61 ni.addresses.add(ia.address); 62 ni.interfaceAddresses.add(ia); 63 } 64 } 65 } 66 return networkInterfaces.values().toArray(new NetworkInterface[networkInterfaces.size()]); 67 } 68 private static native InterfaceAddress[] getAllInterfaceAddressesImpl() throws SocketException; 69 70 /** 71 * This constructor is used by the native method in order to construct the 72 * NetworkInterface objects in the array that it returns. 73 * 74 * @param name 75 * internal name associated with the interface. 76 * @param displayName 77 * a user interpretable name for the interface. 78 * @param addresses 79 * the Internet addresses associated with the interface. 80 * @param interfaceIndex 81 * an index for the interface. Only set for platforms that 82 * support IPv6. 83 */ 84 NetworkInterface(String name, String displayName, InetAddress[] addresses, 85 int interfaceIndex) { 86 this.name = name; 87 this.displayName = displayName; 88 this.interfaceIndex = interfaceIndex; 89 if (addresses != null) { 90 for (InetAddress address : addresses) { 91 this.addresses.add(address); 92 } 93 } 94 } 95 96 /** 97 * Returns the index for the network interface. Unless the system supports 98 * IPv6 this will be 0. 99 * 100 * @return the index 101 */ 102 int getIndex() { 103 return interfaceIndex; 104 } 105 106 /** 107 * Returns the first address for the network interface. This is used in the 108 * natives when we need one of the addresses for the interface and any one 109 * will do 110 * 111 * @return the first address if one exists, otherwise null. 112 */ 113 InetAddress getFirstAddress() { 114 if (addresses.size() >= 1) { 115 return addresses.get(0); 116 } 117 return null; 118 } 119 120 /** 121 * Gets the name associated with this network interface. 122 * 123 * @return the name of this {@code NetworkInterface} instance. 124 */ 125 public String getName() { 126 return name; 127 } 128 129 /** 130 * Gets a list of addresses bound to this network interface. 131 * 132 * @return the address list of the represented network interface. 133 */ 134 public Enumeration<InetAddress> getInetAddresses() { 135 return Collections.enumeration(addresses); 136 } 137 138 /** 139 * Gets the human-readable name associated with this network interface. 140 * 141 * @return the display name of this network interface or the name if the 142 * display name is not available. 143 */ 144 public String getDisplayName() { 145 /* 146 * we should return the display name unless it is blank in this case 147 * return the name so that something is displayed. 148 */ 149 return displayName.isEmpty() ? name : displayName; 150 } 151 152 /** 153 * Gets the specific network interface according to a given name. 154 * 155 * @param interfaceName 156 * the name to identify the searched network interface. 157 * @return the network interface with the specified name if one exists or 158 * {@code null} otherwise. 159 * @throws SocketException 160 * if an error occurs while getting the network interface 161 * information. 162 * @throws NullPointerException 163 * if the given interface's name is {@code null}. 164 */ 165 public static NetworkInterface getByName(String interfaceName) throws SocketException { 166 if (interfaceName == null) { 167 throw new NullPointerException(); 168 } 169 for (NetworkInterface networkInterface : getNetworkInterfacesList()) { 170 if (networkInterface.name.equals(interfaceName)) { 171 return networkInterface; 172 } 173 } 174 return null; 175 } 176 177 /** 178 * Returns the {@code NetworkInterface} corresponding to the given address, or null if no 179 * interface has this address. 180 * 181 * @throws SocketException if an error occurs. 182 * @throws NullPointerException if {@code address == null}. 183 */ 184 public static NetworkInterface getByInetAddress(InetAddress address) throws SocketException { 185 if (address == null) { 186 throw new NullPointerException("address == null"); 187 } 188 for (NetworkInterface networkInterface : getNetworkInterfacesList()) { 189 if (networkInterface.addresses.contains(address)) { 190 return networkInterface; 191 } 192 } 193 return null; 194 } 195 196 /** 197 * Returns the NetworkInterface corresponding to the given interface index, or null if no 198 * interface has this index. 199 * 200 * @throws SocketException if an error occurs. 201 * @throws NullPointerException if {@code address == null}. 202 * @hide 1.7 203 */ 204 public static NetworkInterface getByIndex(int index) throws SocketException { 205 for (NetworkInterface networkInterface : getNetworkInterfacesList()) { 206 if (networkInterface.interfaceIndex == index) { 207 return networkInterface; 208 } 209 } 210 return null; 211 } 212 213 /** 214 * Gets a list of all network interfaces available on the local system or 215 * {@code null} if no interface is available. 216 * 217 * @return the list of {@code NetworkInterface} instances representing the 218 * available interfaces. 219 * @throws SocketException 220 * if an error occurs while getting the network interface 221 * information. 222 */ 223 public static Enumeration<NetworkInterface> getNetworkInterfaces() throws SocketException { 224 return Collections.enumeration(getNetworkInterfacesList()); 225 } 226 227 private static List<NetworkInterface> getNetworkInterfacesList() throws SocketException { 228 NetworkInterface[] interfaces = getNetworkInterfacesImpl(); 229 230 for (NetworkInterface netif : interfaces) { 231 // Ensure that current NetworkInterface is bound to at least 232 // one InetAddress before processing 233 for (InetAddress addr : netif.addresses) { 234 if (addr.ipaddress.length == 16) { 235 if (addr.isLinkLocalAddress() || addr.isSiteLocalAddress()) { 236 ((Inet6Address) addr).scopedIf = netif; 237 ((Inet6Address) addr).ifname = netif.name; 238 ((Inet6Address) addr).scope_ifname_set = true; 239 } 240 } 241 } 242 } 243 244 List<NetworkInterface> result = new ArrayList<NetworkInterface>(); 245 boolean[] peeked = new boolean[interfaces.length]; 246 for (int counter = 0; counter < interfaces.length; counter++) { 247 // If this interface has been touched, continue. 248 if (peeked[counter]) { 249 continue; 250 } 251 int counter2 = counter; 252 // Checks whether the following interfaces are children. 253 for (; counter2 < interfaces.length; counter2++) { 254 if (peeked[counter2]) { 255 continue; 256 } 257 if (interfaces[counter2].name.startsWith(interfaces[counter].name + ":")) { 258 // Tagged as peeked 259 peeked[counter2] = true; 260 interfaces[counter].children.add(interfaces[counter2]); 261 interfaces[counter2].parent = interfaces[counter]; 262 interfaces[counter].addresses.addAll(interfaces[counter2].addresses); 263 } 264 } 265 // Tagged as peeked 266 result.add(interfaces[counter]); 267 peeked[counter] = true; 268 } 269 return result; 270 } 271 272 /** 273 * Compares the specified object to this {@code NetworkInterface} and 274 * returns whether they are equal or not. The object must be an instance of 275 * {@code NetworkInterface} with the same name, {@code displayName} and list 276 * of network interfaces to be equal. 277 * 278 * @param obj 279 * the object to compare with this instance. 280 * @return {@code true} if the specified object is equal to this {@code 281 * NetworkInterface}, {@code false} otherwise. 282 * @see #hashCode() 283 */ 284 @Override 285 public boolean equals(Object obj) { 286 if (obj == this) { 287 return true; 288 } 289 if (!(obj instanceof NetworkInterface)) { 290 return false; 291 } 292 NetworkInterface rhs = (NetworkInterface) obj; 293 // TODO: should the order of the addresses matter (we use List.equals)? 294 return interfaceIndex == rhs.interfaceIndex && 295 name.equals(rhs.name) && displayName.equals(rhs.displayName) && 296 addresses.equals(rhs.addresses); 297 } 298 299 /** 300 * Returns the hash code for this {@code NetworkInterface}. Since the 301 * name should be unique for each network interface the hash code is 302 * generated using this name. 303 */ 304 @Override 305 public int hashCode() { 306 return name.hashCode(); 307 } 308 309 /** 310 * Gets a string containing a concise, human-readable description of this 311 * network interface. 312 * 313 * @return the textual representation for this network interface. 314 */ 315 @Override 316 public String toString() { 317 StringBuilder string = new StringBuilder(25); 318 string.append("["); 319 string.append(name); 320 string.append("]["); 321 string.append(displayName); 322 string.append("]["); 323 string.append(interfaceIndex); 324 string.append("]"); 325 326 /* 327 * get the addresses through this call to make sure we only reveal those 328 * that we should 329 */ 330 Enumeration<InetAddress> theAddresses = getInetAddresses(); 331 if (theAddresses != null) { 332 while (theAddresses.hasMoreElements()) { 333 InetAddress nextAddress = theAddresses.nextElement(); 334 string.append("["); 335 string.append(nextAddress.toString()); 336 string.append("]"); 337 } 338 } 339 return string.toString(); 340 } 341 342 /** 343 * Returns a List of the InterfaceAddresses for this network interface. 344 * @since 1.6 345 */ 346 public List<InterfaceAddress> getInterfaceAddresses() { 347 return Collections.unmodifiableList(interfaceAddresses); 348 } 349 350 /** 351 * Returns an {@code Enumeration} of all the sub-interfaces of this network interface. 352 * Sub-interfaces are also known as virtual interfaces. 353 * <p> 354 * For example, {@code eth0:1} would be a sub-interface of {@code eth0}. 355 * 356 * @return an Enumeration of all the sub-interfaces of this network interface 357 * @since 1.6 358 */ 359 public Enumeration<NetworkInterface> getSubInterfaces() { 360 return Collections.enumeration(children); 361 } 362 363 /** 364 * Returns the parent NetworkInterface of this interface if this is a 365 * sub-interface, or null if it's a physical (non virtual) interface. 366 * 367 * @return the NetworkInterface this interface is attached to. 368 * @since 1.6 369 */ 370 public NetworkInterface getParent() { 371 return parent; 372 } 373 374 /** 375 * Returns true if this network interface is up. 376 * 377 * @return true if the interface is up. 378 * @throws SocketException if an I/O error occurs. 379 * @since 1.6 380 */ 381 public boolean isUp() throws SocketException { 382 if (addresses.isEmpty()) { 383 return false; 384 } 385 return isUpImpl(name); 386 } 387 private static native boolean isUpImpl(String n) throws SocketException; 388 389 /** 390 * Returns true if this network interface is a loopback interface. 391 * 392 * @return true if the interface is a loopback interface. 393 * @throws SocketException if an I/O error occurs. 394 * @since 1.6 395 */ 396 public boolean isLoopback() throws SocketException { 397 if (addresses.isEmpty()) { 398 return false; 399 } 400 return isLoopbackImpl(name); 401 } 402 private static native boolean isLoopbackImpl(String n) throws SocketException; 403 404 /** 405 * Returns true if this network interface is a point-to-point interface. 406 * (For example, a PPP connection using a modem.) 407 * 408 * @return true if the interface is point-to-point. 409 * @throws SocketException if an I/O error occurs. 410 * @since 1.6 411 */ 412 public boolean isPointToPoint() throws SocketException { 413 if (addresses.isEmpty()) { 414 return false; 415 } 416 return isPointToPointImpl(name); 417 } 418 private static native boolean isPointToPointImpl(String n) throws SocketException; 419 420 /** 421 * Returns true if this network interface supports multicast. 422 * 423 * @throws SocketException if an I/O error occurs. 424 * @since 1.6 425 */ 426 public boolean supportsMulticast() throws SocketException { 427 if (addresses.isEmpty()) { 428 return false; 429 } 430 return supportsMulticastImpl(name); 431 } 432 private static native boolean supportsMulticastImpl(String n) throws SocketException; 433 434 /** 435 * Returns the hardware address of the interface, if it has one, and the 436 * user has the necessary privileges to access the address. 437 * 438 * @return a byte array containing the address or null if the address 439 * doesn't exist or is not accessible. 440 * @throws SocketException if an I/O error occurs. 441 * @since 1.6 442 */ 443 public byte[] getHardwareAddress() throws SocketException { 444 if (addresses.isEmpty()) { 445 return EmptyArray.BYTE; 446 } 447 return getHardwareAddressImpl(name); 448 } 449 private static native byte[] getHardwareAddressImpl(String n) throws SocketException; 450 451 /** 452 * Returns the Maximum Transmission Unit (MTU) of this interface. 453 * 454 * @return the value of the MTU for the interface. 455 * @throws SocketException if an I/O error occurs. 456 * @since 1.6 457 */ 458 public int getMTU() throws SocketException { 459 if (addresses.isEmpty()) { 460 return 0; 461 } 462 return getMTUImpl(name); 463 } 464 private static native int getMTUImpl(String n) throws SocketException; 465 466 /** 467 * Returns true if this interface is a virtual interface (also called 468 * a sub-interface). Virtual interfaces are, on some systems, interfaces 469 * created as a child of a physical interface and given different settings 470 * (like address or MTU). Usually the name of the interface will the name of 471 * the parent followed by a colon (:) and a number identifying the child, 472 * since there can be several virtual interfaces attached to a single 473 * physical interface. 474 * 475 * @return true if this interface is a virtual interface. 476 * @since 1.6 477 */ 478 public boolean isVirtual() { 479 return parent != null; 480 } 481} 482