From: Ronan Pigott Date: Thu, 29 Jun 2023 22:53:02 +0000 (-0700) Subject: dhcp-client: parse RFC8910 captive portal dhcp option X-Git-Tag: v254-rc1~51^2~8 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7040fd381a60959076c166cc8d38156bfc42aedf;p=thirdparty%2Fsystemd.git dhcp-client: parse RFC8910 captive portal dhcp option --- diff --git a/src/basic/string-util.h b/src/basic/string-util.h index 0ff5b46bba9..22ae777fd5d 100644 --- a/src/basic/string-util.h +++ b/src/basic/string-util.h @@ -22,6 +22,9 @@ #define ALPHANUMERICAL LETTERS DIGITS #define HEXDIGITS DIGITS "abcdefABCDEF" #define LOWERCASE_HEXDIGITS DIGITS "abcdef" +#define URI_RESERVED ":/?#[]@!$&'()*+;=" /* [RFC3986] */ +#define URI_UNRESERVED ALPHANUMERICAL "-._~" /* [RFC3986] */ +#define URI_VALID URI_RESERVED URI_UNRESERVED /* [RFC3986] */ static inline char* strstr_ptr(const char *haystack, const char *needle) { if (!haystack || !needle) diff --git a/src/libsystemd-network/dhcp-lease-internal.h b/src/libsystemd-network/dhcp-lease-internal.h index a660e522018..6503e3ce2d2 100644 --- a/src/libsystemd-network/dhcp-lease-internal.h +++ b/src/libsystemd-network/dhcp-lease-internal.h @@ -60,6 +60,7 @@ struct sd_dhcp_lease { char **search_domains; char *hostname; char *root_path; + char *captive_portal; void *client_id; size_t client_id_len; diff --git a/src/libsystemd-network/sd-dhcp-lease.c b/src/libsystemd-network/sd-dhcp-lease.c index fcc3f551549..03fd80064b7 100644 --- a/src/libsystemd-network/sd-dhcp-lease.c +++ b/src/libsystemd-network/sd-dhcp-lease.c @@ -168,6 +168,17 @@ int sd_dhcp_lease_get_root_path(sd_dhcp_lease *lease, const char **root_path) { return 0; } +int sd_dhcp_lease_get_captive_portal(sd_dhcp_lease *lease, const char **ret) { + assert_return(lease, -EINVAL); + assert_return(ret, -EINVAL); + + if (!lease->captive_portal) + return -ENODATA; + + *ret = lease->captive_portal; + return 0; +} + int sd_dhcp_lease_get_router(sd_dhcp_lease *lease, const struct in_addr **addr) { assert_return(lease, -EINVAL); assert_return(addr, -EINVAL); @@ -322,6 +333,7 @@ static sd_dhcp_lease *dhcp_lease_free(sd_dhcp_lease *lease) { free(lease->timezone); free(lease->hostname); free(lease->domainname); + free(lease->captive_portal); for (sd_dhcp_lease_server_type_t i = 0; i < _SD_DHCP_LEASE_SERVER_TYPE_MAX; i++) free(lease->servers[i].addr); @@ -406,6 +418,22 @@ static int lease_parse_domain(const uint8_t *option, size_t len, char **ret) { return 0; } +static int lease_parse_captive_portal(const uint8_t *option, size_t len, char **ret) { + _cleanup_free_ char *uri = NULL; + int r; + + assert(option); + assert(ret); + + r = dhcp_option_parse_string(option, len, &uri); + if (r < 0) + return r; + if (uri && !in_charset(uri, URI_VALID)) + return -EINVAL; + + return free_and_replace(*ret, uri); +} + static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_addr **ret, size_t *n_ret) { assert(option || len == 0); assert(ret); @@ -675,6 +703,12 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void log_debug_errno(r, "Failed to parse LPR server, ignoring: %m"); break; + case SD_DHCP_OPTION_DHCP_CAPTIVE_PORTAL: + r = lease_parse_captive_portal(option, len, &lease->captive_portal); + if (r < 0) + log_debug_errno(r, "Failed to parse captive portal, ignoring: %m"); + break; + case SD_DHCP_OPTION_STATIC_ROUTE: r = lease_parse_static_routes(lease, option, len); if (r < 0) diff --git a/src/systemd/sd-dhcp-lease.h b/src/systemd/sd-dhcp-lease.h index 3f21826b8a6..a0e09e52aca 100644 --- a/src/systemd/sd-dhcp-lease.h +++ b/src/systemd/sd-dhcp-lease.h @@ -67,6 +67,7 @@ int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname); int sd_dhcp_lease_get_search_domains(sd_dhcp_lease *lease, char ***domains); int sd_dhcp_lease_get_hostname(sd_dhcp_lease *lease, const char **hostname); int sd_dhcp_lease_get_root_path(sd_dhcp_lease *lease, const char **root_path); +int sd_dhcp_lease_get_captive_portal(sd_dhcp_lease *lease, const char **captive_portal); int sd_dhcp_lease_get_static_routes(sd_dhcp_lease *lease, sd_dhcp_route ***ret); int sd_dhcp_lease_get_classless_routes(sd_dhcp_lease *lease, sd_dhcp_route ***ret); int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const void **data, size_t *data_len);