blob: 29dd8ad9e95157e905f8f875e737480f82793d4f [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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
Lorenzo Colitti566e0cb2015-03-06 19:57:39 +090019import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import java.net.InetAddress;
Robert Greenwalt585ac0f2010-08-27 09:24:29 -070021import java.net.Inet4Address;
22import java.net.Inet6Address;
Lorenzo Colitti566e0cb2015-03-06 19:57:39 +090023import java.net.SocketException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024import java.net.UnknownHostException;
Robert Greenwalta10b7fd2011-07-25 16:06:25 -070025import java.util.Collection;
Jeff Sharkeyfea17de2013-06-11 14:13:09 -070026import java.util.Locale;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027
Lorenzo Colitti0a82e802014-07-31 00:48:01 +090028import android.os.Parcel;
Robert Greenwalt585ac0f2010-08-27 09:24:29 -070029import android.util.Log;
Lorenzo Colitti8c6c2c32014-06-12 13:41:17 +090030import android.util.Pair;
31
Robert Greenwalt585ac0f2010-08-27 09:24:29 -070032
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033/**
34 * Native methods for managing network interfaces.
35 *
36 * {@hide}
37 */
38public class NetworkUtils {
Robert Greenwalt585ac0f2010-08-27 09:24:29 -070039
40 private static final String TAG = "NetworkUtils";
41
Wink Saville8171e6f2011-07-07 16:17:06 -070042 /** Setting bit 0 indicates reseting of IPv4 addresses required */
43 public static final int RESET_IPV4_ADDRESSES = 0x01;
44
45 /** Setting bit 1 indicates reseting of IPv4 addresses required */
46 public static final int RESET_IPV6_ADDRESSES = 0x02;
47
48 /** Reset all addresses */
49 public static final int RESET_ALL_ADDRESSES = RESET_IPV4_ADDRESSES | RESET_IPV6_ADDRESSES;
50
51 /**
52 * Reset IPv6 or IPv4 sockets that are connected via the named interface.
53 *
54 * @param interfaceName is the interface to reset
55 * @param mask {@see #RESET_IPV4_ADDRESSES} and {@see #RESET_IPV6_ADDRESSES}
56 */
57 public native static int resetConnections(String interfaceName, int mask);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058
59 /**
60 * Start the DHCP client daemon, in order to have it request addresses
Erik Kline3c3ce172015-02-19 19:51:15 +090061 * for the named interface. This returns {@code true} if the DHCPv4 daemon
62 * starts, {@code false} otherwise. This call blocks until such time as a
63 * result is available or the default discovery timeout has been reached.
64 * Callers should check {@link #getDhcpResults} to determine whether DHCP
65 * succeeded or failed, and if it succeeded, to fetch the {@link DhcpResults}.
66 * @param interfaceName the name of the interface to configure
67 * @return {@code true} for success, {@code false} for failure
68 */
69 public native static boolean startDhcp(String interfaceName);
70
71 /**
72 * Initiate renewal on the DHCP client daemon for the named interface. This
73 * returns {@code true} if the DHCPv4 daemon has been notified, {@code false}
74 * otherwise. This call blocks until such time as a result is available or
75 * the default renew timeout has been reached. Callers should check
76 * {@link #getDhcpResults} to determine whether DHCP succeeded or failed,
77 * and if it succeeded, to fetch the {@link DhcpResults}.
78 * @param interfaceName the name of the interface to configure
79 * @return {@code true} for success, {@code false} for failure
80 */
81 public native static boolean startDhcpRenew(String interfaceName);
82
83 /**
84 * Start the DHCP client daemon, in order to have it request addresses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085 * for the named interface, and then configure the interface with those
86 * addresses. This call blocks until it obtains a result (either success
87 * or failure) from the daemon.
88 * @param interfaceName the name of the interface to configure
Robert Greenwalt4717c262012-10-31 14:32:53 -070089 * @param dhcpResults if the request succeeds, this object is filled in with
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090 * the IP address information.
91 * @return {@code true} for success, {@code false} for failure
92 */
Erik Kline3c3ce172015-02-19 19:51:15 +090093 public static boolean runDhcp(String interfaceName, DhcpResults dhcpResults) {
94 return startDhcp(interfaceName) && getDhcpResults(interfaceName, dhcpResults);
95 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096
97 /**
Erik Kline3c3ce172015-02-19 19:51:15 +090098 * Initiate renewal on the DHCP client daemon. This call blocks until it obtains
Irfan Sheriff914ed902011-06-21 14:26:37 -070099 * a result (either success or failure) from the daemon.
100 * @param interfaceName the name of the interface to configure
Robert Greenwalt4717c262012-10-31 14:32:53 -0700101 * @param dhcpResults if the request succeeds, this object is filled in with
Irfan Sheriff914ed902011-06-21 14:26:37 -0700102 * the IP address information.
103 * @return {@code true} for success, {@code false} for failure
104 */
Erik Kline3c3ce172015-02-19 19:51:15 +0900105 public static boolean runDhcpRenew(String interfaceName, DhcpResults dhcpResults) {
106 return startDhcpRenew(interfaceName) && getDhcpResults(interfaceName, dhcpResults);
107 }
108
109 /**
110 * Fetch results from the DHCP client daemon. This call returns {@code true} if
111 * if there are results available to be read, {@code false} otherwise.
112 * @param interfaceName the name of the interface to configure
113 * @param dhcpResults if the request succeeds, this object is filled in with
114 * the IP address information.
115 * @return {@code true} for success, {@code false} for failure
116 */
117 public native static boolean getDhcpResults(String interfaceName, DhcpResults dhcpResults);
Irfan Sheriff914ed902011-06-21 14:26:37 -0700118
119 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120 * Shut down the DHCP client daemon.
121 * @param interfaceName the name of the interface for which the daemon
122 * should be stopped
123 * @return {@code true} for success, {@code false} for failure
124 */
125 public native static boolean stopDhcp(String interfaceName);
126
127 /**
128 * Release the current DHCP lease.
129 * @param interfaceName the name of the interface for which the lease should
130 * be released
131 * @return {@code true} for success, {@code false} for failure
132 */
133 public native static boolean releaseDhcpLease(String interfaceName);
134
135 /**
136 * Return the last DHCP-related error message that was recorded.
137 * <p/>NOTE: This string is not localized, but currently it is only
138 * used in logging.
139 * @return the most recent error message, if any
140 */
141 public native static String getDhcpError();
142
143 /**
Lorenzo Colitti566e0cb2015-03-06 19:57:39 +0900144 * Attaches a socket filter that accepts DHCP packets to the given socket.
145 */
146 public native static void attachDhcpFilter(FileDescriptor fd) throws SocketException;
147
148 /**
Paul Jensen38764952014-05-20 11:25:35 -0400149 * Binds the current process to the network designated by {@code netId}. All sockets created
150 * in the future (and not explicitly bound via a bound {@link SocketFactory} (see
Paul Jensen6d3ff9e2014-05-29 10:12:39 -0400151 * {@link Network#getSocketFactory}) will be bound to this network. Note that if this
Paul Jensen38764952014-05-20 11:25:35 -0400152 * {@code Network} ever disconnects all sockets created in this way will cease to work. This
153 * is by design so an application doesn't accidentally use sockets it thinks are still bound to
Paul Jensenbcc76d32014-07-11 08:17:29 -0400154 * a particular {@code Network}. Passing NETID_UNSET clears the binding.
Paul Jensen38764952014-05-20 11:25:35 -0400155 */
Paul Jensen32a58f02014-06-20 13:58:14 -0400156 public native static boolean bindProcessToNetwork(int netId);
Paul Jensen38764952014-05-20 11:25:35 -0400157
158 /**
Paul Jensen38764952014-05-20 11:25:35 -0400159 * Return the netId last passed to {@link #bindProcessToNetwork}, or NETID_UNSET if
160 * {@link #unbindProcessToNetwork} has been called since {@link #bindProcessToNetwork}.
161 */
Paul Jensen72db88e2015-03-10 10:54:12 -0400162 public native static int getBoundNetworkForProcess();
Paul Jensen38764952014-05-20 11:25:35 -0400163
164 /**
165 * Binds host resolutions performed by this process to the network designated by {@code netId}.
Paul Jensenbcc76d32014-07-11 08:17:29 -0400166 * {@link #bindProcessToNetwork} takes precedence over this setting. Passing NETID_UNSET clears
167 * the binding.
Paul Jensen38764952014-05-20 11:25:35 -0400168 *
169 * @deprecated This is strictly for legacy usage to support startUsingNetworkFeature().
170 */
Paul Jensen32a58f02014-06-20 13:58:14 -0400171 public native static boolean bindProcessToNetworkForHostResolution(int netId);
Paul Jensen38764952014-05-20 11:25:35 -0400172
173 /**
Paul Jensen38764952014-05-20 11:25:35 -0400174 * Explicitly binds {@code socketfd} to the network designated by {@code netId}. This
175 * overrides any binding via {@link #bindProcessToNetwork}.
Lorenzo Colitti9f1274b2014-08-21 11:45:54 -0700176 * @return 0 on success or negative errno on failure.
Paul Jensen38764952014-05-20 11:25:35 -0400177 */
Lorenzo Colitti9f1274b2014-08-21 11:45:54 -0700178 public native static int bindSocketToNetwork(int socketfd, int netId);
Paul Jensen38764952014-05-20 11:25:35 -0400179
180 /**
Lorenzo Colitti4ff9f0f2015-03-17 17:56:10 +0900181 * Protect {@code fd} from VPN connections. After protecting, data sent through
182 * this socket will go directly to the underlying network, so its traffic will not be
183 * forwarded through the VPN.
184 */
185 public static boolean protectFromVpn(FileDescriptor fd) {
186 return protectFromVpn(fd.getInt$());
187 }
188
189 /**
Paul Jensen6bc2c2c2014-05-07 15:27:40 -0400190 * Protect {@code socketfd} from VPN connections. After protecting, data sent through
191 * this socket will go directly to the underlying network, so its traffic will not be
192 * forwarded through the VPN.
193 */
194 public native static boolean protectFromVpn(int socketfd);
195
196 /**
Robert Greenwalt585ac0f2010-08-27 09:24:29 -0700197 * Convert a IPv4 address from an integer to an InetAddress.
Jesse Wilson07481cc2011-01-06 17:18:23 -0800198 * @param hostAddress an int corresponding to the IPv4 address in network byte order
Robert Greenwalt585ac0f2010-08-27 09:24:29 -0700199 */
200 public static InetAddress intToInetAddress(int hostAddress) {
Robert Greenwalt585ac0f2010-08-27 09:24:29 -0700201 byte[] addressBytes = { (byte)(0xff & hostAddress),
202 (byte)(0xff & (hostAddress >> 8)),
203 (byte)(0xff & (hostAddress >> 16)),
204 (byte)(0xff & (hostAddress >> 24)) };
205
206 try {
Jesse Wilson07481cc2011-01-06 17:18:23 -0800207 return InetAddress.getByAddress(addressBytes);
208 } catch (UnknownHostException e) {
209 throw new AssertionError();
Robert Greenwalt585ac0f2010-08-27 09:24:29 -0700210 }
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700211 }
212
Robert Greenwalt585ac0f2010-08-27 09:24:29 -0700213 /**
Irfan Sheriff96ca9172010-10-05 16:12:25 -0700214 * Convert a IPv4 address from an InetAddress to an integer
215 * @param inetAddr is an InetAddress corresponding to the IPv4 address
216 * @return the IP address as an integer in network byte order
217 */
Robert Greenwalt4717c262012-10-31 14:32:53 -0700218 public static int inetAddressToInt(Inet4Address inetAddr)
Irfan Sheriff96ca9172010-10-05 16:12:25 -0700219 throws IllegalArgumentException {
220 byte [] addr = inetAddr.getAddress();
Irfan Sheriff96ca9172010-10-05 16:12:25 -0700221 return ((addr[3] & 0xff) << 24) | ((addr[2] & 0xff) << 16) |
222 ((addr[1] & 0xff) << 8) | (addr[0] & 0xff);
223 }
224
225 /**
226 * Convert a network prefix length to an IPv4 netmask integer
227 * @param prefixLength
228 * @return the IPv4 netmask as an integer in network byte order
229 */
230 public static int prefixLengthToNetmaskInt(int prefixLength)
231 throws IllegalArgumentException {
232 if (prefixLength < 0 || prefixLength > 32) {
233 throw new IllegalArgumentException("Invalid prefix length (0 <= prefix <= 32)");
234 }
235 int value = 0xffffffff << (32 - prefixLength);
236 return Integer.reverseBytes(value);
237 }
238
Irfan Sheriff96ca9172010-10-05 16:12:25 -0700239 /**
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700240 * Convert a IPv4 netmask integer to a prefix length
241 * @param netmask as an integer in network byte order
242 * @return the network prefix length
243 */
244 public static int netmaskIntToPrefixLength(int netmask) {
245 return Integer.bitCount(netmask);
246 }
247
248 /**
Lorenzo Colitti475085b2015-03-10 01:32:40 +0900249 * Convert an IPv4 netmask to a prefix length, checking that the netmask is contiguous.
250 * @param netmask as a {@code Inet4Address}.
251 * @return the network prefix length
252 * @throws IllegalArgumentException the specified netmask was not contiguous.
253 * @hide
254 */
255 public static int netmaskToPrefixLength(Inet4Address netmask) {
256 // inetAddressToInt returns an int in *network* byte order.
257 int i = Integer.reverseBytes(inetAddressToInt(netmask));
258 int prefixLength = Integer.bitCount(i);
259 int trailingZeros = Integer.numberOfTrailingZeros(i);
260 if (trailingZeros != 32 - prefixLength) {
261 throw new IllegalArgumentException("Non-contiguous netmask: " + Integer.toHexString(i));
262 }
263 return prefixLength;
264 }
265
266
267 /**
Robert Greenwalt0216e612011-01-14 16:29:58 -0800268 * Create an InetAddress from a string where the string must be a standard
269 * representation of a V4 or V6 address. Avoids doing a DNS lookup on failure
270 * but it will throw an IllegalArgumentException in that case.
271 * @param addrString
272 * @return the InetAddress
273 * @hide
274 */
275 public static InetAddress numericToInetAddress(String addrString)
276 throws IllegalArgumentException {
Elliott Hughesf5bbb572011-02-15 17:11:29 -0800277 return InetAddress.parseNumericAddress(addrString);
Robert Greenwalt0216e612011-01-14 16:29:58 -0800278 }
279
280 /**
Lorenzo Colitti0a82e802014-07-31 00:48:01 +0900281 * Writes an InetAddress to a parcel. The address may be null. This is likely faster than
282 * calling writeSerializable.
283 */
284 protected static void parcelInetAddress(Parcel parcel, InetAddress address, int flags) {
285 byte[] addressArray = (address != null) ? address.getAddress() : null;
286 parcel.writeByteArray(addressArray);
287 }
288
289 /**
290 * Reads an InetAddress from a parcel. Returns null if the address that was written was null
291 * or if the data is invalid.
292 */
293 protected static InetAddress unparcelInetAddress(Parcel in) {
294 byte[] addressArray = in.createByteArray();
295 if (addressArray == null) {
296 return null;
297 }
298 try {
299 return InetAddress.getByAddress(addressArray);
300 } catch (UnknownHostException e) {
301 return null;
302 }
303 }
304
305
306 /**
Lorenzo Colitti8c6c2c32014-06-12 13:41:17 +0900307 * Masks a raw IP address byte array with the specified prefix length.
Robert Greenwaltf43396c2011-05-06 17:10:53 -0700308 */
Lorenzo Colitti8c6c2c32014-06-12 13:41:17 +0900309 public static void maskRawAddress(byte[] array, int prefixLength) {
Robert Greenwaltf43396c2011-05-06 17:10:53 -0700310 if (prefixLength < 0 || prefixLength > array.length * 8) {
Lorenzo Colitti8c6c2c32014-06-12 13:41:17 +0900311 throw new RuntimeException("IP address with " + array.length +
312 " bytes has invalid prefix length " + prefixLength);
Robert Greenwaltf43396c2011-05-06 17:10:53 -0700313 }
314
315 int offset = prefixLength / 8;
Lorenzo Colitti8c6c2c32014-06-12 13:41:17 +0900316 int remainder = prefixLength % 8;
317 byte mask = (byte)(0xFF << (8 - remainder));
Robert Greenwaltf43396c2011-05-06 17:10:53 -0700318
319 if (offset < array.length) array[offset] = (byte)(array[offset] & mask);
320
321 offset++;
322
323 for (; offset < array.length; offset++) {
324 array[offset] = 0;
325 }
Lorenzo Colitti8c6c2c32014-06-12 13:41:17 +0900326 }
327
328 /**
329 * Get InetAddress masked with prefixLength. Will never return null.
330 * @param address the IP address to mask with
331 * @param prefixLength the prefixLength used to mask the IP
332 */
333 public static InetAddress getNetworkPart(InetAddress address, int prefixLength) {
334 byte[] array = address.getAddress();
335 maskRawAddress(array, prefixLength);
Robert Greenwaltf43396c2011-05-06 17:10:53 -0700336
337 InetAddress netPart = null;
338 try {
339 netPart = InetAddress.getByAddress(array);
340 } catch (UnknownHostException e) {
341 throw new RuntimeException("getNetworkPart error - " + e.toString());
342 }
343 return netPart;
344 }
345
346 /**
Lorenzo Colitti475085b2015-03-10 01:32:40 +0900347 * Returns the implicit netmask of an IPv4 address, as was the custom before 1993.
348 */
349 public static int getImplicitNetmask(Inet4Address address) {
350 int firstByte = address.getAddress()[0] & 0xff; // Convert to an unsigned value.
351 if (firstByte < 128) {
352 return 8;
353 } else if (firstByte < 192) {
354 return 16;
355 } else if (firstByte < 224) {
356 return 24;
357 } else {
358 return 32; // Will likely not end well for other reasons.
359 }
360 }
361
362 /**
Lorenzo Colitti8c6c2c32014-06-12 13:41:17 +0900363 * Utility method to parse strings such as "192.0.2.5/24" or "2001:db8::cafe:d00d/64".
364 * @hide
365 */
366 public static Pair<InetAddress, Integer> parseIpAndMask(String ipAndMaskString) {
367 InetAddress address = null;
368 int prefixLength = -1;
369 try {
370 String[] pieces = ipAndMaskString.split("/", 2);
371 prefixLength = Integer.parseInt(pieces[1]);
372 address = InetAddress.parseNumericAddress(pieces[0]);
373 } catch (NullPointerException e) { // Null string.
374 } catch (ArrayIndexOutOfBoundsException e) { // No prefix length.
375 } catch (NumberFormatException e) { // Non-numeric prefix.
376 } catch (IllegalArgumentException e) { // Invalid IP address.
377 }
378
379 if (address == null || prefixLength == -1) {
380 throw new IllegalArgumentException("Invalid IP address and mask " + ipAndMaskString);
381 }
382
383 return new Pair<InetAddress, Integer>(address, prefixLength);
384 }
385
386 /**
Robert Greenwaltf43396c2011-05-06 17:10:53 -0700387 * Check if IP address type is consistent between two InetAddress.
388 * @return true if both are the same type. False otherwise.
389 */
390 public static boolean addressTypeMatches(InetAddress left, InetAddress right) {
391 return (((left instanceof Inet4Address) && (right instanceof Inet4Address)) ||
392 ((left instanceof Inet6Address) && (right instanceof Inet6Address)));
393 }
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700394
395 /**
396 * Convert a 32 char hex string into a Inet6Address.
397 * throws a runtime exception if the string isn't 32 chars, isn't hex or can't be
398 * made into an Inet6Address
399 * @param addrHexString a 32 character hex string representing an IPv6 addr
400 * @return addr an InetAddress representation for the string
401 */
402 public static InetAddress hexToInet6Address(String addrHexString)
403 throws IllegalArgumentException {
404 try {
Jeff Sharkeyfea17de2013-06-11 14:13:09 -0700405 return numericToInetAddress(String.format(Locale.US, "%s:%s:%s:%s:%s:%s:%s:%s",
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700406 addrHexString.substring(0,4), addrHexString.substring(4,8),
407 addrHexString.substring(8,12), addrHexString.substring(12,16),
408 addrHexString.substring(16,20), addrHexString.substring(20,24),
409 addrHexString.substring(24,28), addrHexString.substring(28,32)));
410 } catch (Exception e) {
411 Log.e("NetworkUtils", "error in hexToInet6Address(" + addrHexString + "): " + e);
412 throw new IllegalArgumentException(e);
413 }
414 }
Robert Greenwalta10b7fd2011-07-25 16:06:25 -0700415
416 /**
417 * Create a string array of host addresses from a collection of InetAddresses
418 * @param addrs a Collection of InetAddresses
419 * @return an array of Strings containing their host addresses
420 */
421 public static String[] makeStrings(Collection<InetAddress> addrs) {
422 String[] result = new String[addrs.size()];
423 int i = 0;
424 for (InetAddress addr : addrs) {
425 result[i++] = addr.getHostAddress();
426 }
427 return result;
428 }
Robert Greenwaltd4420ab2011-12-07 09:58:48 -0800429
430 /**
431 * Trim leading zeros from IPv4 address strings
432 * Our base libraries will interpret that as octel..
433 * Must leave non v4 addresses and host names alone.
434 * For example, 192.168.000.010 -> 192.168.0.10
435 * TODO - fix base libraries and remove this function
436 * @param addr a string representing an ip addr
437 * @return a string propertly trimmed
438 */
439 public static String trimV4AddrZeros(String addr) {
Robert Greenwalt0faacf02011-12-07 16:43:59 -0800440 if (addr == null) return null;
Robert Greenwaltd4420ab2011-12-07 09:58:48 -0800441 String[] octets = addr.split("\\.");
442 if (octets.length != 4) return addr;
443 StringBuilder builder = new StringBuilder(16);
444 String result = null;
445 for (int i = 0; i < 4; i++) {
446 try {
Robert Greenwalt3957b5f2011-12-07 13:10:59 -0800447 if (octets[i].length() > 3) return addr;
Robert Greenwaltd4420ab2011-12-07 09:58:48 -0800448 builder.append(Integer.parseInt(octets[i]));
449 } catch (NumberFormatException e) {
450 return addr;
451 }
452 if (i < 3) builder.append('.');
453 }
454 result = builder.toString();
455 return result;
456 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800457}