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 
17 package android.net;
18 
19 import static android.system.OsConstants.AF_INET;
20 import static android.system.OsConstants.AF_INET6;
21 
22 import android.annotation.NonNull;
23 import android.compat.annotation.UnsupportedAppUsage;
24 import android.net.shared.Inet4AddressUtils;
25 import android.os.Build;
26 import android.system.ErrnoException;
27 import android.system.Os;
28 import android.util.Log;
29 import android.util.Pair;
30 
31 import java.io.FileDescriptor;
32 import java.math.BigInteger;
33 import java.net.Inet4Address;
34 import java.net.InetAddress;
35 import java.net.SocketException;
36 import java.net.UnknownHostException;
37 import java.util.Collection;
38 import java.util.Locale;
39 import java.util.TreeSet;
40 
41 /**
42  * Native methods for managing network interfaces.
43  *
44  * {@hide}
45  */
46 public class NetworkUtils {
47 
48     private static final String TAG = "NetworkUtils";
49 
50     /**
51      * Attaches a socket filter that drops all of incoming packets.
52      * @param fd the socket's {@link FileDescriptor}.
53      */
attachDropAllBPFFilter(FileDescriptor fd)54     public static native void attachDropAllBPFFilter(FileDescriptor fd) throws SocketException;
55 
56     /**
57      * Detaches a socket filter.
58      * @param fd the socket's {@link FileDescriptor}.
59      */
detachBPFFilter(FileDescriptor fd)60     public static native void detachBPFFilter(FileDescriptor fd) throws SocketException;
61 
62     /**
63      * Binds the current process to the network designated by {@code netId}.  All sockets created
64      * in the future (and not explicitly bound via a bound {@link SocketFactory} (see
65      * {@link Network#getSocketFactory}) will be bound to this network.  Note that if this
66      * {@code Network} ever disconnects all sockets created in this way will cease to work.  This
67      * is by design so an application doesn't accidentally use sockets it thinks are still bound to
68      * a particular {@code Network}.  Passing NETID_UNSET clears the binding.
69      */
bindProcessToNetwork(int netId)70     public native static boolean bindProcessToNetwork(int netId);
71 
72     /**
73      * Return the netId last passed to {@link #bindProcessToNetwork}, or NETID_UNSET if
74      * {@link #unbindProcessToNetwork} has been called since {@link #bindProcessToNetwork}.
75      */
getBoundNetworkForProcess()76     public native static int getBoundNetworkForProcess();
77 
78     /**
79      * Binds host resolutions performed by this process to the network designated by {@code netId}.
80      * {@link #bindProcessToNetwork} takes precedence over this setting.  Passing NETID_UNSET clears
81      * the binding.
82      *
83      * @deprecated This is strictly for legacy usage to support startUsingNetworkFeature().
84      */
85     @Deprecated
bindProcessToNetworkForHostResolution(int netId)86     public native static boolean bindProcessToNetworkForHostResolution(int netId);
87 
88     /**
89      * Explicitly binds {@code socketfd} to the network designated by {@code netId}.  This
90      * overrides any binding via {@link #bindProcessToNetwork}.
91      * @return 0 on success or negative errno on failure.
92      */
bindSocketToNetwork(int socketfd, int netId)93     public native static int bindSocketToNetwork(int socketfd, int netId);
94 
95     /**
96      * Protect {@code fd} from VPN connections.  After protecting, data sent through
97      * this socket will go directly to the underlying network, so its traffic will not be
98      * forwarded through the VPN.
99      */
100     @UnsupportedAppUsage
protectFromVpn(FileDescriptor fd)101     public static boolean protectFromVpn(FileDescriptor fd) {
102         return protectFromVpn(fd.getInt$());
103     }
104 
105     /**
106      * Protect {@code socketfd} from VPN connections.  After protecting, data sent through
107      * this socket will go directly to the underlying network, so its traffic will not be
108      * forwarded through the VPN.
109      */
protectFromVpn(int socketfd)110     public native static boolean protectFromVpn(int socketfd);
111 
112     /**
113      * Determine if {@code uid} can access network designated by {@code netId}.
114      * @return {@code true} if {@code uid} can access network, {@code false} otherwise.
115      */
queryUserAccess(int uid, int netId)116     public native static boolean queryUserAccess(int uid, int netId);
117 
118     /**
119      * DNS resolver series jni method.
120      * Issue the query {@code msg} on the network designated by {@code netId}.
121      * {@code flags} is an additional config to control actual querying behavior.
122      * @return a file descriptor to watch for read events
123      */
resNetworkSend( int netId, byte[] msg, int msglen, int flags)124     public static native FileDescriptor resNetworkSend(
125             int netId, byte[] msg, int msglen, int flags) throws ErrnoException;
126 
127     /**
128      * DNS resolver series jni method.
129      * Look up the {@code nsClass} {@code nsType} Resource Record (RR) associated
130      * with Domain Name {@code dname} on the network designated by {@code netId}.
131      * {@code flags} is an additional config to control actual querying behavior.
132      * @return a file descriptor to watch for read events
133      */
resNetworkQuery( int netId, String dname, int nsClass, int nsType, int flags)134     public static native FileDescriptor resNetworkQuery(
135             int netId, String dname, int nsClass, int nsType, int flags) throws ErrnoException;
136 
137     /**
138      * DNS resolver series jni method.
139      * Read a result for the query associated with the {@code fd}.
140      * @return DnsResponse containing blob answer and rcode
141      */
resNetworkResult(FileDescriptor fd)142     public static native DnsResolver.DnsResponse resNetworkResult(FileDescriptor fd)
143             throws ErrnoException;
144 
145     /**
146      * DNS resolver series jni method.
147      * Attempts to cancel the in-progress query associated with the {@code fd}.
148      */
resNetworkCancel(FileDescriptor fd)149     public static native void resNetworkCancel(FileDescriptor fd);
150 
151     /**
152      * DNS resolver series jni method.
153      * Attempts to get network which resolver will use if no network is explicitly selected.
154      */
getDnsNetwork()155     public static native Network getDnsNetwork() throws ErrnoException;
156 
157     /**
158      * Allow/Disallow creating AF_INET/AF_INET6 sockets and DNS lookups for current process.
159      *
160      * @param allowNetworking whether to allow or disallow creating AF_INET/AF_INET6 sockets
161      *                        and DNS lookups.
162      */
setAllowNetworkingForProcess(boolean allowNetworking)163     public static native void setAllowNetworkingForProcess(boolean allowNetworking);
164 
165     /**
166      * Get the tcp repair window associated with the {@code fd}.
167      *
168      * @param fd the tcp socket's {@link FileDescriptor}.
169      * @return a {@link TcpRepairWindow} object indicates tcp window size.
170      */
getTcpRepairWindow(FileDescriptor fd)171     public static native TcpRepairWindow getTcpRepairWindow(FileDescriptor fd)
172             throws ErrnoException;
173 
174     /**
175      * @see Inet4AddressUtils#intToInet4AddressHTL(int)
176      * @deprecated Use either {@link Inet4AddressUtils#intToInet4AddressHTH(int)}
177      *             or {@link Inet4AddressUtils#intToInet4AddressHTL(int)}
178      */
179     @Deprecated
180     @UnsupportedAppUsage
intToInetAddress(int hostAddress)181     public static InetAddress intToInetAddress(int hostAddress) {
182         return Inet4AddressUtils.intToInet4AddressHTL(hostAddress);
183     }
184 
185     /**
186      * @see Inet4AddressUtils#inet4AddressToIntHTL(Inet4Address)
187      * @deprecated Use either {@link Inet4AddressUtils#inet4AddressToIntHTH(Inet4Address)}
188      *             or {@link Inet4AddressUtils#inet4AddressToIntHTL(Inet4Address)}
189      */
190     @Deprecated
inetAddressToInt(Inet4Address inetAddr)191     public static int inetAddressToInt(Inet4Address inetAddr)
192             throws IllegalArgumentException {
193         return Inet4AddressUtils.inet4AddressToIntHTL(inetAddr);
194     }
195 
196     /**
197      * @see Inet4AddressUtils#prefixLengthToV4NetmaskIntHTL(int)
198      * @deprecated Use either {@link Inet4AddressUtils#prefixLengthToV4NetmaskIntHTH(int)}
199      *             or {@link Inet4AddressUtils#prefixLengthToV4NetmaskIntHTL(int)}
200      */
201     @Deprecated
202     @UnsupportedAppUsage
prefixLengthToNetmaskInt(int prefixLength)203     public static int prefixLengthToNetmaskInt(int prefixLength)
204             throws IllegalArgumentException {
205         return Inet4AddressUtils.prefixLengthToV4NetmaskIntHTL(prefixLength);
206     }
207 
208     /**
209      * Convert a IPv4 netmask integer to a prefix length
210      * @param netmask as an integer (0xff000000 for a /8 subnet)
211      * @return the network prefix length
212      */
netmaskIntToPrefixLength(int netmask)213     public static int netmaskIntToPrefixLength(int netmask) {
214         return Integer.bitCount(netmask);
215     }
216 
217     /**
218      * Convert an IPv4 netmask to a prefix length, checking that the netmask is contiguous.
219      * @param netmask as a {@code Inet4Address}.
220      * @return the network prefix length
221      * @throws IllegalArgumentException the specified netmask was not contiguous.
222      * @hide
223      * @deprecated use {@link Inet4AddressUtils#netmaskToPrefixLength(Inet4Address)}
224      */
225     @UnsupportedAppUsage
226     @Deprecated
netmaskToPrefixLength(Inet4Address netmask)227     public static int netmaskToPrefixLength(Inet4Address netmask) {
228         // This is only here because some apps seem to be using it (@UnsupportedAppUsage).
229         return Inet4AddressUtils.netmaskToPrefixLength(netmask);
230     }
231 
232 
233     /**
234      * Create an InetAddress from a string where the string must be a standard
235      * representation of a V4 or V6 address.  Avoids doing a DNS lookup on failure
236      * but it will throw an IllegalArgumentException in that case.
237      * @param addrString
238      * @return the InetAddress
239      * @hide
240      * @deprecated Use {@link InetAddresses#parseNumericAddress(String)}, if possible.
241      */
242     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
243     @Deprecated
numericToInetAddress(String addrString)244     public static InetAddress numericToInetAddress(String addrString)
245             throws IllegalArgumentException {
246         return InetAddress.parseNumericAddress(addrString);
247     }
248 
249     /**
250      *  Masks a raw IP address byte array with the specified prefix length.
251      */
maskRawAddress(byte[] array, int prefixLength)252     public static void maskRawAddress(byte[] array, int prefixLength) {
253         if (prefixLength < 0 || prefixLength > array.length * 8) {
254             throw new RuntimeException("IP address with " + array.length +
255                     " bytes has invalid prefix length " + prefixLength);
256         }
257 
258         int offset = prefixLength / 8;
259         int remainder = prefixLength % 8;
260         byte mask = (byte)(0xFF << (8 - remainder));
261 
262         if (offset < array.length) array[offset] = (byte)(array[offset] & mask);
263 
264         offset++;
265 
266         for (; offset < array.length; offset++) {
267             array[offset] = 0;
268         }
269     }
270 
271     /**
272      * Get InetAddress masked with prefixLength.  Will never return null.
273      * @param address the IP address to mask with
274      * @param prefixLength the prefixLength used to mask the IP
275      */
getNetworkPart(InetAddress address, int prefixLength)276     public static InetAddress getNetworkPart(InetAddress address, int prefixLength) {
277         byte[] array = address.getAddress();
278         maskRawAddress(array, prefixLength);
279 
280         InetAddress netPart = null;
281         try {
282             netPart = InetAddress.getByAddress(array);
283         } catch (UnknownHostException e) {
284             throw new RuntimeException("getNetworkPart error - " + e.toString());
285         }
286         return netPart;
287     }
288 
289     /**
290      * Returns the implicit netmask of an IPv4 address, as was the custom before 1993.
291      */
292     @UnsupportedAppUsage
getImplicitNetmask(Inet4Address address)293     public static int getImplicitNetmask(Inet4Address address) {
294         // Only here because it seems to be used by apps
295         return Inet4AddressUtils.getImplicitNetmask(address);
296     }
297 
298     /**
299      * Utility method to parse strings such as "192.0.2.5/24" or "2001:db8::cafe:d00d/64".
300      * @hide
301      */
parseIpAndMask(String ipAndMaskString)302     public static Pair<InetAddress, Integer> parseIpAndMask(String ipAndMaskString) {
303         InetAddress address = null;
304         int prefixLength = -1;
305         try {
306             String[] pieces = ipAndMaskString.split("/", 2);
307             prefixLength = Integer.parseInt(pieces[1]);
308             address = InetAddress.parseNumericAddress(pieces[0]);
309         } catch (NullPointerException e) {            // Null string.
310         } catch (ArrayIndexOutOfBoundsException e) {  // No prefix length.
311         } catch (NumberFormatException e) {           // Non-numeric prefix.
312         } catch (IllegalArgumentException e) {        // Invalid IP address.
313         }
314 
315         if (address == null || prefixLength == -1) {
316             throw new IllegalArgumentException("Invalid IP address and mask " + ipAndMaskString);
317         }
318 
319         return new Pair<InetAddress, Integer>(address, prefixLength);
320     }
321 
322     /**
323      * Convert a 32 char hex string into a Inet6Address.
324      * throws a runtime exception if the string isn't 32 chars, isn't hex or can't be
325      * made into an Inet6Address
326      * @param addrHexString a 32 character hex string representing an IPv6 addr
327      * @return addr an InetAddress representation for the string
328      */
hexToInet6Address(String addrHexString)329     public static InetAddress hexToInet6Address(String addrHexString)
330             throws IllegalArgumentException {
331         try {
332             return numericToInetAddress(String.format(Locale.US, "%s:%s:%s:%s:%s:%s:%s:%s",
333                     addrHexString.substring(0,4),   addrHexString.substring(4,8),
334                     addrHexString.substring(8,12),  addrHexString.substring(12,16),
335                     addrHexString.substring(16,20), addrHexString.substring(20,24),
336                     addrHexString.substring(24,28), addrHexString.substring(28,32)));
337         } catch (Exception e) {
338             Log.e("NetworkUtils", "error in hexToInet6Address(" + addrHexString + "): " + e);
339             throw new IllegalArgumentException(e);
340         }
341     }
342 
343     /**
344      * Create a string array of host addresses from a collection of InetAddresses
345      * @param addrs a Collection of InetAddresses
346      * @return an array of Strings containing their host addresses
347      */
makeStrings(Collection<InetAddress> addrs)348     public static String[] makeStrings(Collection<InetAddress> addrs) {
349         String[] result = new String[addrs.size()];
350         int i = 0;
351         for (InetAddress addr : addrs) {
352             result[i++] = addr.getHostAddress();
353         }
354         return result;
355     }
356 
357     /**
358      * Trim leading zeros from IPv4 address strings
359      * Our base libraries will interpret that as octel..
360      * Must leave non v4 addresses and host names alone.
361      * For example, 192.168.000.010 -> 192.168.0.10
362      * TODO - fix base libraries and remove this function
363      * @param addr a string representing an ip addr
364      * @return a string propertly trimmed
365      */
366     @UnsupportedAppUsage
trimV4AddrZeros(String addr)367     public static String trimV4AddrZeros(String addr) {
368         if (addr == null) return null;
369         String[] octets = addr.split("\\.");
370         if (octets.length != 4) return addr;
371         StringBuilder builder = new StringBuilder(16);
372         String result = null;
373         for (int i = 0; i < 4; i++) {
374             try {
375                 if (octets[i].length() > 3) return addr;
376                 builder.append(Integer.parseInt(octets[i]));
377             } catch (NumberFormatException e) {
378                 return addr;
379             }
380             if (i < 3) builder.append('.');
381         }
382         result = builder.toString();
383         return result;
384     }
385 
386     /**
387      * Returns a prefix set without overlaps.
388      *
389      * This expects the src set to be sorted from shorter to longer. Results are undefined
390      * failing this condition. The returned prefix set is sorted in the same order as the
391      * passed set, with the same comparator.
392      */
deduplicatePrefixSet(final TreeSet<IpPrefix> src)393     private static TreeSet<IpPrefix> deduplicatePrefixSet(final TreeSet<IpPrefix> src) {
394         final TreeSet<IpPrefix> dst = new TreeSet<>(src.comparator());
395         // Prefixes match addresses that share their upper part up to their length, therefore
396         // the only kind of possible overlap in two prefixes is strict inclusion of the longer
397         // (more restrictive) in the shorter (including equivalence if they have the same
398         // length).
399         // Because prefixes in the src set are sorted from shorter to longer, deduplicating
400         // is done by simply iterating in order, and not adding any longer prefix that is
401         // already covered by a shorter one.
402         newPrefixes:
403         for (IpPrefix newPrefix : src) {
404             for (IpPrefix existingPrefix : dst) {
405                 if (existingPrefix.containsPrefix(newPrefix)) {
406                     continue newPrefixes;
407                 }
408             }
409             dst.add(newPrefix);
410         }
411         return dst;
412     }
413 
414     /**
415      * Returns how many IPv4 addresses match any of the prefixes in the passed ordered set.
416      *
417      * Obviously this returns an integral value between 0 and 2**32.
418      * The behavior is undefined if any of the prefixes is not an IPv4 prefix or if the
419      * set is not ordered smallest prefix to longer prefix.
420      *
421      * @param prefixes the set of prefixes, ordered by length
422      */
routedIPv4AddressCount(final TreeSet<IpPrefix> prefixes)423     public static long routedIPv4AddressCount(final TreeSet<IpPrefix> prefixes) {
424         long routedIPCount = 0;
425         for (final IpPrefix prefix : deduplicatePrefixSet(prefixes)) {
426             if (!prefix.isIPv4()) {
427                 Log.wtf(TAG, "Non-IPv4 prefix in routedIPv4AddressCount");
428             }
429             int rank = 32 - prefix.getPrefixLength();
430             routedIPCount += 1L << rank;
431         }
432         return routedIPCount;
433     }
434 
435     /**
436      * Returns how many IPv6 addresses match any of the prefixes in the passed ordered set.
437      *
438      * This returns a BigInteger between 0 and 2**128.
439      * The behavior is undefined if any of the prefixes is not an IPv6 prefix or if the
440      * set is not ordered smallest prefix to longer prefix.
441      */
routedIPv6AddressCount(final TreeSet<IpPrefix> prefixes)442     public static BigInteger routedIPv6AddressCount(final TreeSet<IpPrefix> prefixes) {
443         BigInteger routedIPCount = BigInteger.ZERO;
444         for (final IpPrefix prefix : deduplicatePrefixSet(prefixes)) {
445             if (!prefix.isIPv6()) {
446                 Log.wtf(TAG, "Non-IPv6 prefix in routedIPv6AddressCount");
447             }
448             int rank = 128 - prefix.getPrefixLength();
449             routedIPCount = routedIPCount.add(BigInteger.ONE.shiftLeft(rank));
450         }
451         return routedIPCount;
452     }
453 
454     private static final int[] ADDRESS_FAMILIES = new int[] {AF_INET, AF_INET6};
455 
456     /**
457      * Returns true if the hostname is weakly validated.
458      * @param hostname Name of host to validate.
459      * @return True if it's a valid-ish hostname.
460      *
461      * @hide
462      */
isWeaklyValidatedHostname(@onNull String hostname)463     public static boolean isWeaklyValidatedHostname(@NonNull String hostname) {
464         // TODO(b/34953048): Use a validation method that permits more accurate,
465         // but still inexpensive, checking of likely valid DNS hostnames.
466         final String weakHostnameRegex = "^[a-zA-Z0-9_.-]+$";
467         if (!hostname.matches(weakHostnameRegex)) {
468             return false;
469         }
470 
471         for (int address_family : ADDRESS_FAMILIES) {
472             if (Os.inet_pton(address_family, hostname) != null) {
473                 return false;
474             }
475         }
476 
477         return true;
478     }
479 
480     /**
481      * Safely multiple a value by a rational.
482      * <p>
483      * Internally it uses integer-based math whenever possible, but switches
484      * over to double-based math if values would overflow.
485      * @hide
486      */
multiplySafeByRational(long value, long num, long den)487     public static long multiplySafeByRational(long value, long num, long den) {
488         if (den == 0) {
489             throw new ArithmeticException("Invalid Denominator");
490         }
491         long x = value;
492         long y = num;
493 
494         // Logic shamelessly borrowed from Math.multiplyExact()
495         long r = x * y;
496         long ax = Math.abs(x);
497         long ay = Math.abs(y);
498         if (((ax | ay) >>> 31 != 0)) {
499             // Some bits greater than 2^31 that might cause overflow
500             // Check the result using the divide operator
501             // and check for the special case of Long.MIN_VALUE * -1
502             if (((y != 0) && (r / y != x)) ||
503                     (x == Long.MIN_VALUE && y == -1)) {
504                 // Use double math to avoid overflowing
505                 return (long) (((double) num / den) * value);
506             }
507         }
508         return r / den;
509     }
510 }
511