mirror of
https://github.com/systemd/systemd
synced 2024-09-06 16:56:43 +00:00
sd-dhcp-client: support 6rd option
This commit is contained in:
parent
63dc602570
commit
dbdcaca3ab
|
@ -70,6 +70,12 @@ struct sd_dhcp_lease {
|
|||
|
||||
char *timezone;
|
||||
|
||||
uint8_t sixrd_ipv4masklen;
|
||||
uint8_t sixrd_prefixlen;
|
||||
struct in6_addr sixrd_prefix;
|
||||
struct in_addr *sixrd_br_addresses;
|
||||
size_t sixrd_n_br_addresses;
|
||||
|
||||
LIST_HEAD(struct sd_dhcp_raw_option, private_options);
|
||||
};
|
||||
|
||||
|
|
|
@ -251,6 +251,33 @@ int sd_dhcp_lease_get_search_domains(sd_dhcp_lease *lease, char ***domains) {
|
|||
return -ENODATA;
|
||||
}
|
||||
|
||||
int sd_dhcp_lease_get_6rd(
|
||||
sd_dhcp_lease *lease,
|
||||
uint8_t *ret_ipv4masklen,
|
||||
uint8_t *ret_prefixlen,
|
||||
struct in6_addr *ret_prefix,
|
||||
const struct in_addr **ret_br_addresses,
|
||||
size_t *ret_n_br_addresses) {
|
||||
|
||||
assert_return(lease, -EINVAL);
|
||||
|
||||
if (lease->sixrd_n_br_addresses <= 0)
|
||||
return -ENODATA;
|
||||
|
||||
if (ret_ipv4masklen)
|
||||
*ret_ipv4masklen = lease->sixrd_ipv4masklen;
|
||||
if (ret_prefixlen)
|
||||
*ret_prefixlen = lease->sixrd_prefixlen;
|
||||
if (ret_prefix)
|
||||
*ret_prefix = lease->sixrd_prefix;
|
||||
if (ret_br_addresses)
|
||||
*ret_br_addresses = lease->sixrd_br_addresses;
|
||||
if (ret_n_br_addresses)
|
||||
*ret_n_br_addresses = lease->sixrd_n_br_addresses;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const void **data, size_t *data_len) {
|
||||
assert_return(lease, -EINVAL);
|
||||
assert_return(data, -EINVAL);
|
||||
|
@ -289,6 +316,7 @@ static sd_dhcp_lease *dhcp_lease_free(sd_dhcp_lease *lease) {
|
|||
free(lease->client_id);
|
||||
free(lease->vendor_specific);
|
||||
strv_free(lease->search_domains);
|
||||
free(lease->sixrd_br_addresses);
|
||||
return mfree(lease);
|
||||
}
|
||||
|
||||
|
@ -534,6 +562,61 @@ static int lease_parse_classless_routes(
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int lease_parse_6rd(sd_dhcp_lease *lease, const uint8_t *option, size_t len) {
|
||||
uint8_t ipv4masklen, prefixlen;
|
||||
struct in6_addr prefix;
|
||||
_cleanup_free_ struct in_addr *br_addresses = NULL;
|
||||
size_t n_br_addresses;
|
||||
|
||||
assert(lease);
|
||||
assert(option);
|
||||
|
||||
/* See RFC 5969 Section 7.1.1 */
|
||||
|
||||
if (lease->sixrd_n_br_addresses > 0)
|
||||
/* Multiple 6rd option?? */
|
||||
return -EINVAL;
|
||||
|
||||
/* option-length: The length of the DHCP option in octets (22 octets with one BR IPv4 address). */
|
||||
if (len < 2 + sizeof(struct in6_addr) + sizeof(struct in_addr) ||
|
||||
(len - 2 - sizeof(struct in6_addr)) % sizeof(struct in_addr) != 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* IPv4MaskLen: The number of high-order bits that are identical across all CE IPv4 addresses
|
||||
* within a given 6rd domain. This may be any value between 0 and 32. Any value
|
||||
* greater than 32 is invalid. */
|
||||
ipv4masklen = option[0];
|
||||
if (ipv4masklen > 32)
|
||||
return -EINVAL;
|
||||
|
||||
/* 6rdPrefixLen: The IPv6 prefix length of the SP's 6rd IPv6 prefix in number of bits. For the
|
||||
* purpose of bounds checking by DHCP option processing, the sum of
|
||||
* (32 - IPv4MaskLen) + 6rdPrefixLen MUST be less than or equal to 128. */
|
||||
prefixlen = option[1];
|
||||
if (32 - ipv4masklen + prefixlen > 128)
|
||||
return -EINVAL;
|
||||
|
||||
/* 6rdPrefix: The service provider's 6rd IPv6 prefix represented as a 16-octet IPv6 address.
|
||||
* The bits in the prefix after the 6rdPrefixlen number of bits are reserved and
|
||||
* MUST be initialized to zero by the sender and ignored by the receiver. */
|
||||
memcpy(&prefix, option + 2, sizeof(struct in6_addr));
|
||||
(void) in6_addr_mask(&prefix, prefixlen);
|
||||
|
||||
/* 6rdBRIPv4Address: One or more IPv4 addresses of the 6rd Border Relay(s) for a given 6rd domain. */
|
||||
n_br_addresses = (len - 2 - sizeof(struct in6_addr)) / sizeof(struct in_addr);
|
||||
br_addresses = newdup(struct in_addr, option + 2 + sizeof(struct in6_addr), n_br_addresses);
|
||||
if (!br_addresses)
|
||||
return -ENOMEM;
|
||||
|
||||
lease->sixrd_ipv4masklen = ipv4masklen;
|
||||
lease->sixrd_prefixlen = prefixlen;
|
||||
lease->sixrd_prefix = prefix;
|
||||
lease->sixrd_br_addresses = TAKE_PTR(br_addresses);
|
||||
lease->sixrd_n_br_addresses = n_br_addresses;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void *userdata) {
|
||||
sd_dhcp_lease *lease = userdata;
|
||||
int r;
|
||||
|
@ -719,6 +802,12 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
|
|||
lease->vendor_specific_len = len;
|
||||
break;
|
||||
|
||||
case SD_DHCP_OPTION_6RD:
|
||||
r = lease_parse_6rd(lease, option, len);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to parse 6rd option, ignoring: %m");
|
||||
break;
|
||||
|
||||
case SD_DHCP_OPTION_PRIVATE_BASE ... SD_DHCP_OPTION_PRIVATE_LAST:
|
||||
r = dhcp_lease_insert_private_option(lease, code, option, len);
|
||||
if (r < 0)
|
||||
|
|
|
@ -97,6 +97,7 @@ enum {
|
|||
SD_DHCP_OPTION_SIP_SERVER = 120,
|
||||
SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE = 121,
|
||||
SD_DHCP_OPTION_MUD_URL = 161,
|
||||
SD_DHCP_OPTION_6RD = 212,
|
||||
SD_DHCP_OPTION_PRIVATE_BASE = 224,
|
||||
/* Windows 10 option to send when Anonymize=true */
|
||||
SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE = 249,
|
||||
|
|
|
@ -71,6 +71,13 @@ int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, sd_dhcp_route ***routes);
|
|||
int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const void **data, size_t *data_len);
|
||||
int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const void **client_id, size_t *client_id_len);
|
||||
int sd_dhcp_lease_get_timezone(sd_dhcp_lease *lease, const char **timezone);
|
||||
int sd_dhcp_lease_get_6rd(
|
||||
sd_dhcp_lease *lease,
|
||||
uint8_t *ret_ipv4masklen,
|
||||
uint8_t *ret_prefixlen,
|
||||
struct in6_addr *ret_prefix,
|
||||
const struct in_addr **ret_br_addresses,
|
||||
size_t *ret_n_br_addresses);
|
||||
|
||||
int sd_dhcp_route_get_destination(sd_dhcp_route *route, struct in_addr *destination);
|
||||
int sd_dhcp_route_get_destination_prefix_length(sd_dhcp_route *route, uint8_t *length);
|
||||
|
|
Loading…
Reference in a new issue