mirror of
https://github.com/systemd/systemd
synced 2024-10-14 20:17:52 +00:00
network: DHCPv6 client add support for prefix delegation hint
Add support for prefix hint lenth and prefix hint address ``` Frame 43: 177 bytes on wire (1416 bits), 177 bytes captured (1416 bits) on interface 0 Ethernet II, Src: f6:c1:08:4d:45:f1 (f6:c1:08:4d:45:f1), Dst: IPv6mcast_01:00:02 (33:33:00:01:00:02) Internet Protocol Version 6, Src: fe80::d250:c82:7f6e:28d6, Dst: ff02::1:2 User Datagram Protocol, Src Port: 546, Dst Port: 547 DHCPv6 Message type: Solicit (1) Transaction ID: 0x5c7902 Rapid Commit Identity Association for Non-temporary Address Fully Qualified Domain Name Identity Association for Prefix Delegation Option: Identity Association for Prefix Delegation (25) Length: 41 Value: 1b97b1690000000000000000001a0019ffffffffffffffff… IAID: 1b97b169 T1: 0 T2: 0 IA Prefix Option: IA Prefix (26) Length: 25 Value: ffffffffffffffff3c000000000000000000000000000000… Preferred lifetime: infinity Valid lifetime: infinity Prefix length: 60 Prefix address: :: Option Request Client Identifier Elapsed time ```
This commit is contained in:
parent
d90874b4e2
commit
2805536bff
|
@ -1632,6 +1632,14 @@
|
|||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>PrefixDelegationHint=</varname></term>
|
||||
<listitem>
|
||||
<para>Takes an IPv6 address with prefix length as <varname>Addresss=</varname> in
|
||||
the "[Network]" section. Specifies the DHCPv6 client for the requesting router to include
|
||||
a prefix-hint in the DHCPv6 solicitation. Prefix ranges 1-128. Defaults to unset.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ typedef struct DHCP6IA DHCP6IA;
|
|||
int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code,
|
||||
size_t optlen, const void *optval);
|
||||
int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia);
|
||||
int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd);
|
||||
int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd, DHCP6Address *hint_pd_prefix);
|
||||
int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn);
|
||||
int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode,
|
||||
size_t *optlen, uint8_t **optvalue);
|
||||
|
|
|
@ -168,9 +168,10 @@ int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn) {
|
|||
return r;
|
||||
}
|
||||
|
||||
int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd) {
|
||||
int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd, DHCP6Address *hint_pd_prefix) {
|
||||
DHCP6Option *option = (DHCP6Option *)buf;
|
||||
size_t i = sizeof(*option) + sizeof(pd->ia_pd);
|
||||
DHCP6PDPrefixOption *prefix_opt;
|
||||
DHCP6Address *prefix;
|
||||
|
||||
assert_return(buf, -EINVAL);
|
||||
|
@ -183,10 +184,7 @@ int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd) {
|
|||
option->code = htobe16(SD_DHCP6_OPTION_IA_PD);
|
||||
|
||||
memcpy(&option->data, &pd->ia_pd, sizeof(pd->ia_pd));
|
||||
|
||||
LIST_FOREACH(addresses, prefix, pd->addresses) {
|
||||
DHCP6PDPrefixOption *prefix_opt;
|
||||
|
||||
if (len < i + sizeof(*prefix_opt))
|
||||
return -ENOBUFS;
|
||||
|
||||
|
@ -194,9 +192,19 @@ int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd) {
|
|||
prefix_opt->option.code = htobe16(SD_DHCP6_OPTION_IA_PD_PREFIX);
|
||||
prefix_opt->option.len = htobe16(sizeof(prefix_opt->iapdprefix));
|
||||
|
||||
memcpy(&prefix_opt->iapdprefix, &prefix->iapdprefix,
|
||||
sizeof(struct iapdprefix));
|
||||
memcpy(&prefix_opt->iapdprefix, &prefix->iapdprefix, sizeof(struct iapdprefix));
|
||||
i += sizeof(*prefix_opt);
|
||||
}
|
||||
|
||||
if (hint_pd_prefix && hint_pd_prefix->iapdprefix.prefixlen > 0) {
|
||||
if (len < i + sizeof(*prefix_opt))
|
||||
return -ENOBUFS;
|
||||
|
||||
prefix_opt = (DHCP6PDPrefixOption *)&buf[i];
|
||||
prefix_opt->option.code = htobe16(SD_DHCP6_OPTION_IA_PD_PREFIX);
|
||||
prefix_opt->option.len = htobe16(sizeof(prefix_opt->iapdprefix));
|
||||
|
||||
memcpy(&prefix_opt->iapdprefix, &hint_pd_prefix->iapdprefix, sizeof(struct iapdprefix));
|
||||
i += sizeof(*prefix_opt);
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ struct sd_dhcp6_client {
|
|||
sd_event *event;
|
||||
int event_priority;
|
||||
int ifindex;
|
||||
DHCP6Address hint_pd_prefix;
|
||||
struct in6_addr local_address;
|
||||
uint8_t mac_addr[MAX_MAC_ADDR_LEN];
|
||||
size_t mac_addr_len;
|
||||
|
@ -187,6 +188,22 @@ int sd_dhcp6_client_set_mac(
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sd_dhcp6_client_set_prefix_delegation_hint(
|
||||
sd_dhcp6_client *client,
|
||||
uint8_t prefixlen,
|
||||
const struct in6_addr *pd_address) {
|
||||
|
||||
assert_return(client, -EINVAL);
|
||||
assert_return(pd_address, -EINVAL);
|
||||
|
||||
assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
|
||||
|
||||
client->hint_pd_prefix.iapdprefix.address = *pd_address;
|
||||
client->hint_pd_prefix.iapdprefix.prefixlen = prefixlen;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int client_ensure_duid(sd_dhcp6_client *client) {
|
||||
if (client->duid_len != 0)
|
||||
return 0;
|
||||
|
@ -492,7 +509,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
|
|||
}
|
||||
|
||||
if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) {
|
||||
r = dhcp6_option_append_pd(opt, optlen, &client->ia_pd);
|
||||
r = dhcp6_option_append_pd(opt, optlen, &client->ia_pd, &client->hint_pd_prefix);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
@ -530,7 +547,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
|
|||
}
|
||||
|
||||
if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) {
|
||||
r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd);
|
||||
r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
@ -556,7 +573,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
|
|||
}
|
||||
|
||||
if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) {
|
||||
r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd);
|
||||
r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
@ -1537,6 +1554,8 @@ int sd_dhcp6_client_new(sd_dhcp6_client **ret) {
|
|||
.request = DHCP6_REQUEST_IA_NA,
|
||||
.fd = -1,
|
||||
.req_opts_len = ELEMENTSOF(default_req_opts),
|
||||
.hint_pd_prefix.iapdprefix.lifetime_preferred = (be32_t) -1,
|
||||
.hint_pd_prefix.iapdprefix.lifetime_valid = (be32_t) -1,
|
||||
.req_opts = TAKE_PTR(req_opts),
|
||||
};
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#include "in-addr-util.h"
|
||||
#include "networkd-dhcp-common.h"
|
||||
#include "networkd-network.h"
|
||||
#include "parse-util.h"
|
||||
|
@ -227,6 +228,41 @@ int config_parse_iaid(const char *unit,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_dhcp6_pd_hint(
|
||||
const char* unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
Network *network = data;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
r = in_addr_prefix_from_string(rvalue, AF_INET6, (union in_addr_union *) &network->dhcp6_pd_address, &network->dhcp6_pd_length);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse PrefixDelegationHint=%s, ignoring assignment", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (network->dhcp6_pd_length < 1 || network->dhcp6_pd_length > 128) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid prefix length='%d', ignoring assignment", network->dhcp6_pd_length);
|
||||
network->dhcp6_pd_length = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains, dhcp_use_domains, DHCPUseDomains,
|
||||
"Failed to parse DHCP use domains setting");
|
||||
|
||||
|
|
|
@ -34,3 +34,4 @@ CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_ntp);
|
|||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_sip);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_iaid);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_section_route_table);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_pd_hint);
|
||||
|
|
|
@ -686,6 +686,12 @@ int dhcp6_configure(Link *link) {
|
|||
return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set prefix delegation: %m");
|
||||
}
|
||||
|
||||
if (link->network->dhcp6_pd_length > 0) {
|
||||
r = sd_dhcp6_client_set_prefix_delegation_hint(client, link->network->dhcp6_pd_length, &link->network->dhcp6_pd_address);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set prefix hint: %m");
|
||||
}
|
||||
|
||||
link->dhcp6_client = TAKE_PTR(client);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -172,6 +172,7 @@ DHCPv6.UseDNS, config_parse_bool,
|
|||
DHCPv6.UseNTP, config_parse_bool, 0, offsetof(Network, dhcp6_use_ntp)
|
||||
DHCPv6.RapidCommit, config_parse_bool, 0, offsetof(Network, rapid_commit)
|
||||
DHCPv6.ForceDHCPv6PDOtherInformation, config_parse_bool, 0, offsetof(Network, dhcp6_force_pd_other_information)
|
||||
DHCPv6.PrefixDelegationHint, config_parse_dhcp6_pd_hint, 0, 0
|
||||
IPv6AcceptRA.UseAutonomousPrefix, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_autonomous_prefix)
|
||||
IPv6AcceptRA.UseOnLinkPrefix, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_onlink_prefix)
|
||||
IPv6AcceptRA.UseDNS, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_dns)
|
||||
|
|
|
@ -109,6 +109,8 @@ struct Network {
|
|||
/* DHCPv6 Client support*/
|
||||
bool dhcp6_use_dns;
|
||||
bool dhcp6_use_ntp;
|
||||
uint8_t dhcp6_pd_length;
|
||||
struct in6_addr dhcp6_pd_address;
|
||||
|
||||
/* DHCP Server Support */
|
||||
bool dhcp_server;
|
||||
|
|
|
@ -120,6 +120,10 @@ int sd_dhcp6_client_get_information_request(
|
|||
int sd_dhcp6_client_set_request_option(
|
||||
sd_dhcp6_client *client,
|
||||
uint16_t option);
|
||||
int sd_dhcp6_client_set_prefix_delegation_hint(
|
||||
sd_dhcp6_client *client,
|
||||
uint8_t prefixlen,
|
||||
const struct in6_addr *pd_address);
|
||||
int sd_dhcp6_client_get_prefix_delegation(sd_dhcp6_client *client,
|
||||
int *delegation);
|
||||
int sd_dhcp6_client_set_prefix_delegation(sd_dhcp6_client *client,
|
||||
|
|
|
@ -99,6 +99,7 @@ UseNTP=
|
|||
UseDNS=
|
||||
RapidCommit=
|
||||
ForceDHCPv6PDOtherInformation=
|
||||
PrefixDelegationHint=
|
||||
[Route]
|
||||
Destination=
|
||||
Protocol=
|
||||
|
|
Loading…
Reference in a new issue