mirror of
https://github.com/systemd/systemd.git
synced 2024-12-23 21:35:11 +03:00
network: Parse RFC9463 DHCPv6 DNR option
Implement the parsing for V6_DNR DHCPv6 option. This does the same as the DHCP V4_DNR option.
This commit is contained in:
parent
1be9b30a3b
commit
a07e83cc58
@ -8,6 +8,7 @@
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "sd-dhcp6-lease.h"
|
||||
#include "dns-resolver-internal.h"
|
||||
|
||||
#include "dhcp6-option.h"
|
||||
#include "dhcp6-protocol.h"
|
||||
@ -38,6 +39,8 @@ struct sd_dhcp6_lease {
|
||||
|
||||
struct in6_addr *dns;
|
||||
size_t dns_count;
|
||||
sd_dns_resolver *dnr;
|
||||
size_t n_dnr;
|
||||
char **domains;
|
||||
struct in6_addr *ntp;
|
||||
size_t ntp_count;
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "dhcp6-internal.h"
|
||||
#include "dhcp6-lease-internal.h"
|
||||
#include "network-common.h"
|
||||
#include "sort-util.h"
|
||||
#include "strv.h"
|
||||
#include "unaligned.h"
|
||||
|
||||
@ -438,6 +439,98 @@ int sd_dhcp6_lease_get_domains(sd_dhcp6_lease *lease, char ***ret) {
|
||||
return strv_length(lease->domains);
|
||||
}
|
||||
|
||||
static int dhcp6_lease_add_dnr(sd_dhcp6_lease *lease, const uint8_t *optval, size_t optlen) {
|
||||
int r;
|
||||
|
||||
assert(lease);
|
||||
|
||||
_cleanup_(sd_dns_resolver_done) sd_dns_resolver res = {};
|
||||
|
||||
size_t offset = 0;
|
||||
|
||||
/* priority */
|
||||
if (optlen - offset < sizeof(uint16_t))
|
||||
return -EBADMSG;
|
||||
res.priority = unaligned_read_be16(optval + offset);
|
||||
offset += sizeof(uint16_t);
|
||||
|
||||
/* adn */
|
||||
if (optlen - offset < sizeof(uint16_t))
|
||||
return -EBADMSG;
|
||||
size_t ilen = unaligned_read_be16(optval + offset);
|
||||
offset += sizeof(uint16_t);
|
||||
if (offset + ilen > optlen)
|
||||
return -EBADMSG;
|
||||
|
||||
r = dhcp6_option_parse_domainname(optval + offset, ilen, &res.auth_name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
offset += ilen;
|
||||
|
||||
/* RFC9463 § 3.1.6: adn only mode */
|
||||
if (offset == optlen)
|
||||
return 0;
|
||||
|
||||
/* addrs */
|
||||
if (optlen - offset < sizeof(uint16_t))
|
||||
return -EBADMSG;
|
||||
ilen = unaligned_read_be16(optval + offset);
|
||||
offset += sizeof(uint16_t);
|
||||
if (offset + ilen > optlen)
|
||||
return -EBADMSG;
|
||||
|
||||
_cleanup_free_ struct in6_addr *addrs = NULL;
|
||||
size_t n_addrs = 0;
|
||||
|
||||
r = dhcp6_option_parse_addresses(optval + offset, ilen, &addrs, &n_addrs);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (n_addrs == 0)
|
||||
return -EBADMSG;
|
||||
offset += ilen;
|
||||
|
||||
res.addrs = new(union in_addr_union, n_addrs);
|
||||
if (!res.addrs)
|
||||
return -ENOMEM
|
||||
|
||||
for (size_t i = 0; i < n_addrs; i++) {
|
||||
union in_addr_union addr = {.in6 = addrs[i]};
|
||||
/* RFC9463 § 6.2 client MUST discard multicast and host loopback addresses */
|
||||
if (in_addr_is_multicast(AF_INET6, &addr) ||
|
||||
in_addr_is_localhost(AF_INET6, &addr))
|
||||
return -EBADMSG;
|
||||
res.addrs[i] = addr;
|
||||
}
|
||||
res.n_addrs = n_addrs;
|
||||
res.family = AF_INET6;
|
||||
|
||||
/* svc params */
|
||||
r = dnr_parse_svc_params(optval + offset, optlen-offset, &res);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Append this resolver */
|
||||
if (!GREEDY_REALLOC(lease->dnr, lease->n_dnr+1))
|
||||
return -ENOMEM;
|
||||
|
||||
lease->dnr[lease->n_dnr++] = TAKE_STRUCT(res);
|
||||
|
||||
typesafe_qsort(lease->dnr, lease->n_dnr, dns_resolver_prio_compare);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sd_dhcp6_lease_get_dnr(sd_dhcp6_lease *lease, sd_dns_resolver **ret) {
|
||||
assert_return(lease, -EINVAL);
|
||||
assert_return(ret, -EINVAL);
|
||||
|
||||
if (!lease->dnr)
|
||||
return -ENODATA;
|
||||
|
||||
*ret = lease->dnr;
|
||||
return lease->n_dnr;
|
||||
}
|
||||
|
||||
int dhcp6_lease_add_ntp(sd_dhcp6_lease *lease, const uint8_t *optval, size_t optlen) {
|
||||
int r;
|
||||
|
||||
@ -851,6 +944,15 @@ static int dhcp6_lease_parse_message(
|
||||
irt = unaligned_be32_sec_to_usec(optval, /* max_as_infinity = */ false);
|
||||
break;
|
||||
|
||||
case SD_DHCP6_OPTION_V6_DNR:
|
||||
r = dhcp6_lease_add_dnr(lease, optval, optlen);
|
||||
if (r < 0)
|
||||
return log_dhcp6_client_errno(client, r, "Failed to parse DNR option, ignoring: %m");
|
||||
if (r == 0)
|
||||
log_dhcp6_client(client, "Received ADN-only DNRv6 option, ignoring.");
|
||||
|
||||
break;
|
||||
|
||||
case SD_DHCP6_OPTION_VENDOR_OPTS:
|
||||
r = dhcp6_lease_add_vendor_option(lease, optval, optlen);
|
||||
if (r < 0)
|
||||
@ -904,6 +1006,7 @@ static sd_dhcp6_lease *dhcp6_lease_free(sd_dhcp6_lease *lease) {
|
||||
dhcp6_ia_free(lease->ia_na);
|
||||
dhcp6_ia_free(lease->ia_pd);
|
||||
free(lease->dns);
|
||||
dns_resolver_done_many(lease->dnr, lease->n_dnr);
|
||||
free(lease->fqdn);
|
||||
free(lease->captive_portal);
|
||||
strv_free(lease->domains);
|
||||
|
@ -30,6 +30,7 @@
|
||||
_SD_BEGIN_DECLARATIONS;
|
||||
|
||||
typedef struct sd_dhcp6_lease sd_dhcp6_lease;
|
||||
typedef struct sd_dns_resolver sd_dns_resolver;
|
||||
|
||||
int sd_dhcp6_lease_get_timestamp(sd_dhcp6_lease *lease, clockid_t clock, uint64_t *ret);
|
||||
int sd_dhcp6_lease_get_t1(sd_dhcp6_lease *lease, uint64_t *ret);
|
||||
@ -74,6 +75,7 @@ int sd_dhcp6_lease_get_pd_lifetime_timestamp(
|
||||
int sd_dhcp6_lease_has_pd_prefix(sd_dhcp6_lease *lease);
|
||||
|
||||
int sd_dhcp6_lease_get_dns(sd_dhcp6_lease *lease, const struct in6_addr **ret);
|
||||
int sd_dhcp6_lease_get_dnr(sd_dhcp6_lease *lease, sd_dns_resolver **ret);
|
||||
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);
|
||||
|
@ -165,8 +165,9 @@ enum {
|
||||
SD_DHCP6_OPTION_SLAP_QUAD = 140, /* RFC 8948 */
|
||||
SD_DHCP6_OPTION_V6_DOTS_RI = 141, /* RFC 8973 */
|
||||
SD_DHCP6_OPTION_V6_DOTS_ADDRESS = 142, /* RFC 8973 */
|
||||
SD_DHCP6_OPTION_IPV6_ADDRESS_ANDSF = 143 /* RFC 6153 */
|
||||
/* option codes 144-65535 are unassigned */
|
||||
SD_DHCP6_OPTION_IPV6_ADDRESS_ANDSF = 143, /* RFC 6153 */
|
||||
SD_DHCP6_OPTION_V6_DNR = 144 /* RFC 9463 */
|
||||
/* option codes 145-65535 are unassigned */
|
||||
};
|
||||
|
||||
_SD_END_DECLARATIONS;
|
||||
|
Loading…
Reference in New Issue
Block a user