1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/*
2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Licensed to the Apache Software Foundation (ASF) under one or more
3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  contributor license agreements.  See the NOTICE file distributed with
4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  this work for additional information regarding copyright ownership.
5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  The ASF licenses this file to You under the Apache License, Version 2.0
6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  (the "License"); you may not use this file except in compliance with
7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  the License.  You may obtain a copy of the License at
8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  See the License for the specific language governing permissions and
15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  limitations under the License.
16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage java.net;
19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
205d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughesimport android.system.ErrnoException;
21a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughesimport java.io.File;
22a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughesimport java.io.FileDescriptor;
23a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughesimport java.io.IOException;
24d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughesimport java.util.ArrayList;
25a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughesimport java.util.Arrays;
26d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughesimport java.util.Collections;
27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Enumeration;
28d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughesimport java.util.LinkedList;
29b5fc5ecd3fe5315fc2756c0c25adc458cc8c8d91Elliott Hughesimport java.util.List;
30a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughesimport libcore.io.IoUtils;
31a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughesimport libcore.io.Libcore;
325d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughesimport static android.system.OsConstants.*;
33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This class is used to represent a network interface of the local device. An
36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * interface is defined by its address and a platform dependent name. The class
37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * provides methods to get all information about the available interfaces of the
38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * system or to identify the local interface of a joined multicast group.
39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic final class NetworkInterface extends Object {
41ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath    private static final File SYS_CLASS_NET = new File("/sys/class/net");
42ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath
43d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes    private final String name;
44a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes    private final int interfaceIndex;
45a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    private final List<InterfaceAddress> interfaceAddresses;
46a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    private final List<InetAddress> addresses;
47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
48a9c6c9013b08934867f71b69a90efce0c1b66918Elliott Hughes    private final List<NetworkInterface> children = new LinkedList<NetworkInterface>();
49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
50d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes    private NetworkInterface parent = null;
51d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes
52a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    private NetworkInterface(String name, int interfaceIndex,
53a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            List<InetAddress> addresses, List<InterfaceAddress> interfaceAddresses) {
54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.name = name;
55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.interfaceIndex = interfaceIndex;
56a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        this.addresses = addresses;
57a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        this.interfaceAddresses = interfaceAddresses;
58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
60a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    static NetworkInterface forUnboundMulticastSocket() {
61a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        // This is what the RI returns for a MulticastSocket that hasn't been constrained
62a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        // to a specific interface.
63a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        return new NetworkInterface(null, -1,
64a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes                Arrays.asList(Inet6Address.ANY), Collections.<InterfaceAddress>emptyList());
65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
68a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes     * Returns the index for the network interface, or -1 if unknown.
698ffa0b68c9fd3f722bee2bcd94b1d38151a0791dElliott Hughes     * @since 1.7
70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
71a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    public int getIndex() {
72a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        return interfaceIndex;
73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
76a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes     * Returns the name of this network interface (such as "eth0" or "lo").
77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String getName() {
79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return name;
80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
83a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes     * Returns an enumeration of the addresses bound to this network interface.
84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public Enumeration<InetAddress> getInetAddresses() {
86ad41624e761bcf1af9c8008eb45187fc13983717Elliott Hughes        return Collections.enumeration(addresses);
87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
90a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes     * Returns a human-readable name for this network interface. On Android, this is the same
91a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes     * string as returned by {@link #getName}.
92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String getDisplayName() {
94a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        return name;
95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
98a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes     * Returns the {@code NetworkInterface} corresponding to the named network interface, or null
99a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes     * if no interface has this name.
100f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
101a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes     * @throws SocketException if an error occurs.
102a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes     * @throws NullPointerException if {@code interfaceName == null}.
103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
104d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes    public static NetworkInterface getByName(String interfaceName) throws SocketException {
105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (interfaceName == null) {
106a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            throw new NullPointerException("interfaceName == null");
107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
108a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        if (!isValidInterfaceName(interfaceName)) {
109a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            return null;
110a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        }
111a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes
112ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath        return getByNameInternal(interfaceName, readIfInet6Lines());
113ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath    }
114ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath
115ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath    /**
116ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath     * Similar to {@link #getByName(String)} except that {@code interfaceName}
117ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath     * is assumed to be valid.
118ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath     */
119ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath    private static NetworkInterface getByNameInternal(String interfaceName,
120ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath            String[] ifInet6Lines) throws SocketException {
121a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        int interfaceIndex = readIntFile("/sys/class/net/" + interfaceName + "/ifindex");
122a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        List<InetAddress> addresses = new ArrayList<InetAddress>();
123a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        List<InterfaceAddress> interfaceAddresses = new ArrayList<InterfaceAddress>();
124ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath
125ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath        collectIpv6Addresses(interfaceName, interfaceIndex, addresses, interfaceAddresses,
126ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath                ifInet6Lines);
127a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        collectIpv4Address(interfaceName, addresses, interfaceAddresses);
128a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes
129a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        return new NetworkInterface(interfaceName, interfaceIndex, addresses, interfaceAddresses);
130a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    }
131a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes
132ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath    private static String[] readIfInet6Lines() throws SocketException {
133ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath        try {
134ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath            return IoUtils.readFileAsString("/proc/net/if_inet6").split("\n");
135ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath        } catch (IOException ioe) {
136ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath            throw rethrowAsSocketException(ioe);
137ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath        }
138ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath    }
139ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath
140ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath    /**
141ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath     * Visible for testing only.
142ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath     *
143ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath     * @hide
144ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath     */
145ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath    public static void collectIpv6Addresses(String interfaceName, int interfaceIndex,
146ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath            List<InetAddress> addresses, List<InterfaceAddress> interfaceAddresses,
147ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath            String[] ifInet6Lines) throws SocketException {
148b0e6dc5464f959b3d42f37b32f4b01767f6fe506Elliott Hughes        // Format of /proc/net/if_inet6.
149b0e6dc5464f959b3d42f37b32f4b01767f6fe506Elliott Hughes        // All numeric fields are implicit hex,
150b0e6dc5464f959b3d42f37b32f4b01767f6fe506Elliott Hughes        // but not necessarily two-digit (http://code.google.com/p/android/issues/detail?id=34022).
151a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        // 1. IPv6 address
152a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        // 2. interface index
153a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        // 3. prefix length
154a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        // 4. scope
155a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        // 5. flags
156a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        // 6. interface name
157a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        // "00000000000000000000000000000001 01 80 10 80       lo"
158b0e6dc5464f959b3d42f37b32f4b01767f6fe506Elliott Hughes        // "fe800000000000000000000000000000 407 40 20 80    wlan0"
159ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath        final String suffix = " " + interfaceName;
160a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        try {
161ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath            for (String line : ifInet6Lines) {
162a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes                if (!line.endsWith(suffix)) {
163a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes                    continue;
164a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes                }
165b0e6dc5464f959b3d42f37b32f4b01767f6fe506Elliott Hughes
166b0e6dc5464f959b3d42f37b32f4b01767f6fe506Elliott Hughes                // Extract the IPv6 address.
167a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes                byte[] addressBytes = new byte[16];
168a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes                for (int i = 0; i < addressBytes.length; ++i) {
169a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes                    addressBytes[i] = (byte) Integer.parseInt(line.substring(2*i, 2*i + 2), 16);
170a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes                }
171a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes
172b0e6dc5464f959b3d42f37b32f4b01767f6fe506Elliott Hughes                // Extract the prefix length.
173b0e6dc5464f959b3d42f37b32f4b01767f6fe506Elliott Hughes                // Skip the IPv6 address and its trailing space.
174b0e6dc5464f959b3d42f37b32f4b01767f6fe506Elliott Hughes                int prefixLengthStart = 32 + 1;
175b0e6dc5464f959b3d42f37b32f4b01767f6fe506Elliott Hughes                // Skip the interface index and its trailing space.
176b0e6dc5464f959b3d42f37b32f4b01767f6fe506Elliott Hughes                prefixLengthStart = line.indexOf(' ', prefixLengthStart) + 1;
177b0e6dc5464f959b3d42f37b32f4b01767f6fe506Elliott Hughes                int prefixLengthEnd = line.indexOf(' ', prefixLengthStart);
178b0e6dc5464f959b3d42f37b32f4b01767f6fe506Elliott Hughes                short prefixLength = Short.parseShort(line.substring(prefixLengthStart, prefixLengthEnd), 16);
179b0e6dc5464f959b3d42f37b32f4b01767f6fe506Elliott Hughes
180b0e6dc5464f959b3d42f37b32f4b01767f6fe506Elliott Hughes                Inet6Address inet6Address = new Inet6Address(addressBytes, null, interfaceIndex);
181a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes                addresses.add(inet6Address);
182a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes                interfaceAddresses.add(new InterfaceAddress(inet6Address, prefixLength));
183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
184ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath        } catch (NumberFormatException ex) {
185a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            throw rethrowAsSocketException(ex);
186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
187a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    }
188a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes
189a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    private static void collectIpv4Address(String interfaceName, List<InetAddress> addresses,
190a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            List<InterfaceAddress> interfaceAddresses) throws SocketException {
191a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        FileDescriptor fd = null;
192a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        try {
193a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            fd = Libcore.os.socket(AF_INET, SOCK_DGRAM, 0);
194a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            InetAddress address = Libcore.os.ioctlInetAddress(fd, SIOCGIFADDR, interfaceName);
195a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            InetAddress broadcast = Libcore.os.ioctlInetAddress(fd, SIOCGIFBRDADDR, interfaceName);
196a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            InetAddress netmask = Libcore.os.ioctlInetAddress(fd, SIOCGIFNETMASK, interfaceName);
197a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            if (broadcast.equals(Inet4Address.ANY)) {
198a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes                broadcast = null;
199a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            }
200a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes
201a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            addresses.add(address);
202a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            interfaceAddresses.add(new InterfaceAddress((Inet4Address) address,
203a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes                    (Inet4Address) broadcast, (Inet4Address) netmask));
204a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        } catch (ErrnoException errnoException) {
205a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            if (errnoException.errno != EADDRNOTAVAIL) {
206a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes                // EADDRNOTAVAIL just means no IPv4 address for this interface.
207a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes                // Anything else is a real error.
208a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes                throw rethrowAsSocketException(errnoException);
209a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            }
210a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        } catch (Exception ex) {
211a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            throw rethrowAsSocketException(ex);
212a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        } finally {
213a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            IoUtils.closeQuietly(fd);
214a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        }
215a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    }
216a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes
2170d4daefcf389b6433a0af481ef44a84a2546541aElliott Hughes    @FindBugsSuppressWarnings("DMI_HARDCODED_ABSOLUTE_FILENAME")
218a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    private static boolean isValidInterfaceName(String interfaceName) {
219ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath        final String[] interfaceList = SYS_CLASS_NET.list();
220ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath        // We have no interfaces listed under /sys/class/net
221ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath        if (interfaceList == null) {
222ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath            return false;
223ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath        }
224ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath
225a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        // Don't just stat because a crafty user might have / or .. in the supposed interface name.
226ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath        for (String validName : interfaceList) {
227a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            if (interfaceName.equals(validName)) {
228a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes                return true;
229a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            }
230a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        }
231a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        return false;
232a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    }
233a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes
234a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    private static int readIntFile(String path) throws SocketException {
235a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        try {
236a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            String s = IoUtils.readFileAsString(path).trim();
237a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            if (s.startsWith("0x")) {
238a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes                return Integer.parseInt(s.substring(2), 16);
239a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            } else {
240a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes                return Integer.parseInt(s);
241a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            }
242a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        } catch (Exception ex) {
243a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            throw rethrowAsSocketException(ex);
244a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        }
245a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    }
246a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes
247a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    private static SocketException rethrowAsSocketException(Exception ex) throws SocketException {
248a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        SocketException result = new SocketException();
249a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        result.initCause(ex);
250a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        throw result;
251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
254c3d19477189eafcdfec5735f9e5e13ffdeaf963dElliott Hughes     * Returns the {@code NetworkInterface} corresponding to the given address, or null if no
255c3d19477189eafcdfec5735f9e5e13ffdeaf963dElliott Hughes     * interface has this address.
256f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
257c3d19477189eafcdfec5735f9e5e13ffdeaf963dElliott Hughes     * @throws SocketException if an error occurs.
258c3d19477189eafcdfec5735f9e5e13ffdeaf963dElliott Hughes     * @throws NullPointerException if {@code address == null}.
259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
260d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes    public static NetworkInterface getByInetAddress(InetAddress address) throws SocketException {
261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (address == null) {
262b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new NullPointerException("address == null");
263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
264d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes        for (NetworkInterface networkInterface : getNetworkInterfacesList()) {
265d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes            if (networkInterface.addresses.contains(address)) {
266d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes                return networkInterface;
267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return null;
270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
273c3d19477189eafcdfec5735f9e5e13ffdeaf963dElliott Hughes     * Returns the NetworkInterface corresponding to the given interface index, or null if no
274c3d19477189eafcdfec5735f9e5e13ffdeaf963dElliott Hughes     * interface has this index.
275c3d19477189eafcdfec5735f9e5e13ffdeaf963dElliott Hughes     *
276c3d19477189eafcdfec5735f9e5e13ffdeaf963dElliott Hughes     * @throws SocketException if an error occurs.
2778ffa0b68c9fd3f722bee2bcd94b1d38151a0791dElliott Hughes     * @since 1.7
278c3d19477189eafcdfec5735f9e5e13ffdeaf963dElliott Hughes     */
279c3d19477189eafcdfec5735f9e5e13ffdeaf963dElliott Hughes    public static NetworkInterface getByIndex(int index) throws SocketException {
280a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        String name = Libcore.os.if_indextoname(index);
281a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        if (name == null) {
282a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            return null;
283c3d19477189eafcdfec5735f9e5e13ffdeaf963dElliott Hughes        }
284a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        return NetworkInterface.getByName(name);
285c3d19477189eafcdfec5735f9e5e13ffdeaf963dElliott Hughes    }
286c3d19477189eafcdfec5735f9e5e13ffdeaf963dElliott Hughes
287c3d19477189eafcdfec5735f9e5e13ffdeaf963dElliott Hughes    /**
288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Gets a list of all network interfaces available on the local system or
289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code null} if no interface is available.
290f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the list of {@code NetworkInterface} instances representing the
292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         available interfaces.
293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws SocketException
294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an error occurs while getting the network interface
295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             information.
296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
297d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes    public static Enumeration<NetworkInterface> getNetworkInterfaces() throws SocketException {
298d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes        return Collections.enumeration(getNetworkInterfacesList());
299d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes    }
300d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes
3010d4daefcf389b6433a0af481ef44a84a2546541aElliott Hughes    @FindBugsSuppressWarnings("DMI_HARDCODED_ABSOLUTE_FILENAME")
302d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes    private static List<NetworkInterface> getNetworkInterfacesList() throws SocketException {
303ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath        String[] interfaceNames = SYS_CLASS_NET.list();
304a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        NetworkInterface[] interfaces = new NetworkInterface[interfaceNames.length];
3054bbc5de89764a9bcdb62c65be31e0f110578d427Elliott Hughes        boolean[] done = new boolean[interfaces.length];
306ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath
307ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath        String[] ifInet6Lines = readIfInet6Lines();
308a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        for (int i = 0; i < interfaceNames.length; ++i) {
309ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath            interfaces[i] = NetworkInterface.getByNameInternal(interfaceNames[i], ifInet6Lines);
3104bbc5de89764a9bcdb62c65be31e0f110578d427Elliott Hughes            // http://b/5833739: getByName can return null if the interface went away between our
3114bbc5de89764a9bcdb62c65be31e0f110578d427Elliott Hughes            // readdir(2) and our stat(2), so mark interfaces that disappeared as 'done'.
3124bbc5de89764a9bcdb62c65be31e0f110578d427Elliott Hughes            if (interfaces[i] == null) {
3134bbc5de89764a9bcdb62c65be31e0f110578d427Elliott Hughes                done[i] = true;
3144bbc5de89764a9bcdb62c65be31e0f110578d427Elliott Hughes            }
315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
317d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes        List<NetworkInterface> result = new ArrayList<NetworkInterface>();
318d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes        for (int counter = 0; counter < interfaces.length; counter++) {
3194bbc5de89764a9bcdb62c65be31e0f110578d427Elliott Hughes            // If this interface has been dealt with already, continue.
3204bbc5de89764a9bcdb62c65be31e0f110578d427Elliott Hughes            if (done[counter]) {
321d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes                continue;
322d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes            }
323ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath
324d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes            // Checks whether the following interfaces are children.
325ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath            for (int counter2 = counter; counter2 < interfaces.length; counter2++) {
3264bbc5de89764a9bcdb62c65be31e0f110578d427Elliott Hughes                if (done[counter2]) {
327d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes                    continue;
328d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes                }
329d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes                if (interfaces[counter2].name.startsWith(interfaces[counter].name + ":")) {
330d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes                    interfaces[counter].children.add(interfaces[counter2]);
331d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes                    interfaces[counter2].parent = interfaces[counter];
332d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes                    interfaces[counter].addresses.addAll(interfaces[counter2].addresses);
3334bbc5de89764a9bcdb62c65be31e0f110578d427Elliott Hughes                    done[counter2] = true;
334ab6d858336e6db8b5117b78837fee2a9f35fdf2cNarayan Kamath                }
335d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes            }
336d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes            result.add(interfaces[counter]);
3374bbc5de89764a9bcdb62c65be31e0f110578d427Elliott Hughes            done[counter] = true;
338d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes        }
339d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes        return result;
340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
342adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Compares the specified object to this {@code NetworkInterface} and
344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * returns whether they are equal or not. The object must be an instance of
345a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes     * {@code NetworkInterface} with the same name, display name, and list
346a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes     * of interface addresses.
347f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param obj
349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the object to compare with this instance.
350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if the specified object is equal to this {@code
351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         NetworkInterface}, {@code false} otherwise.
3525839b909d9528b7726e678a4b696ed37df15d897Jesse Wilson     * @see #hashCode()
353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean equals(Object obj) {
356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (obj == this) {
357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return true;
358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
3595839b909d9528b7726e678a4b696ed37df15d897Jesse Wilson        if (!(obj instanceof NetworkInterface)) {
3605839b909d9528b7726e678a4b696ed37df15d897Jesse Wilson            return false;
3615839b909d9528b7726e678a4b696ed37df15d897Jesse Wilson        }
362d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes        NetworkInterface rhs = (NetworkInterface) obj;
363d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes        // TODO: should the order of the addresses matter (we use List.equals)?
364d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes        return interfaceIndex == rhs.interfaceIndex &&
365a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes                name.equals(rhs.name) &&
366d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes                addresses.equals(rhs.addresses);
367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
370d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * Returns the hash code for this {@code NetworkInterface}. Since the
371d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * name should be unique for each network interface the hash code is
372a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes     * generated using the name.
373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
374a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    @Override public int hashCode() {
375d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes        return name.hashCode();
376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
37810914811ea02b4acc7ab1dc5a0ada1b54cdf2203Elliott Hughes    /**
37910914811ea02b4acc7ab1dc5a0ada1b54cdf2203Elliott Hughes     * Returns a string containing details of this network interface.
38010914811ea02b4acc7ab1dc5a0ada1b54cdf2203Elliott Hughes     * The exact format is deliberately unspecified. Callers that require a specific
38110914811ea02b4acc7ab1dc5a0ada1b54cdf2203Elliott Hughes     * format should build a string themselves, using this class' accessor methods.
38210914811ea02b4acc7ab1dc5a0ada1b54cdf2203Elliott Hughes     */
383a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    @Override public String toString() {
384a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        StringBuilder sb = new StringBuilder(25);
385a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        sb.append("[");
386a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        sb.append(name);
387a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        sb.append("][");
388a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        sb.append(interfaceIndex);
389a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        sb.append("]");
390a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        for (InetAddress address : addresses) {
391a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            sb.append("[");
392a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            sb.append(address.toString());
393a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            sb.append("]");
394adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
395a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        return sb.toString();
396adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
397d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes
398d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes    /**
399ad41624e761bcf1af9c8008eb45187fc13983717Elliott Hughes     * Returns a List of the InterfaceAddresses for this network interface.
400d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * @since 1.6
401d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     */
402d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes    public List<InterfaceAddress> getInterfaceAddresses() {
403ad41624e761bcf1af9c8008eb45187fc13983717Elliott Hughes        return Collections.unmodifiableList(interfaceAddresses);
404d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes    }
405d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes
406d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes    /**
407a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes     * Returns an enumeration of all the sub-interfaces of this network interface.
408d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * Sub-interfaces are also known as virtual interfaces.
409a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes     *
410a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes     * <p>For example, {@code eth0:1} would be a sub-interface of {@code eth0}.
411f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
412d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * @return an Enumeration of all the sub-interfaces of this network interface
413d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * @since 1.6
414d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     */
415d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes    public Enumeration<NetworkInterface> getSubInterfaces() {
416d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes        return Collections.enumeration(children);
417d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes    }
418d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes
419d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes    /**
420d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * Returns the parent NetworkInterface of this interface if this is a
421d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * sub-interface, or null if it's a physical (non virtual) interface.
422f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
423d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * @return the NetworkInterface this interface is attached to.
424d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * @since 1.6
425d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     */
426d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes    public NetworkInterface getParent() {
427d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes        return parent;
428d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes    }
429d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes
430d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes    /**
431d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * Returns true if this network interface is up.
432f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
433d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * @return true if the interface is up.
434d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * @throws SocketException if an I/O error occurs.
435d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * @since 1.6
436d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     */
437d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes    public boolean isUp() throws SocketException {
438a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        return hasFlag(IFF_UP);
439d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes    }
440d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes
441d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes    /**
442d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * Returns true if this network interface is a loopback interface.
443f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
444d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * @return true if the interface is a loopback interface.
445d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * @throws SocketException if an I/O error occurs.
446d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * @since 1.6
447d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     */
448d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes    public boolean isLoopback() throws SocketException {
449a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        return hasFlag(IFF_LOOPBACK);
450d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes    }
451d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes
452d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes    /**
453d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * Returns true if this network interface is a point-to-point interface.
454d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * (For example, a PPP connection using a modem.)
455f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
456d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * @return true if the interface is point-to-point.
457d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * @throws SocketException if an I/O error occurs.
458d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * @since 1.6
459d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     */
460d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes    public boolean isPointToPoint() throws SocketException {
461a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        return hasFlag(IFF_POINTOPOINT);
462d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes    }
463d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes
464d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes    /**
465d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * Returns true if this network interface supports multicast.
466f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
467d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * @throws SocketException if an I/O error occurs.
468d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * @since 1.6
469d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     */
470d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes    public boolean supportsMulticast() throws SocketException {
471a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        return hasFlag(IFF_MULTICAST);
472a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    }
473a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes
474a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    private boolean hasFlag(int mask) throws SocketException {
475a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        int flags = readIntFile("/sys/class/net/" + name + "/flags");
476a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        return (flags & mask) != 0;
477d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes    }
478d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes
479d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes    /**
480a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes     * Returns the hardware address of the interface, if it has one, or null otherwise.
481f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
482d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * @throws SocketException if an I/O error occurs.
483d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * @since 1.6
484d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     */
485d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes    public byte[] getHardwareAddress() throws SocketException {
486a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        try {
487a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            // Parse colon-separated bytes with a trailing newline: "aa:bb:cc:dd:ee:ff\n".
488a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            String s = IoUtils.readFileAsString("/sys/class/net/" + name + "/address");
489a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            byte[] result = new byte[s.length()/3];
490a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            for (int i = 0; i < result.length; ++i) {
491a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes                result[i] = (byte) Integer.parseInt(s.substring(3*i, 3*i + 2), 16);
492a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            }
493a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            // We only want to return non-zero hardware addresses.
494a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            for (int i = 0; i < result.length; ++i) {
495a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes                if (result[i] != 0) {
496a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes                    return result;
497a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes                }
498a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            }
499a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            return null;
500a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        } catch (Exception ex) {
501a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            throw rethrowAsSocketException(ex);
502d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes        }
503d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes    }
504d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes
505d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes    /**
506d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * Returns the Maximum Transmission Unit (MTU) of this interface.
507f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
508d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * @return the value of the MTU for the interface.
509d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * @throws SocketException if an I/O error occurs.
510d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * @since 1.6
511d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     */
512d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes    public int getMTU() throws SocketException {
513a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        return readIntFile("/sys/class/net/" + name + "/mtu");
514d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes    }
515d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes
516d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes    /**
517d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * Returns true if this interface is a virtual interface (also called
518d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * a sub-interface). Virtual interfaces are, on some systems, interfaces
519d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * created as a child of a physical interface and given different settings
520d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * (like address or MTU). Usually the name of the interface will the name of
521d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * the parent followed by a colon (:) and a number identifying the child,
522d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * since there can be several virtual interfaces attached to a single
523d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * physical interface.
524f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
525d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * @return true if this interface is a virtual interface.
526d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     * @since 1.6
527d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes     */
528d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes    public boolean isVirtual() {
529d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes        return parent != null;
530d2af45a6fd008ceb958ac74e5a50e582b8419e9cElliott Hughes    }
531adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
532