• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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.util;
18 
19 import android.content.Context;
20 import android.net.MacAddress;
21 
22 import androidx.annotation.NonNull;
23 
24 import com.android.net.module.util.DeviceConfigUtils;
25 
26 import java.io.FileDescriptor;
27 import java.io.IOException;
28 import java.net.Inet4Address;
29 import java.net.Inet6Address;
30 import java.net.SocketException;
31 
32 /**
33  * Collection of utilities for the network stack.
34  */
35 public class NetworkStackUtils {
36     private static final String TAG = "NetworkStackUtils";
37 
38     /**
39      * A list of captive portal detection specifications used in addition to the fallback URLs.
40      * Each spec has the format url@@/@@statusCodeRegex@@/@@contentRegex. Specs are separated
41      * by "@@,@@".
42      */
43     public static final String CAPTIVE_PORTAL_FALLBACK_PROBE_SPECS =
44             "captive_portal_fallback_probe_specs";
45 
46     /**
47      * A comma separated list of URLs used for captive portal detection in addition to the
48      * fallback HTTP url associated with the CAPTIVE_PORTAL_FALLBACK_URL settings.
49      */
50     public static final String CAPTIVE_PORTAL_OTHER_FALLBACK_URLS =
51             "captive_portal_other_fallback_urls";
52 
53     /**
54      * A comma separated list of URLs used for captive portal detection in addition to the HTTP url
55      * associated with the CAPTIVE_PORTAL_HTTP_URL settings.
56      */
57     public static final String CAPTIVE_PORTAL_OTHER_HTTP_URLS = "captive_portal_other_http_urls";
58 
59     /**
60      * A comma separated list of URLs used for network validation. in addition to the HTTPS url
61      * associated with the CAPTIVE_PORTAL_HTTPS_URL settings.
62      */
63     public static final String CAPTIVE_PORTAL_OTHER_HTTPS_URLS = "captive_portal_other_https_urls";
64 
65     /**
66      * Which User-Agent string to use in the header of the captive portal detection probes.
67      * The User-Agent field is unset when this setting has no value (HttpUrlConnection default).
68      */
69     public static final String CAPTIVE_PORTAL_USER_AGENT = "captive_portal_user_agent";
70 
71     /**
72      * Whether to use HTTPS for network validation. This is enabled by default and the setting
73      * needs to be set to 0 to disable it. This setting is a misnomer because captive portals
74      * don't actually use HTTPS, but it's consistent with the other settings.
75      */
76     public static final String CAPTIVE_PORTAL_USE_HTTPS = "captive_portal_use_https";
77 
78     /**
79      * The URL used for HTTPS captive portal detection upon a new connection.
80      * A 204 response code from the server is used for validation.
81      */
82     public static final String CAPTIVE_PORTAL_HTTPS_URL = "captive_portal_https_url";
83 
84     /**
85      * The URL used for HTTP captive portal detection upon a new connection.
86      * A 204 response code from the server is used for validation.
87      */
88     public static final String CAPTIVE_PORTAL_HTTP_URL = "captive_portal_http_url";
89 
90     /**
91      * A test URL used to override configuration settings and overlays for the network validation
92      * HTTPS URL, when set in {@link android.provider.DeviceConfig} configuration.
93      *
94      * <p>This URL will be ignored if the host is not "localhost" (it can only be used to test with
95      * a local test server), and must not be set in production scenarios (as enforced by CTS tests).
96      *
97      * <p>{@link #TEST_URL_EXPIRATION_TIME} must also be set to use this setting.
98      */
99     public static final String TEST_CAPTIVE_PORTAL_HTTPS_URL = "test_captive_portal_https_url";
100 
101     /**
102      * A test URL used to override configuration settings and overlays for the network validation
103      * HTTP URL, when set in {@link android.provider.DeviceConfig} configuration.
104      *
105      * <p>This URL will be ignored if the host is not "localhost" (it can only be used to test with
106      * a local test server), and must not be set in production scenarios (as enforced by CTS tests).
107      *
108      * <p>{@link #TEST_URL_EXPIRATION_TIME} must also be set to use this setting.
109      */
110     public static final String TEST_CAPTIVE_PORTAL_HTTP_URL = "test_captive_portal_http_url";
111 
112     /**
113      * Expiration time of the test URL, in ms, relative to {@link System#currentTimeMillis()}.
114      *
115      * <p>After this expiration time, test URLs will be ignored. They will also be ignored if
116      * the expiration time is more than 10 minutes in the future, to avoid misconfiguration
117      * following test runs.
118      */
119     public static final String TEST_URL_EXPIRATION_TIME = "test_url_expiration_time";
120 
121     /**
122      * The URL used for fallback HTTP captive portal detection when previous HTTP
123      * and HTTPS captive portal detection attemps did not return a conclusive answer.
124      */
125     public static final String CAPTIVE_PORTAL_FALLBACK_URL = "captive_portal_fallback_url";
126 
127     /**
128      * What to do when connecting a network that presents a captive portal.
129      * Must be one of the CAPTIVE_PORTAL_MODE_* constants above.
130      *
131      * The default for this setting is CAPTIVE_PORTAL_MODE_PROMPT.
132      */
133     public static final String CAPTIVE_PORTAL_MODE = "captive_portal_mode";
134 
135     /**
136      * Don't attempt to detect captive portals.
137      */
138     public static final int CAPTIVE_PORTAL_MODE_IGNORE = 0;
139 
140     /**
141      * When detecting a captive portal, display a notification that
142      * prompts the user to sign in.
143      */
144     public static final int CAPTIVE_PORTAL_MODE_PROMPT = 1;
145 
146     /**
147      * When detecting a captive portal, immediately disconnect from the
148      * network and do not reconnect to that network in the future.
149      */
150     public static final int CAPTIVE_PORTAL_MODE_AVOID = 2;
151 
152     /**
153      * DNS probe timeout for network validation. Enough for 3 DNS queries 5 seconds apart.
154      */
155     public static final int DEFAULT_CAPTIVE_PORTAL_DNS_PROBE_TIMEOUT = 12500;
156 
157     /**
158      * List of fallback probe specs to use for detecting captive portals. This is an alternative to
159      * fallback URLs that provides more flexibility on detection rules. Empty, so unused by default.
160      */
161     public static final String[] DEFAULT_CAPTIVE_PORTAL_FALLBACK_PROBE_SPECS =
162             new String[] {};
163 
164     /**
165      * The default list of HTTP URLs to use for detecting captive portals.
166      */
167     public static final String[] DEFAULT_CAPTIVE_PORTAL_HTTP_URLS =
168             new String [] {"http://connectivitycheck.gstatic.com/generate_204"};
169 
170     /**
171      * The default list of HTTPS URLs for network validation, to use for confirming internet
172      * connectivity.
173      */
174     public static final String[] DEFAULT_CAPTIVE_PORTAL_HTTPS_URLS =
175             new String [] {"https://www.google.com/generate_204"};
176 
177     /**
178      * @deprecated Considering boolean experiment flag is likely to cause misconfiguration
179      *             particularly when NetworkStack module rolls back to previous version. It's
180      *             much safer to determine whether or not to enable one specific experimental
181      *             feature by comparing flag version with module version.
182      */
183     @Deprecated
184     public static final String DHCP_INIT_REBOOT_ENABLED = "dhcp_init_reboot_enabled";
185 
186     /**
187      * @deprecated See above explanation.
188      */
189     @Deprecated
190     public static final String DHCP_RAPID_COMMIT_ENABLED = "dhcp_rapid_commit_enabled";
191 
192     /**
193      * Minimum module version at which to enable the DHCP INIT-REBOOT state.
194      */
195     public static final String DHCP_INIT_REBOOT_VERSION = "dhcp_init_reboot_version";
196 
197     /**
198      * Minimum module version at which to enable the DHCP Rapid Commit option.
199      */
200     public static final String DHCP_RAPID_COMMIT_VERSION = "dhcp_rapid_commit_version";
201 
202     /**
203      * Minimum module version at which to enable the IP address conflict detection feature.
204      */
205     public static final String DHCP_IP_CONFLICT_DETECT_VERSION = "dhcp_ip_conflict_detect_version";
206 
207     /**
208      * Minimum module version at which to enable the IPv6-Only preferred option.
209      */
210     public static final String DHCP_IPV6_ONLY_PREFERRED_VERSION =
211             "dhcp_ipv6_only_preferred_version";
212 
213     /**
214      * Minimum module version at which to enable dismissal CaptivePortalLogin app in validated
215      * network feature. CaptivePortalLogin app will also use validation facilities in
216      * {@link NetworkMonitor} to perform portal validation if feature is enabled.
217      */
218     public static final String DISMISS_PORTAL_IN_VALIDATED_NETWORK =
219             "dismiss_portal_in_validated_network";
220 
221     /**
222      * Experiment flag to enable considering DNS probes returning private IP addresses as failed
223      * when attempting to detect captive portals.
224      *
225      * This flag is enabled if !=0 and less than the module APK version.
226      */
227     public static final String DNS_PROBE_PRIVATE_IP_NO_INTERNET_VERSION =
228             "dns_probe_private_ip_no_internet";
229 
230     /**
231      * Experiment flag to enable validation metrics sent by NetworkMonitor.
232      *
233      * Metrics are sent by default. They can be disabled by setting the flag to a number greater
234      * than the APK version (for example 999999999).
235      * @see DeviceConfigUtils#isFeatureEnabled(Context, String, String, boolean)
236      */
237     public static final String VALIDATION_METRICS_VERSION = "validation_metrics_version";
238 
239     /**
240      * Experiment flag to enable sending gratuitous multicast unsolicited Neighbor Advertisements
241      * to propagate new assigned IPv6 GUA as quickly as possible.
242      */
243     public static final String IPCLIENT_GRATUITOUS_NA_VERSION = "ipclient_gratuitous_na_version";
244 
245     /**
246      * Experiment flag to enable sending Gratuitous APR and Gratuitous Neighbor Advertisement for
247      * all assigned IPv4 and IPv6 GUAs after completing L2 roaming.
248      */
249     public static final String IPCLIENT_GARP_NA_ROAMING_VERSION =
250             "ipclient_garp_na_roaming_version";
251 
252     /**
253      * Experiment flag to disable accept_ra parameter when IPv6 provisioning loss happens due to
254      * the default route has gone.
255      */
256     public static final String IPCLIENT_DISABLE_ACCEPT_RA_VERSION = "ipclient_disable_accept_ra";
257 
258     static {
259         System.loadLibrary("networkstackutilsjni");
260     }
261 
262     /**
263      * Close a socket, ignoring any exception while closing.
264      */
closeSocketQuietly(FileDescriptor fd)265     public static void closeSocketQuietly(FileDescriptor fd) {
266         try {
267             SocketUtils.closeSocket(fd);
268         } catch (IOException ignored) {
269         }
270     }
271 
272     /**
273      * Convert IPv6 multicast address to ethernet multicast address in network order.
274      */
ipv6MulticastToEthernetMulticast(@onNull final Inet6Address addr)275     public static MacAddress ipv6MulticastToEthernetMulticast(@NonNull final Inet6Address addr) {
276         final byte[] etherMulticast = new byte[6];
277         final byte[] ipv6Multicast = addr.getAddress();
278         etherMulticast[0] = (byte) 0x33;
279         etherMulticast[1] = (byte) 0x33;
280         etherMulticast[2] = ipv6Multicast[12];
281         etherMulticast[3] = ipv6Multicast[13];
282         etherMulticast[4] = ipv6Multicast[14];
283         etherMulticast[5] = ipv6Multicast[15];
284         return MacAddress.fromBytes(etherMulticast);
285     }
286 
287     /**
288      * Attaches a socket filter that accepts DHCP packets to the given socket.
289      */
attachDhcpFilter(FileDescriptor fd)290     public static native void attachDhcpFilter(FileDescriptor fd) throws SocketException;
291 
292     /**
293      * Attaches a socket filter that accepts ICMPv6 router advertisements to the given socket.
294      * @param fd the socket's {@link FileDescriptor}.
295      * @param packetType the hardware address type, one of ARPHRD_*.
296      */
attachRaFilter(FileDescriptor fd, int packetType)297     public static native void attachRaFilter(FileDescriptor fd, int packetType)
298             throws SocketException;
299 
300     /**
301      * Attaches a socket filter that accepts L2-L4 signaling traffic required for IP connectivity.
302      *
303      * This includes: all ARP, ICMPv6 RS/RA/NS/NA messages, and DHCPv4 exchanges.
304      *
305      * @param fd the socket's {@link FileDescriptor}.
306      * @param packetType the hardware address type, one of ARPHRD_*.
307      */
attachControlPacketFilter(FileDescriptor fd, int packetType)308     public static native void attachControlPacketFilter(FileDescriptor fd, int packetType)
309             throws SocketException;
310 
311     /**
312      * Add an entry into the ARP cache.
313      */
addArpEntry(Inet4Address ipv4Addr, android.net.MacAddress ethAddr, String ifname, FileDescriptor fd)314     public static void addArpEntry(Inet4Address ipv4Addr, android.net.MacAddress ethAddr,
315             String ifname, FileDescriptor fd) throws IOException {
316         addArpEntry(ethAddr.toByteArray(), ipv4Addr.getAddress(), ifname, fd);
317     }
318 
addArpEntry(byte[] ethAddr, byte[] netAddr, String ifname, FileDescriptor fd)319     private static native void addArpEntry(byte[] ethAddr, byte[] netAddr, String ifname,
320             FileDescriptor fd) throws IOException;
321 
322 }
323