NetworkUtils.java revision 8171e6f690cca1bad354e7e352823d79d420daf3
1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.net;
18
19import java.net.InetAddress;
20import java.net.Inet4Address;
21import java.net.Inet6Address;
22import java.net.UnknownHostException;
23
24import android.util.Log;
25
26/**
27 * Native methods for managing network interfaces.
28 *
29 * {@hide}
30 */
31public class NetworkUtils {
32
33    private static final String TAG = "NetworkUtils";
34
35    /** Bring the named network interface up. */
36    public native static int enableInterface(String interfaceName);
37
38    /** Bring the named network interface down. */
39    public native static int disableInterface(String interfaceName);
40
41    /** Setting bit 0 indicates reseting of IPv4 addresses required */
42    public static final int RESET_IPV4_ADDRESSES = 0x01;
43
44    /** Setting bit 1 indicates reseting of IPv4 addresses required */
45    public static final int RESET_IPV6_ADDRESSES = 0x02;
46
47    /** Reset all addresses */
48    public static final int RESET_ALL_ADDRESSES = RESET_IPV4_ADDRESSES | RESET_IPV6_ADDRESSES;
49
50    /**
51     * Reset IPv6 or IPv4 sockets that are connected via the named interface.
52     *
53     * @param interfaceName is the interface to reset
54     * @param mask {@see #RESET_IPV4_ADDRESSES} and {@see #RESET_IPV6_ADDRESSES}
55     */
56    public native static int resetConnections(String interfaceName, int mask);
57
58    /**
59     * Start the DHCP client daemon, in order to have it request addresses
60     * for the named interface, and then configure the interface with those
61     * addresses. This call blocks until it obtains a result (either success
62     * or failure) from the daemon.
63     * @param interfaceName the name of the interface to configure
64     * @param ipInfo if the request succeeds, this object is filled in with
65     * the IP address information.
66     * @return {@code true} for success, {@code false} for failure
67     */
68    public native static boolean runDhcp(String interfaceName, DhcpInfoInternal ipInfo);
69
70    /**
71     * Initiate renewal on the Dhcp client daemon. This call blocks until it obtains
72     * a result (either success or failure) from the daemon.
73     * @param interfaceName the name of the interface to configure
74     * @param ipInfo if the request succeeds, this object is filled in with
75     * the IP address information.
76     * @return {@code true} for success, {@code false} for failure
77     */
78    public native static boolean runDhcpRenew(String interfaceName, DhcpInfoInternal ipInfo);
79
80    /**
81     * Shut down the DHCP client daemon.
82     * @param interfaceName the name of the interface for which the daemon
83     * should be stopped
84     * @return {@code true} for success, {@code false} for failure
85     */
86    public native static boolean stopDhcp(String interfaceName);
87
88    /**
89     * Release the current DHCP lease.
90     * @param interfaceName the name of the interface for which the lease should
91     * be released
92     * @return {@code true} for success, {@code false} for failure
93     */
94    public native static boolean releaseDhcpLease(String interfaceName);
95
96    /**
97     * Return the last DHCP-related error message that was recorded.
98     * <p/>NOTE: This string is not localized, but currently it is only
99     * used in logging.
100     * @return the most recent error message, if any
101     */
102    public native static String getDhcpError();
103
104    /**
105     * Convert a IPv4 address from an integer to an InetAddress.
106     * @param hostAddress an int corresponding to the IPv4 address in network byte order
107     */
108    public static InetAddress intToInetAddress(int hostAddress) {
109        byte[] addressBytes = { (byte)(0xff & hostAddress),
110                                (byte)(0xff & (hostAddress >> 8)),
111                                (byte)(0xff & (hostAddress >> 16)),
112                                (byte)(0xff & (hostAddress >> 24)) };
113
114        try {
115           return InetAddress.getByAddress(addressBytes);
116        } catch (UnknownHostException e) {
117           throw new AssertionError();
118        }
119    }
120
121    /**
122     * Convert a IPv4 address from an InetAddress to an integer
123     * @param inetAddr is an InetAddress corresponding to the IPv4 address
124     * @return the IP address as an integer in network byte order
125     */
126    public static int inetAddressToInt(InetAddress inetAddr)
127            throws IllegalArgumentException {
128        byte [] addr = inetAddr.getAddress();
129        if (addr.length != 4) {
130            throw new IllegalArgumentException("Not an IPv4 address");
131        }
132        return ((addr[3] & 0xff) << 24) | ((addr[2] & 0xff) << 16) |
133                ((addr[1] & 0xff) << 8) | (addr[0] & 0xff);
134    }
135
136    /**
137     * Convert a network prefix length to an IPv4 netmask integer
138     * @param prefixLength
139     * @return the IPv4 netmask as an integer in network byte order
140     */
141    public static int prefixLengthToNetmaskInt(int prefixLength)
142            throws IllegalArgumentException {
143        if (prefixLength < 0 || prefixLength > 32) {
144            throw new IllegalArgumentException("Invalid prefix length (0 <= prefix <= 32)");
145        }
146        int value = 0xffffffff << (32 - prefixLength);
147        return Integer.reverseBytes(value);
148    }
149
150    /**
151     * Convert a IPv4 netmask integer to a prefix length
152     * @param netmask as an integer in network byte order
153     * @return the network prefix length
154     */
155    public static int netmaskIntToPrefixLength(int netmask) {
156        return Integer.bitCount(netmask);
157    }
158
159    /**
160     * Create an InetAddress from a string where the string must be a standard
161     * representation of a V4 or V6 address.  Avoids doing a DNS lookup on failure
162     * but it will throw an IllegalArgumentException in that case.
163     * @param addrString
164     * @return the InetAddress
165     * @hide
166     */
167    public static InetAddress numericToInetAddress(String addrString)
168            throws IllegalArgumentException {
169        return InetAddress.parseNumericAddress(addrString);
170    }
171
172    /**
173     * Get InetAddress masked with prefixLength.  Will never return null.
174     * @param IP address which will be masked with specified prefixLength
175     * @param prefixLength the prefixLength used to mask the IP
176     */
177    public static InetAddress getNetworkPart(InetAddress address, int prefixLength) {
178        if (address == null) {
179            throw new RuntimeException("getNetworkPart doesn't accept null address");
180        }
181
182        byte[] array = address.getAddress();
183
184        if (prefixLength < 0 || prefixLength > array.length * 8) {
185            throw new RuntimeException("getNetworkPart - bad prefixLength");
186        }
187
188        int offset = prefixLength / 8;
189        int reminder = prefixLength % 8;
190        byte mask = (byte)(0xFF << (8 - reminder));
191
192        if (offset < array.length) array[offset] = (byte)(array[offset] & mask);
193
194        offset++;
195
196        for (; offset < array.length; offset++) {
197            array[offset] = 0;
198        }
199
200        InetAddress netPart = null;
201        try {
202            netPart = InetAddress.getByAddress(array);
203        } catch (UnknownHostException e) {
204            throw new RuntimeException("getNetworkPart error - " + e.toString());
205        }
206        return netPart;
207    }
208
209    /**
210     * Check if IP address type is consistent between two InetAddress.
211     * @return true if both are the same type.  False otherwise.
212     */
213    public static boolean addressTypeMatches(InetAddress left, InetAddress right) {
214        return (((left instanceof Inet4Address) && (right instanceof Inet4Address)) ||
215                ((left instanceof Inet6Address) && (right instanceof Inet6Address)));
216    }
217
218    /**
219     * Convert a 32 char hex string into a Inet6Address.
220     * throws a runtime exception if the string isn't 32 chars, isn't hex or can't be
221     * made into an Inet6Address
222     * @param addrHexString a 32 character hex string representing an IPv6 addr
223     * @return addr an InetAddress representation for the string
224     */
225    public static InetAddress hexToInet6Address(String addrHexString)
226            throws IllegalArgumentException {
227        try {
228            return numericToInetAddress(String.format("%s:%s:%s:%s:%s:%s:%s:%s",
229                    addrHexString.substring(0,4),   addrHexString.substring(4,8),
230                    addrHexString.substring(8,12),  addrHexString.substring(12,16),
231                    addrHexString.substring(16,20), addrHexString.substring(20,24),
232                    addrHexString.substring(24,28), addrHexString.substring(28,32)));
233        } catch (Exception e) {
234            Log.e("NetworkUtils", "error in hexToInet6Address(" + addrHexString + "): " + e);
235            throw new IllegalArgumentException(e);
236        }
237    }
238}
239