diff options
| author | Paul Donald | 2025-11-17 19:43:15 +0000 |
|---|---|---|
| committer | Álvaro Fernández Rojas | 2025-11-18 10:53:02 +0000 |
| commit | 9830e5e2bf375a7b74fa4ffc72330fccf0da6097 (patch) | |
| tree | 2a45fa08011d96bbb4d7c98b832a1179fe2df64a | |
| parent | d1500bb5d64d60e3fa4ec7ddb60501162002db3e (diff) | |
| download | odhcpd-9830e5e2bf375a7b74fa4ffc72330fccf0da6097.tar.gz | |
all: implement RFC8910 captive portal (CP) option for DHCPv4
https://www.rfc-editor.org/rfc/rfc8910.html
Signed-off-by: Paul Donald <newtwen+github@gmail.com>
Link: https://github.com/openwrt/odhcpd/pull/315
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
| -rw-r--r-- | README.md | 2 | ||||
| -rw-r--r-- | src/config.c | 5 | ||||
| -rw-r--r-- | src/dhcpv4.c | 19 | ||||
| -rw-r--r-- | src/dhcpv4.h | 1 |
4 files changed, 26 insertions, 1 deletions
@@ -121,7 +121,7 @@ and may also receive information from ubus | prefix_filter |string |`::/0` | Only advertise on-link prefixes within the provided IPv6 prefix; others are filtered out. [IPv6 prefix] | | ntp |list |`<local address>`| NTP servers to announce accepts IPv4 and IPv6 | | upstream |list | - | A list of interfaces which can be used as a source of configuration information (e.g. for NTP servers, if not set explicitly). | -| captive_portal_uri |string | no | The API URI to be sent in RFC8910 captive portal options, via DHCPv6 and ICMPv6 RA. | +| captive_portal_uri |string | no | The API URI to be sent in RFC8910 captive portal options, via DHCPv4, DHCPv6, and ICMPv6 RA. | [//]: # "dhcpv6_raw - string - not documented, may change when generic DHCPv4/DHCPv6 options are added" diff --git a/src/config.c b/src/config.c index b2991ef..865dadf 100644 --- a/src/config.c +++ b/src/config.c @@ -1310,6 +1310,11 @@ int config_parse_interface(void *data, size_t len, const char *name, bool overwr if ((c = tb[IFACE_ATTR_CAPTIVE_PORTAL_URI])) { iface->captive_portal_uri = strdup(blobmsg_get_string(c)); iface->captive_portal_uri_len = strlen(iface->captive_portal_uri); + if (iface->captive_portal_uri_len > UINT8_MAX) { + warn("RFC8910 captive portal URI > %d characters for interface '%s': option via DHCPv4 not possible", + UINT8_MAX, + iface->name); + } debug("Set RFC8910 captive portal URI: '%s' for interface '%s'", iface->captive_portal_uri, iface->name); } diff --git a/src/dhcpv4.c b/src/dhcpv4.c index cf5abf5..9ab7869 100644 --- a/src/dhcpv4.c +++ b/src/dhcpv4.c @@ -779,6 +779,7 @@ enum { IOV_FR_NONCE_CAP, IOV_DNR, IOV_DNR_BODY, + IOV_CAPTIVE_PORTAL, IOV_END, IOV_PADDING, IOV_TOTAL @@ -920,6 +921,7 @@ void dhcpv4_handle_msg(void *src_addr, void *data, size_t len, [IOV_FR_NONCE_CAP] = { &reply_fr_nonce_cap, 0 }, [IOV_DNR] = { &reply_dnr, 0 }, [IOV_DNR_BODY] = { NULL, 0 }, + [IOV_CAPTIVE_PORTAL] = { NULL, 0 }, [IOV_END] = { &reply_end, sizeof(reply_end) }, [IOV_PADDING] = { NULL, 0 }, }; @@ -938,6 +940,7 @@ void dhcpv4_handle_msg(void *src_addr, void *data, size_t len, DHCPV4_OPT_CLIENTID, // Must be in reply if present in req, RFC6842, §3 DHCPV4_OPT_AUTHENTICATION, DHCPV4_OPT_SEARCH_DOMAIN, + DHCPV4_OPT_CAPTIVE_PORTAL, DHCPV4_OPT_FORCERENEW_NONCE_CAPABLE, }; @@ -1296,6 +1299,22 @@ void dhcpv4_handle_msg(void *src_addr, void *data, size_t len, iov[IOV_DNR_BODY].iov_base = dnrs; iov[IOV_DNR_BODY].iov_len = dnrs_len; break; + + case DHCPV4_OPT_CAPTIVE_PORTAL: + size_t uri_len = iface->captive_portal_uri_len; + if (uri_len == 0 || uri_len > UINT8_MAX) + break; + + uint8_t *buf = alloca(2 + uri_len); + struct dhcpv4_option *opt = (struct dhcpv4_option *)buf; + + opt->code = DHCPV4_OPT_CAPTIVE_PORTAL; + opt->len = uri_len; + memcpy(opt->data, iface->captive_portal_uri, uri_len); + + iov[IOV_CAPTIVE_PORTAL].iov_base = opt; + iov[IOV_CAPTIVE_PORTAL].iov_len = 2 + uri_len; + break; } } diff --git a/src/dhcpv4.h b/src/dhcpv4.h index d2b31a3..f428022 100644 --- a/src/dhcpv4.h +++ b/src/dhcpv4.h @@ -78,6 +78,7 @@ enum dhcpv4_opt { DHCPV4_OPT_CLIENTID = 61, DHCPV4_OPT_USER_CLASS = 77, DHCPV4_OPT_AUTHENTICATION = 90, + DHCPV4_OPT_CAPTIVE_PORTAL = 114, // RFC8910 DHCPV4_OPT_SEARCH_DOMAIN = 119, DHCPV4_OPT_FORCERENEW_NONCE_CAPABLE = 145, DHCPV4_OPT_DNR = 162, |