diff --git a/src/libsystemd-network/dhcp6-lease-internal.h b/src/libsystemd-network/dhcp6-lease-internal.h index 1f10dccbbb0..f4c12ca7c4a 100644 --- a/src/libsystemd-network/dhcp6-lease-internal.h +++ b/src/libsystemd-network/dhcp6-lease-internal.h @@ -43,6 +43,7 @@ struct sd_dhcp6_lease { struct in6_addr *sntp; size_t sntp_count; char *fqdn; + char *captive_portal; }; int dhcp6_lease_get_lifetime(sd_dhcp6_lease *lease, usec_t *ret_t1, usec_t *ret_t2, usec_t *ret_valid); @@ -60,6 +61,7 @@ int dhcp6_lease_add_domains(sd_dhcp6_lease *lease, const uint8_t *optval, size_t int dhcp6_lease_add_ntp(sd_dhcp6_lease *lease, const uint8_t *optval, size_t optlen); int dhcp6_lease_add_sntp(sd_dhcp6_lease *lease, const uint8_t *optval, size_t optlen); int dhcp6_lease_set_fqdn(sd_dhcp6_lease *lease, const uint8_t *optval, size_t optlen); +int dhcp6_lease_set_captive_portal(sd_dhcp6_lease *lease, const uint8_t *optval, size_t optlen); int dhcp6_lease_new(sd_dhcp6_lease **ret); int dhcp6_lease_new_from_message( diff --git a/src/libsystemd-network/dhcp6-option.c b/src/libsystemd-network/dhcp6-option.c index a6b74e07b28..3409485e118 100644 --- a/src/libsystemd-network/dhcp6-option.c +++ b/src/libsystemd-network/dhcp6-option.c @@ -524,6 +524,26 @@ int dhcp6_option_parse_status(const uint8_t *data, size_t data_len, char **ret_s return status; } +/* parse a string from dhcp option field. *ret must be initialized */ +int dhcp6_option_parse_string(const uint8_t *data, size_t data_len, char **ret) { + _cleanup_free_ char *string = NULL; + int r; + + assert(data); + assert(ret); + + if (data_len <= 0) { + *ret = mfree(*ret); + return 0; + } + + r = make_cstring((const char *) data, data_len, MAKE_CSTRING_REFUSE_TRAILING_NUL, &string); + if (r < 0) + return r; + + return free_and_replace(*ret, string); +} + static int dhcp6_option_parse_ia_options(sd_dhcp6_client *client, const uint8_t *buf, size_t buflen) { int r; diff --git a/src/libsystemd-network/dhcp6-option.h b/src/libsystemd-network/dhcp6-option.h index 36841dd270c..614b4f8a43d 100644 --- a/src/libsystemd-network/dhcp6-option.h +++ b/src/libsystemd-network/dhcp6-option.h @@ -88,6 +88,7 @@ int dhcp6_option_parse( size_t *ret_option_data_len, const uint8_t **ret_option_data); int dhcp6_option_parse_status(const uint8_t *data, size_t data_len, char **ret_status_message); +int dhcp6_option_parse_string(const uint8_t *data, size_t data_len, char **ret); int dhcp6_option_parse_ia( sd_dhcp6_client *client, be32_t iaid, diff --git a/src/libsystemd-network/sd-dhcp6-lease.c b/src/libsystemd-network/sd-dhcp6-lease.c index d14c412c1fb..89e5a608f8a 100644 --- a/src/libsystemd-network/sd-dhcp6-lease.c +++ b/src/libsystemd-network/sd-dhcp6-lease.c @@ -445,6 +445,34 @@ int sd_dhcp6_lease_get_fqdn(sd_dhcp6_lease *lease, const char **ret) { return 0; } +int dhcp6_lease_set_captive_portal(sd_dhcp6_lease *lease, const uint8_t *optval, size_t optlen) { + _cleanup_free_ char *uri = NULL; + int r; + + assert(lease); + assert(optval || optlen == 0); + + r = dhcp6_option_parse_string(optval, optlen, &uri); + if (r < 0) + return r; + + if (uri && !in_charset(uri, URI_VALID)) + return -EINVAL; + + return free_and_replace(lease->captive_portal, uri); +} + +int sd_dhcp6_lease_get_captive_portal(sd_dhcp6_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; +} + static int dhcp6_lease_parse_message( sd_dhcp6_client *client, sd_dhcp6_lease *lease, @@ -605,6 +633,12 @@ static int dhcp6_lease_parse_message( break; + case SD_DHCP6_OPTION_CAPTIVE_PORTAL: + r = dhcp6_lease_set_captive_portal(lease, optval, optlen); + if (r < 0) + log_dhcp6_client_errno(client, r, "Failed to parse captive portal option, ignoring: %m"); + break; + case SD_DHCP6_OPTION_CLIENT_FQDN: r = dhcp6_lease_set_fqdn(lease, optval, optlen); if (r < 0) @@ -665,6 +699,7 @@ static sd_dhcp6_lease *dhcp6_lease_free(sd_dhcp6_lease *lease) { dhcp6_ia_free(lease->ia_pd); free(lease->dns); free(lease->fqdn); + free(lease->captive_portal); strv_free(lease->domains); free(lease->ntp); strv_free(lease->ntp_fqdn); diff --git a/src/systemd/sd-dhcp6-lease.h b/src/systemd/sd-dhcp6-lease.h index 716f6fc17c6..9f52496985b 100644 --- a/src/systemd/sd-dhcp6-lease.h +++ b/src/systemd/sd-dhcp6-lease.h @@ -48,6 +48,7 @@ int sd_dhcp6_lease_get_domains(sd_dhcp6_lease *lease, char ***ret); int sd_dhcp6_lease_get_ntp_addrs(sd_dhcp6_lease *lease, const struct in6_addr **ret); int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease *lease, char ***ret); int sd_dhcp6_lease_get_fqdn(sd_dhcp6_lease *lease, const char **ret); +int sd_dhcp6_lease_get_captive_portal(sd_dhcp6_lease *lease, const char **ret); sd_dhcp6_lease *sd_dhcp6_lease_ref(sd_dhcp6_lease *lease); sd_dhcp6_lease *sd_dhcp6_lease_unref(sd_dhcp6_lease *lease);