static void dhcp6_lease_set_lifetime(sd_dhcp6_lease *lease) {
uint32_t t1 = UINT32_MAX, t2 = UINT32_MAX, min_valid_lt = UINT32_MAX;
- DHCP6Address *a;
assert(lease);
assert(lease->ia_na || lease->ia_pd);
}
void dhcp6_ia_clear_addresses(DHCP6IA *ia) {
- DHCP6Address *a, *n;
-
assert(ia);
- LIST_FOREACH_SAFE(addresses, a, n, ia->addresses)
+ LIST_FOREACH(addresses, a, ia->addresses)
free(a);
ia->addresses = NULL;
if (r < 0)
return r;
- switch(subopt) {
+ switch (subopt) {
case DHCP6_NTP_SUBOPTION_SRV_ADDR:
case DHCP6_NTP_SUBOPTION_MC_ADDR:
if (sublen != 16)
- return 0;
+ return -EINVAL;
r = dhcp6_option_parse_addresses(subval, sublen, &lease->ntp, &lease->ntp_count);
if (r < 0)
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,
size_t optlen;
const uint8_t *optval;
+ if (len - offset < offsetof(DHCP6Option, data)) {
+ log_dhcp6_client(client, "Ignoring %zu invalid byte(s) at the end of the packet", len - offset);
+ break;
+ }
+
r = dhcp6_option_parse(message->options, len, &offset, &optcode, &optlen, &optval);
if (r < 0)
- return r;
+ return log_dhcp6_client_errno(client, r,
+ "Failed to parse option header at offset %zu of total length %zu: %m",
+ offset, len);
switch (optcode) {
case SD_DHCP6_OPTION_CLIENTID:
r = dhcp6_lease_set_clientid(lease, optval, optlen);
if (r < 0)
- return r;
+ return log_dhcp6_client_errno(client, r, "Failed to set client ID: %m");
break;
r = dhcp6_lease_set_serverid(lease, optval, optlen);
if (r < 0)
- return r;
+ return log_dhcp6_client_errno(client, r, "Failed to set server ID: %m");
break;
case SD_DHCP6_OPTION_PREFERENCE:
if (optlen != 1)
- return -EINVAL;
+ return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL), "Received invalid length for preference.");
r = dhcp6_lease_set_preference(lease, optval[0]);
if (r < 0)
- return r;
+ return log_dhcp6_client_errno(client, r, "Failed to set preference: %m");
break;
r = dhcp6_option_parse_status(optval, optlen, &msg);
if (r < 0)
- return r;
-
+ return log_dhcp6_client_errno(client, r, "Failed to parse status code: %m");
if (r > 0)
- return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL),
- "Received %s message with non-zero status: %s%s%s",
+ return log_dhcp6_client_errno(client, dhcp6_message_status_to_errno(r),
+ "Received %s message with non-zero status%s%s",
dhcp6_message_type_to_string(message->type),
- strempty(msg), isempty(msg) ? "" : ": ",
- dhcp6_message_status_to_string(r));
+ isempty(msg) ? "." : ": ", strempty(msg));
break;
}
case SD_DHCP6_OPTION_IA_NA: {
r = dhcp6_option_parse_ia(client, client->ia_na.header.id, optcode, optlen, optval, &ia);
if (r == -ENOMEM)
- return r;
- if (r < 0)
+ return log_oom_debug();
+ if (r < 0) {
+ log_dhcp6_client_errno(client, r, "Failed to parse IA_NA option, ignoring: %m");
continue;
+ }
if (lease->ia_na) {
log_dhcp6_client(client, "Received duplicate matching IA_NA option, ignoring.");
r = dhcp6_option_parse_ia(client, client->ia_pd.header.id, optcode, optlen, optval, &ia);
if (r == -ENOMEM)
- return r;
- if (r < 0)
+ return log_oom_debug();
+ if (r < 0) {
+ log_dhcp6_client_errno(client, r, "Failed to parse IA_PD option, ignoring: %m");
continue;
+ }
if (lease->ia_pd) {
log_dhcp6_client(client, "Received duplicate matching IA_PD option, ignoring.");
break;
}
case SD_DHCP6_OPTION_RAPID_COMMIT:
+ if (optlen != 0)
+ log_dhcp6_client(client, "Received rapid commit option with an invalid length (%zu), ignoring.", optlen);
+
r = dhcp6_lease_set_rapid_commit(lease);
if (r < 0)
- return r;
+ return log_dhcp6_client_errno(client, r, "Failed to set rapid commit flag: %m");
break;
- case SD_DHCP6_OPTION_DNS_SERVERS:
+ case SD_DHCP6_OPTION_DNS_SERVER:
r = dhcp6_lease_add_dns(lease, optval, optlen);
if (r < 0)
log_dhcp6_client_errno(client, r, "Failed to parse DNS server option, ignoring: %m");
break;
- case SD_DHCP6_OPTION_DOMAIN_LIST:
+ case SD_DHCP6_OPTION_DOMAIN:
r = dhcp6_lease_add_domains(lease, optval, optlen);
if (r < 0)
log_dhcp6_client_errno(client, r, "Failed to parse domain list option, ignoring: %m");
break;
- case SD_DHCP6_OPTION_SNTP_SERVERS:
+ case SD_DHCP6_OPTION_SNTP_SERVER:
r = dhcp6_lease_add_sntp(lease, optval, optlen);
if (r < 0)
log_dhcp6_client_errno(client, r, "Failed to parse SNTP server option, ignoring: %m");
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)
case SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME:
if (optlen != 4)
- return -EINVAL;
+ return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL),
+ "Received information refresh time option with an invalid length (%zu).", optlen);
- irt = unaligned_read_be32((be32_t *) optval) * USEC_PER_SEC;
+ irt = unaligned_read_be32(optval) * USEC_PER_SEC;
break;
}
}
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);