dhcp6-client: parse RFC8910 captive portal dhcp6 option

This commit is contained in:
Ronan Pigott 2023-06-29 15:55:21 -07:00
parent 7040fd381a
commit fde788601b
5 changed files with 59 additions and 0 deletions

View file

@ -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(

View file

@ -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;

View file

@ -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,

View file

@ -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);

View file

@ -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);