• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2000, 2013, 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 android.system.ErrnoException;
29 
30 import java.io.FileDescriptor;
31 import java.util.ArrayList;
32 import java.util.Arrays;
33 import java.util.Collections;
34 import java.util.Enumeration;
35 import java.util.HashMap;
36 import java.util.List;
37 import java.util.Map;
38 import java.util.NoSuchElementException;
39 
40 import android.compat.Compatibility;
41 import android.compat.annotation.ChangeId;
42 import android.compat.annotation.EnabledSince;
43 import android.system.StructIfaddrs;
44 import dalvik.annotation.compat.VersionCodes;
45 import libcore.io.IoUtils;
46 import libcore.io.Libcore;
47 import sun.security.action.*;
48 import java.security.AccessController;
49 
50 import static android.system.OsConstants.*;
51 
52 // Android-note: NetworkInterface has been rewritten to avoid native code.
53 // Fix upstream bug not returning link-down interfaces. http://b/26238832
54 // Android-added: Document restrictions for non-system apps. http://b/170188668
55 /**
56  * This class represents a Network Interface made up of a name,
57  * and a list of IP addresses assigned to this interface.
58  * It is used to identify the local interface on which a multicast group
59  * is joined.
60  *
61  * Interfaces are normally known by names such as "le0".
62  * <p>
63  * <a name="access-restrictions"></a>Note that information about
64  * {@link NetworkInterface}s may be restricted. For example, non-system apps
65  * will only have access to information about {@link NetworkInterface}s that are
66  * associated with an {@link InetAddress}.
67  *
68  * @since 1.4
69  */
70 public final class NetworkInterface {
71     // Android-added: Anonymized address for apps targeting old API versions. http://b/170188668
72     /**
73      * If this change is enabled, {@link #getHardwareAddress()} returns null when the hardware
74      * address is <a href="#access-restrictions">inaccessible</a>. If the change is disabled, the
75      * default MAC address (02:00:00:00:00:00) is returned instead.
76      *
77      * @hide
78      */
79     @ChangeId
80     @EnabledSince(targetSdkVersion=VersionCodes.R)
81     public static final long RETURN_NULL_HARDWARE_ADDRESS = 170188668L;
82     // The default hardware address is a zeroed-out MAC address with only its
83     // locally-administered bit set, returned to apps targeting older API versions if they would
84     // otherwise see a null MAC address.
85     // Matches android.net.wifi.WifiInfo.DEFAULT_MAC_ADDRESS
86     private static final byte[] DEFAULT_MAC_ADDRESS = {
87         0x02, 0x00, 0x00, 0x00, 0x00, 0x00 };
88 
89     private String name;
90     private String displayName;
91     private int index;
92     private InetAddress addrs[];
93     private InterfaceAddress bindings[];
94     // Android-changed: Rewrote NetworkInterface on top of Libcore.io.
95     // private NetworkInterface childs[];
96     private List<NetworkInterface> childs;
97     private NetworkInterface parent = null;
98     private boolean virtual = false;
99     private static final NetworkInterface defaultInterface;
100     private static final int defaultIndex; /* index of defaultInterface */
101 
102     // Android-changed: Fix upstream bug not returning link-down interfaces. http://b/26238832
103     private byte[] hardwareAddr;
104 
105     static {
106         // Android-removed: Android doesn't need to call native init.
107         /*
108         AccessController.doPrivileged(
109             new java.security.PrivilegedAction<Void>() {
110                 public Void run() {
111                     System.loadLibrary("net");
112                     return null;
113                 }
114             });
115 
116         init();
117         */
118         defaultInterface = DefaultInterface.getDefault();
119         if (defaultInterface != null) {
120             defaultIndex = defaultInterface.getIndex();
121         } else {
122             defaultIndex = 0;
123         }
124     }
125 
126     /**
127      * Returns an NetworkInterface object with index set to 0 and name to null.
128      * Setting such an interface on a MulticastSocket will cause the
129      * kernel to choose one interface for sending multicast packets.
130      *
131      */
NetworkInterface()132     NetworkInterface() {
133     }
134 
NetworkInterface(String name, int index, InetAddress[] addrs)135     NetworkInterface(String name, int index, InetAddress[] addrs) {
136         this.name = name;
137         this.index = index;
138         this.addrs = addrs;
139     }
140 
141     /**
142      * Get the name of this network interface.
143      *
144      * @return the name of this network interface
145      */
getName()146     public String getName() {
147             return name;
148     }
149 
150     /**
151      * Convenience method to return an Enumeration with all or a
152      * subset of the InetAddresses bound to this network interface.
153      * <p>
154      * If there is a security manager, its {@code checkConnect}
155      * method is called for each InetAddress. Only InetAddresses where
156      * the {@code checkConnect} doesn't throw a SecurityException
157      * will be returned in the Enumeration. However, if the caller has the
158      * {@link NetPermission}("getNetworkInformation") permission, then all
159      * InetAddresses are returned.
160      * @return an Enumeration object with all or a subset of the InetAddresses
161      * bound to this network interface
162      */
getInetAddresses()163     public Enumeration<InetAddress> getInetAddresses() {
164 
165         class checkedAddresses implements Enumeration<InetAddress> {
166 
167             private int i=0, count=0;
168             private InetAddress local_addrs[];
169 
170             checkedAddresses() {
171                 local_addrs = new InetAddress[addrs.length];
172                 boolean trusted = true;
173 
174                 SecurityManager sec = System.getSecurityManager();
175                 if (sec != null) {
176                     try {
177                         sec.checkPermission(new NetPermission("getNetworkInformation"));
178                     } catch (SecurityException e) {
179                         trusted = false;
180                     }
181                 }
182                 for (int j=0; j<addrs.length; j++) {
183                     try {
184                         if (sec != null && !trusted) {
185                             sec.checkConnect(addrs[j].getHostAddress(), -1);
186                         }
187                         local_addrs[count++] = addrs[j];
188                     } catch (SecurityException e) { }
189                 }
190 
191             }
192 
193             public InetAddress nextElement() {
194                 if (i < count) {
195                     return local_addrs[i++];
196                 } else {
197                     throw new NoSuchElementException();
198                 }
199             }
200 
201             public boolean hasMoreElements() {
202                 return (i < count);
203             }
204         }
205         return new checkedAddresses();
206 
207     }
208 
209     /**
210      * Get a List of all or a subset of the {@code InterfaceAddresses}
211      * of this network interface.
212      * <p>
213      * If there is a security manager, its {@code checkConnect}
214      * method is called with the InetAddress for each InterfaceAddress.
215      * Only InterfaceAddresses where the {@code checkConnect} doesn't throw
216      * a SecurityException will be returned in the List.
217      *
218      * @return a {@code List} object with all or a subset of the
219      *         InterfaceAddresss of this network interface
220      * @since 1.6
221      */
getInterfaceAddresses()222     public java.util.List<InterfaceAddress> getInterfaceAddresses() {
223         java.util.List<InterfaceAddress> lst = new java.util.ArrayList<InterfaceAddress>(1);
224         // BEGIN Android-changed: Cherry-picked upstream OpenJDK9 change rev 59a110a38cea
225         // http://b/30628919
226         if (bindings != null) {
227             SecurityManager sec = System.getSecurityManager();
228             for (int j=0; j<bindings.length; j++) {
229                 try {
230                     if (sec != null) {
231                         sec.checkConnect(bindings[j].getAddress().getHostAddress(), -1);
232                     }
233                     lst.add(bindings[j]);
234                 } catch (SecurityException e) { }
235             }
236         }
237         // END Android-changed: Cherry-picked upstream OpenJDK9 change rev 59a110a38cea
238         return lst;
239     }
240 
241     /**
242      * Get an Enumeration with all the subinterfaces (also known as virtual
243      * interfaces) attached to this network interface.
244      * <p>
245      * For instance eth0:1 will be a subinterface to eth0.
246      *
247      * @return an Enumeration object with all of the subinterfaces
248      * of this network interface
249      * @since 1.6
250      */
getSubInterfaces()251     public Enumeration<NetworkInterface> getSubInterfaces() {
252         // Android-changed: Rewrote NetworkInterface on top of Libcore.io.
253         return Collections.enumeration(childs);
254     }
255 
256     /**
257      * Returns the parent NetworkInterface of this interface if this is
258      * a subinterface, or {@code null} if it is a physical
259      * (non virtual) interface or has no parent.
260      *
261      * @return The {@code NetworkInterface} this interface is attached to.
262      * @since 1.6
263      */
getParent()264     public NetworkInterface getParent() {
265         return parent;
266     }
267 
268     /**
269      * Returns the index of this network interface. The index is an integer greater
270      * or equal to zero, or {@code -1} for unknown. This is a system specific value
271      * and interfaces with the same name can have different indexes on different
272      * machines.
273      *
274      * @return the index of this network interface or {@code -1} if the index is
275      *         unknown
276      * @see #getByIndex(int)
277      * @since 1.7
278      */
getIndex()279     public int getIndex() {
280         return index;
281     }
282 
283     /**
284      * Get the display name of this network interface.
285      * A display name is a human readable String describing the network
286      * device.
287      *
288      * @return a non-empty string representing the display name of this network
289      *         interface, or null if no display name is available.
290      */
getDisplayName()291     public String getDisplayName() {
292         /* strict TCK conformance */
293         return "".equals(displayName) ? null : displayName;
294     }
295 
296     // Android-added: Document restrictions for non-system apps. http://b/170188668
297     /**
298      * Searches for the network interface with the specified name.
299      *
300      * @param   name
301      *          The name of the network interface.
302      *
303      * @return  A {@code NetworkInterface} with the specified name,
304      *          or {@code null} if the network interface with the specified
305      *          name does not exist or <a href="#access-restrictions">can't be
306      *          accessed</a>.
307      *
308      * @throws  SocketException
309      *          If an I/O error occurs.
310      *
311      * @throws  NullPointerException
312      *          If the specified name is {@code null}.
313      */
getByName(String name)314     public static NetworkInterface getByName(String name) throws SocketException {
315         if (name == null)
316             throw new NullPointerException();
317 
318         // Android-changed: Rewrote NetworkInterface on top of Libcore.io.
319         NetworkInterface[] nis = getAll();
320         for (NetworkInterface ni : nis) {
321             if (ni.getName().equals(name)) {
322                 return ni;
323             }
324         }
325         return null;
326     }
327 
328     // Android-added: Document restrictions for non-system apps. http://b/170188668
329     /**
330      * Get a network interface given its index.
331      *
332      * @param index an integer, the index of the interface
333      * @return the NetworkInterface obtained from its index, or {@code null} if
334      *         an interface with the specified index does not exist or
335      *         <a href="#access-restrictions">can't be accessed</a>.
336      * @throws  SocketException  if an I/O error occurs.
337      * @throws  IllegalArgumentException if index has a negative value
338      * @see #getIndex()
339      * @since 1.7
340      */
getByIndex(int index)341     public static NetworkInterface getByIndex(int index) throws SocketException {
342         if (index < 0)
343             throw new IllegalArgumentException("Interface index can't be negative");
344 
345         // Android-changed: Rewrote NetworkInterface on top of Libcore.io.
346         NetworkInterface[] nis = getAll();
347         for (NetworkInterface ni : nis) {
348             if (ni.getIndex() == index) {
349                 return ni;
350             }
351         }
352         return null;
353     }
354 
355     /**
356      * Convenience method to search for a network interface that
357      * has the specified Internet Protocol (IP) address bound to
358      * it.
359      * <p>
360      * If the specified IP address is bound to multiple network
361      * interfaces it is not defined which network interface is
362      * returned.
363      *
364      * @param   addr
365      *          The {@code InetAddress} to search with.
366      *
367      * @return  A {@code NetworkInterface}
368      *          or {@code null} if there is no network interface
369      *          with the specified IP address.
370      *
371      * @throws  SocketException
372      *          If an I/O error occurs.
373      *
374      * @throws  NullPointerException
375      *          If the specified address is {@code null}.
376      */
getByInetAddress(InetAddress addr)377     public static NetworkInterface getByInetAddress(InetAddress addr) throws SocketException {
378         if (addr == null) {
379             throw new NullPointerException();
380         }
381         if (!(addr instanceof Inet4Address || addr instanceof Inet6Address)) {
382             throw new IllegalArgumentException ("invalid address type");
383         }
384 
385         // Android-changed: Rewrote NetworkInterface on top of Libcore.io.
386         NetworkInterface[] nis = getAll();
387         for (NetworkInterface ni : nis) {
388             for (InetAddress inetAddress : Collections.list(ni.getInetAddresses())) {
389                 if (inetAddress.equals(addr)) {
390                     return ni;
391                 }
392             }
393         }
394         return null;
395     }
396 
397     // Android-added: Document restrictions for non-system apps. http://b/170188668
398     // Android-added: Note about NullPointerException in older versions. http://b/206053582
399     /**
400      * Returns all the interfaces on this machine. The {@code Enumeration}
401      * contains at least one element, possibly representing a loopback
402      * interface that only supports communication between entities on
403      * this machine.
404      *
405      * NOTE: can use getNetworkInterfaces()+getInetAddresses()
406      *       to obtain all IP addresses for this node
407      * <p>
408      * For non-system apps, this method will only return information for
409      * {@link NetworkInterface}s associated with an {@link InetAddress}.
410      * <p>
411      * ANDROID NOTE: On Android versions before S (API level 31), this method may throw a
412      *               NullPointerException if called in an environment where there is a virtual
413      *               interface without a parent interface present.
414      *
415      * @return an Enumeration of NetworkInterfaces found on this machine
416      *         that <a href="#access-restrictions">are accessible</a>.
417      * @exception  SocketException  if an I/O error occurs.
418      */
419 
getNetworkInterfaces()420     public static Enumeration<NetworkInterface> getNetworkInterfaces()
421         throws SocketException {
422         final NetworkInterface[] netifs = getAll();
423         // Android-changed: Rewrote NetworkInterface on top of Libcore.io.
424         // // specified to return null if no network interfaces
425         // if (netifs == null)
426         if (netifs.length == 0)
427             return null;
428 
429         // Android-changed: Rewrote NetworkInterface on top of Libcore.io.
430         /*
431         return new Enumeration<NetworkInterface>() {
432             private int i = 0;
433             public NetworkInterface nextElement() {
434                 if (netifs != null && i < netifs.length) {
435                     NetworkInterface netif = netifs[i++];
436                     return netif;
437                 } else {
438                     throw new NoSuchElementException();
439                 }
440             }
441 
442             public boolean hasMoreElements() {
443                 return (netifs != null && i < netifs.length);
444             }
445         };
446         */
447         return Collections.enumeration(Arrays.asList(netifs));
448     }
449 
450     // BEGIN Android-changed: Rewrote NetworkInterface on top of Libcore.io.
451     // private native static NetworkInterface[] getAll()
452     //    throws SocketException;
getAll()453     private static NetworkInterface[] getAll() throws SocketException {
454         // Group Ifaddrs by interface name.
455         Map<String, List<StructIfaddrs>> inetMap = new HashMap<>();
456 
457         StructIfaddrs[] ifaddrs;
458         try {
459             ifaddrs = Libcore.os.getifaddrs();
460             // Defensive check for b/217749090: ifaddrs should never be null.
461             if (ifaddrs == null) {
462                 throw new SocketException("Failed to query network interfaces.");
463             }
464         } catch (ErrnoException e) {
465             throw e.rethrowAsSocketException();
466         }
467 
468         for (StructIfaddrs ifa : ifaddrs) {
469             String name = ifa.ifa_name;
470 
471             List<StructIfaddrs> ifas;
472             if ((ifas = inetMap.get(name)) == null) {
473                 ifas = new ArrayList<>();
474                 inetMap.put(name, ifas);
475             }
476 
477             ifas.add(ifa);
478         }
479 
480         // Populate NetworkInterface instances.
481         Map<String, NetworkInterface> nis = new HashMap<>(inetMap.size());
482         for (Map.Entry<String, List<StructIfaddrs>> e : inetMap.entrySet()) {
483             String name = e.getKey();
484             int index = Libcore.os.if_nametoindex(e.getKey());
485             if (index == 0) {
486                 // This interface has gone away between getifaddrs and if_nametoindex
487                 continue;
488             }
489 
490             NetworkInterface ni = new NetworkInterface(name, index, null);
491             ni.displayName = name;
492 
493             List<InetAddress> addrs = new ArrayList<>();
494             List<InterfaceAddress> binds = new ArrayList<>();
495 
496             for (StructIfaddrs ifa : e.getValue()) {
497                 if (ifa.ifa_addr != null) {
498                     addrs.add(ifa.ifa_addr);
499                     binds.add(new InterfaceAddress(ifa.ifa_addr, (Inet4Address) ifa.ifa_broadaddr,
500                                                    ifa.ifa_netmask));
501                 }
502 
503                 if (ifa.hwaddr != null) {
504                     ni.hardwareAddr = ifa.hwaddr;
505                 }
506             }
507 
508             ni.addrs = addrs.toArray(new InetAddress[addrs.size()]);
509             ni.bindings = binds.toArray(new InterfaceAddress[binds.size()]);
510             ni.childs = new ArrayList<>(0);
511             nis.put(name, ni);
512         }
513 
514         // Populate childs/parent.
515         for (Map.Entry<String, NetworkInterface> e : nis.entrySet()) {
516             NetworkInterface ni = e.getValue();
517             String niName = ni.getName();
518             int colonIdx = niName.indexOf(':');
519             if (colonIdx != -1) {
520                 // This is a virtual interface.
521                 String parentName = niName.substring(0, colonIdx);
522                 NetworkInterface parent = nis.get(parentName);
523 
524                 ni.virtual = true;
525 
526                 if (parent != null) {
527                     ni.parent = parent;
528                     parent.childs.add(ni);
529                 }
530             }
531         }
532 
533         return nis.values().toArray(new NetworkInterface[nis.size()]);
534     }
535     // END Android-changed: Rewrote NetworkInterface on top of Libcore.io.
536 
537     /**
538      * Returns whether a network interface is up and running.
539      *
540      * @return  {@code true} if the interface is up and running.
541      * @exception       SocketException if an I/O error occurs.
542      * @since 1.6
543      */
544 
isUp()545     public boolean isUp() throws SocketException {
546         // Android-changed: Rewrote NetworkInterface on top of Libcore.io.
547         final int mask = IFF_UP | IFF_RUNNING;
548         return (getFlags() & mask) == mask;
549     }
550 
551     /**
552      * Returns whether a network interface is a loopback interface.
553      *
554      * @return  {@code true} if the interface is a loopback interface.
555      * @exception       SocketException if an I/O error occurs.
556      * @since 1.6
557      */
558 
isLoopback()559     public boolean isLoopback() throws SocketException {
560         // Android-changed: Rewrote NetworkInterface on top of Libcore.io.
561         return (getFlags() & IFF_LOOPBACK) != 0;
562     }
563 
564     /**
565      * Returns whether a network interface is a point to point interface.
566      * A typical point to point interface would be a PPP connection through
567      * a modem.
568      *
569      * @return  {@code true} if the interface is a point to point
570      *          interface.
571      * @exception       SocketException if an I/O error occurs.
572      * @since 1.6
573      */
574 
isPointToPoint()575     public boolean isPointToPoint() throws SocketException {
576         // Android-changed: Rewrote NetworkInterface on top of Libcore.io.
577         return (getFlags() & IFF_POINTOPOINT) != 0;
578     }
579 
580     /**
581      * Returns whether a network interface supports multicasting or not.
582      *
583      * @return  {@code true} if the interface supports Multicasting.
584      * @exception       SocketException if an I/O error occurs.
585      * @since 1.6
586      */
587 
supportsMulticast()588     public boolean supportsMulticast() throws SocketException {
589         // Android-changed: Rewrote NetworkInterface on top of Libcore.io.
590         return (getFlags() & IFF_MULTICAST) != 0;
591     }
592 
593     // Android-added: Restrictions for non-system apps. http://b/170188668
594     /**
595      * Returns the hardware address (usually MAC) of the interface if it
596      * has one and if it can be accessed given the current privileges.
597      * If a security manager is set, then the caller must have
598      * the permission {@link NetPermission}("getNetworkInformation").
599      *
600      * @return  a byte array containing the address, or {@code null} if
601      *          the address doesn't exist, is not accessible or a security
602      *          manager is set and the caller does not have the permission
603      *          NetPermission("getNetworkInformation"). For example, this
604      *          method will generally return {@code null} when called by
605      *          non-system apps (or 02:00:00:00:00:00 for apps having
606      *          {@code targetSdkVersion < android.os.Build.VERSION_CODES.R}).
607      *
608      * @exception       SocketException if an I/O error occurs.
609      * @since 1.6
610      */
getHardwareAddress()611     public byte[] getHardwareAddress() throws SocketException {
612         // BEGIN Android-changed: Fix upstream not returning link-down interfaces. http://b/26238832
613         /*
614         for (InetAddress addr : addrs) {
615             if (addr instanceof Inet4Address) {
616                 return getMacAddr0(((Inet4Address)addr).getAddress(), name, index);
617             }
618         }
619         return getMacAddr0(null, name, index);
620          */
621         NetworkInterface ni = getByName(name);
622         if (ni == null) {
623             throw new SocketException("NetworkInterface doesn't exist anymore");
624         }
625         // Return 02:00:00:00:00:00 for apps having a target SDK version < R if they would have
626         // otherwise gotten a null MAC address (excluding loopback).
627         if (ni.hardwareAddr == null && !"lo".equals(name)
628                 && !Compatibility.isChangeEnabled(RETURN_NULL_HARDWARE_ADDRESS)) {
629             return DEFAULT_MAC_ADDRESS.clone();
630         }
631         return ni.hardwareAddr;
632         // END Android-changed: Fix upstream not returning link-down interfaces. http://b/26238832
633     }
634 
635     /**
636      * Returns the Maximum Transmission Unit (MTU) of this interface.
637      *
638      * @return the value of the MTU for that interface.
639      * @exception       SocketException if an I/O error occurs.
640      * @since 1.6
641      */
getMTU()642     public int getMTU() throws SocketException {
643         // Android-changed: Rewrote NetworkInterface on top of Libcore.io.
644         // return getMTU0(name, index);
645         FileDescriptor fd = null;
646         try {
647             fd = Libcore.rawOs.socket(AF_INET, SOCK_DGRAM, 0);
648             return Libcore.rawOs.ioctlMTU(fd, name);
649         } catch (ErrnoException e) {
650             throw e.rethrowAsSocketException();
651         } catch (Exception ex) {
652             throw new SocketException(ex);
653         } finally {
654             IoUtils.closeQuietly(fd);
655         }
656     }
657 
658     /**
659      * Returns whether this interface is a virtual interface (also called
660      * subinterface).
661      * Virtual interfaces are, on some systems, interfaces created as a child
662      * of a physical interface and given different settings (like address or
663      * MTU). Usually the name of the interface will the name of the parent
664      * followed by a colon (:) and a number identifying the child since there
665      * can be several virtual interfaces attached to a single physical
666      * interface.
667      *
668      * @return {@code true} if this interface is a virtual interface.
669      * @since 1.6
670      */
isVirtual()671     public boolean isVirtual() {
672         return virtual;
673     }
674 
675     // BEGIN Android-removed: Rewrote NetworkInterface on top of Libcore.io.
676     /*
677     private native static boolean isUp0(String name, int ind) throws SocketException;
678     private native static boolean isLoopback0(String name, int ind) throws SocketException;
679     private native static boolean supportsMulticast0(String name, int ind) throws SocketException;
680     private native static boolean isP2P0(String name, int ind) throws SocketException;
681     private native static byte[] getMacAddr0(byte[] inAddr, String name, int ind) throws SocketException;
682     private native static int getMTU0(String name, int ind) throws SocketException;
683     */
684     // END Android-removed: Rewrote NetworkInterface on top of Libcore.io.
685 
686     // BEGIN Android-added: Rewrote NetworkInterface on top of Libcore.io.
getFlags()687     private int getFlags() throws SocketException {
688         FileDescriptor fd = null;
689         try {
690             fd = Libcore.rawOs.socket(AF_INET, SOCK_DGRAM, 0);
691             return Libcore.rawOs.ioctlFlags(fd, name);
692         } catch (ErrnoException e) {
693             throw e.rethrowAsSocketException();
694         } catch (Exception ex) {
695             throw new SocketException(ex);
696         } finally {
697             IoUtils.closeQuietly(fd);
698         }
699     }
700     // END Android-added: Rewrote NetworkInterface on top of Libcore.io.
701 
702     /**
703      * Compares this object against the specified object.
704      * The result is {@code true} if and only if the argument is
705      * not {@code null} and it represents the same NetworkInterface
706      * as this object.
707      * <p>
708      * Two instances of {@code NetworkInterface} represent the same
709      * NetworkInterface if both name and addrs are the same for both.
710      *
711      * @param   obj   the object to compare against.
712      * @return  {@code true} if the objects are the same;
713      *          {@code false} otherwise.
714      * @see     java.net.InetAddress#getAddress()
715      */
equals(Object obj)716     public boolean equals(Object obj) {
717         if (!(obj instanceof NetworkInterface)) {
718             return false;
719         }
720         NetworkInterface that = (NetworkInterface)obj;
721         if (this.name != null ) {
722             if (!this.name.equals(that.name)) {
723                 return false;
724             }
725         } else {
726             if (that.name != null) {
727                 return false;
728             }
729         }
730 
731         if (this.addrs == null) {
732             return that.addrs == null;
733         } else if (that.addrs == null) {
734             return false;
735         }
736 
737         /* Both addrs not null. Compare number of addresses */
738 
739         if (this.addrs.length != that.addrs.length) {
740             return false;
741         }
742 
743         InetAddress[] thatAddrs = that.addrs;
744         int count = thatAddrs.length;
745 
746         for (int i=0; i<count; i++) {
747             boolean found = false;
748             for (int j=0; j<count; j++) {
749                 if (addrs[i].equals(thatAddrs[j])) {
750                     found = true;
751                     break;
752                 }
753             }
754             if (!found) {
755                 return false;
756             }
757         }
758         return true;
759     }
760 
hashCode()761     public int hashCode() {
762         return name == null? 0: name.hashCode();
763     }
764 
toString()765     public String toString() {
766         String result = "name:";
767         result += name == null? "null": name;
768         if (displayName != null) {
769             result += " (" + displayName + ")";
770         }
771         return result;
772     }
773 
774     // Android-removed: Android doesn't need to call native init.
775     // private static native void init();
776 
777     /**
778      * Returns the default network interface of this system
779      *
780      * @return the default interface
781      */
getDefault()782     static NetworkInterface getDefault() {
783         return defaultInterface;
784     }
785 }
786