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