esp-idf
esp-idf copied to clipboard
feat(esp_netfi): Add DHCPS option for captive portal identification (IDFGH-11885)
RFC 8910 provides a DHCP option to notify clients of a captive portal to be visited prior to using the network.
This is supported by vendors (see Apple since iOS 14 and macOS Big Sur, Android since Android 11), and provides a more standards-compliant mechanism than DNS-based redirection.
This is a simple addition and will be useful in scenarios where the ESP32 broadcasts a network and needs to direct clients to a portal or served content in a modern, standards-compliant way.
This would also address #2723.
| Messages | |
|---|---|
| :book: | 🎉 Good Job! All checks are passing! |
👋 Hello jkingsman, we appreciate your contribution to this project!
📘 Please review the project's Contributions Guide for key guidelines on code, documentation, testing, and more.
🖊️ Please also make sure you have read and signed the Contributor License Agreement for this project.
Click to see more instructions ...
This automated output is generated by the PR linter DangerJS, which checks if your Pull Request meets the project's requirements and helps you fix potential issues.
DangerJS is triggered with each push event to a Pull Request and modify the contents of this comment.
Please consider the following:
- Danger mainly focuses on the PR structure and formatting and can't understand the meaning behind your code or changes.
- Danger is not a substitute for human code reviews; it's still important to request a code review from your colleagues.
- To manually retry these Danger checks, please navigate to the Actions tab and re-run last Danger workflow.
Review and merge process you can expect ...
We do welcome contributions in the form of bug reports, feature requests and pull requests via this public GitHub repository.
This GitHub project is public mirror of our internal git repository
1. An internal issue has been created for the PR, we assign it to the relevant engineer.
2. They review the PR and either approve it or ask you for changes or clarifications.
3. Once the GitHub PR is approved, we synchronize it into our internal git repository.
4. In the internal git repository we do the final review, collect approvals from core owners and make sure all the automated tests are passing.
- At this point we may do some adjustments to the proposed change, or extend it by adding tests or documentation.
5. If the change is approved and passes the tests it is merged into the default branch.
5. On next sync from the internal git repository merged change will appear in this public GitHub repository.
Generated by :no_entry_sign: dangerJS against 593194d6228e7aac6e16577f8dc7dff0978877f5
Looks like a nice, additive, patch. I like it!
Hi @jkingsman
Thanks for the PR, but is it really all that's needed for this option to work? Haven't you forgotten to add other files to your commit?
I mean, it could work from the dhcpserver API using the recently introduced hooks, but since you added the option to esp_netif layer, we probably need some more. I would be also great to update the captive portal example.
Hm, adding to the enum so that you can serve that DHCP option seems all that's necessary to me -- it's up to a user to actually write the captive portal, of course; we have no way of knowing what they want for that. Is there something obvious I've missed?
I will do up a demo this evening if I can find some time. I'm happy to overwrite that captive portal example if desired, but it uses DNS redirection which is probably a reasonable demo to keep around -- DHCP opt is the better, more modern way to accomplish a redirect but DNS is still a valid approach. Do you have any preferences on overwrite vs. add (and I a suppose perhaps annotate each example to emphasize the different approaches and when they're appropriate for use)?
Thanks for the tips!
adding to the enum so that you can serve that DHCP option seems all that's necessary to me
This is probably enough for the DHCP client to parse and use it, that is if the ESP32 is connecting to a captive portal. If ESP32 as acting as a captive portal, it needs to add this option to DHCP server's messages. Our DHCP server is very simple, it just uses these few (hardcoded) options:
https://github.com/espressif/esp-idf/blob/6b9c2fca79a7b77a42242d48b0cfa82d612e9b85/components/lwip/apps/dhcpserver/dhcpserver.c#L407-L456
It's easy to append more options using the LWIP_HOOK_DHCPS_POST_APPEND_OPTS() macro (as I mentioned ^^):
https://github.com/espressif/esp-idf/blob/6b9c2fca79a7b77a42242d48b0cfa82d612e9b85/components/lwip/apps/dhcpserver/dhcpserver.c#L609
But that's again, just the lower layer. If you're adding this enum to esp_netif you'd like to make the netif API aware of this and allow users to configure this option.
Do you have any preferences on overwrite vs. add
It would be great if you use some local Kconfig.projbuld configuration to enable/disable this method in the example (perhaps you can also make the current DNS method configurable)
Ah, that's helpful context; thank you. Seems like I misunderstood how the DHCP system fit together in that regard -- I did indeed intend this as an offer value and not a client value.
I'll look into the funcs you linked and get my head around the least invasive way to do this.
I've got a draft but have just moved states so am waiting for my collection of devices to arrive with our moving van in a few days or so for real testing + sniffing the offer packet for validation. Thanks for your patience!
Alrighty, sorry for the force push noise but I've got this working now. Thank you again for your patience and such a complete explanation to remedy my super surface level understanding -- I've deepened that a bit now, haha.
I've also got a demo "done" in that it's code complete but I still want to make it its own little demo folder with a README etc. so I will have that ready for you tomorrow evening.
The gist is
index 4eba17b50b..4d14061864 100644
--- a/examples/wifi/getting_started/softAP/main/softap_example_main.c
+++ b/examples/wifi/getting_started/softAP/main/softap_example_main.c
@@ -85,6 +85,14 @@ void wifi_init_softap(void)
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
+ esp_netif_t* netif = esp_netif_get_handle_from_ifkey("WIFI_AP_DEF");
+
+ char* captive="http://captiveportal.local";
+
+ ESP_ERROR_CHECK_WITHOUT_ABORT(esp_netif_dhcps_stop(netif));
+ ESP_ERROR_CHECK(esp_netif_dhcps_option(netif, ESP_NETIF_OP_SET, ESP_NETIF_CAPTIVEPORTAL_URI, captive, strlen(captive)));
+ ESP_ERROR_CHECK_WITHOUT_ABORT(esp_netif_dhcps_start(netif));
+
ESP_LOGI(TAG, "wifi_init_softap finished. SSID:%s password:%s channel:%d",
EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS, EXAMPLE_ESP_WIFI_CHANNEL);
}
which updates the DHCP OFFER with the option:
Also wanted to add that I haven't written any C since college and had to muddle through with some help from my partner who is an embedded dev, so if I've made any boneheaded decisions or used any blindingly bad antipatterns, please call me out -- I won't be offended 🙂
Alrighty @david-cermak I think this is ready to go. I've validated this with an example, including tcpdump output of the result as a demo in the example file, and tested everything on real hardware.
Per the contributing docs, I also did an astyle run which moved some bits and bobs around in the files I worked on, but all seem like good changes.
Please let me know your feedback and if you want any changes. Thank you again for your patience!
Thanks for the update @jkingsman ! The changes look very good to me. The only thing is the allocation in the netif layers. Could we let users "own" that buffer, so we just copy the pointer? This would usually be a const char* to the program memory, so no allocation would be needed in most cases.
Sounds good! I've moved that malloc out.
Woohoo! Glad to hear it's made it to the next round.
I've squashed down my commits to one, and I'll sit tight. If you have a rough order of magnitude, please, is 'some time' for review usually weeks? Months? No worries no matter what it is; just curious.
Thanks again!
is 'some time' for review usually weeks? Months?
:-) I'd say ~ weeks (1 month on average, but the standard deviation is 'big')
feat(esp_netfi): add support for captive portal DHCP Option 114
just a typo with your last commit message -> feat(esp_netif)
Whoops, fixed.
Thanks for the info! I will wait to hear more from you when things progress.
It's been merged and published as https://github.com/espressif/esp-idf/commit/3035ce294d94cec9d801ab72866211cb534dac43 (had to rebase to pass the internal tests, so it didn't close automatically)
Eyy awesome; thank you!!
@david-cermak Hi. Is this on the roadmap? I just upgraded to v5.3 and it's not merged yet. Thanks