xref: /aosp_15_r20/external/libwebsockets/READMEs/README.captive-portal-detection.md (revision 1c60b9aca93fdbc9b5f19b2d2194c91294b22281)
1# Captive Portal Detection
2
3## Background
4
5Wifi devices may face some interception of their connection to the
6internet, it's very common for, eg, coffee shop wifi to present some
7kind of login or other clickthrough before access to the Internet is
8granted.  Devices may need to understand that they are in this
9situation, and there are several different techniques for trying to
10gague it.
11
12Sequence-wise the device has been granted a DHCP lease and has been
13configured with DNS, but the DNS may be wrongly resolving everything
14to an address on the LAN or a portal on the net.
15
16Whether there is a captive portal active should be a sticky state for a given
17connection if there is not going to be any attempt to login or pass the landing
18page, it only needs checking for after DHCP acquisition then.  If there will be
19an attempt to satisfy the landing page, the test should be repeated after the
20attempt.
21
22## Detection schemes
23
24The most popular detection scheme by numbers is Android's method,
25which is to make an HTTP client GET to `http://connectivitycheck.android.com/generate_204`
26and see if a 204 is coming back... if intercepted, typically there'll be a
273xx redirect to the portal, perhaps on https.  Or, it may reply on http with
28a 200 and show the portal directly... either way it won't deliver a 204
29like the real remote server does.
30
31Variations include expecting a 200 but with specific http body content, and
32doing a DNS lookup for a static IP that the device knows; if it's resolved to
33something else, it knows there's monkey business implying a captive portal.
34
35Other schemes involve https connections going out and detecting that the cert
36of the server it's actually talking to doesn't check out, although this is
37potentially ambiguous.
38
39Yet more methods are possible outside of tcp or http.
40
41## lws captive portal detect support
42
43lws provides a generic api to start captive portal detection...
44
45```
46LWS_EXTERN LWS_VISIBLE int
47lws_system_cpd_start(struct lws_context *context);
48```
49
50and two states in `lws_system` states to trigger it from, either
51`LWS_SYSTATE_CPD_PRE_TIME` which happens after DHCP acquisition but before
52ntpclient and is suitable for non https-based scheme where the time doesn't
53need to be known, or the alternative `LWS_SYSTATE_CPD_POST_TIME` state which
54happens after ntpclient has completed and we know the time.
55
56The actual platform implementation is set using `lws_system_ops_t` function
57pointer `captive_portal_detect_request`, ie
58
59```
60	int (*captive_portal_detect_request)(struct lws_context *context);
61	/**< Check if we can go out on the internet cleanly, or if we are being
62	 * redirected or intercepted by a captive portal.
63	 * Start the check that proceeds asynchronously, and report the results
64	 * by calling lws_captive_portal_detect_result() api
65	 */
66```
67
68User platform code can provide this to implement whatever scheme they want, when
69it has arrived at a result, it can call the lws api `lws_system_cpd_result()` to
70inform lws.  If there isn't any captive portal, this will also try to advance the
71system state towards OPERATIONAL.
72
73```
74/**
75 * lws_system_cpd_result() - report the result of the captive portal detection
76 *
77 * \param context: the lws_context
78 * \param result: one of the LWS_CPD_ constants representing captive portal state
79 * \param redirect_url: NULL, or the url we were redirected to if result is
80 *     LWS_CPD_HTTP_REDIRECT
81 *
82 * Sets the context's captive portal detection state to result.  User captive
83 * portal detection code would call this once it had a result from its test.
84 */
85LWS_EXTERN LWS_VISIBLE int
86lws_system_cpd_result(struct lws_context *context, int result, const char *redirect_url);
87```
88
89