summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSusant Sahani <ssahani@vmware.com>2020-06-10 04:57:35 +0200
committerYu Watanabe <watanabe.yu+github@gmail.com>2020-06-17 14:20:48 +0900
commit120b5c0bbead6f635eeebce0a47ec5a777560f74 (patch)
treef051753905d5fc514ae62a029265118e37bbb25a
parent8d2d64166e1bb5978b5392b2787d1dd8feb63c16 (diff)
downloadsystemd-120b5c0bbead6f635eeebce0a47ec5a777560f74.tar.gz
network: DHCPv6 - Add support to set token on the LAN interface
This patch adds support to set a token on the LAN interface for the acquired delegated prefixes for the DHCPv6 to generate address.
-rw-r--r--man/systemd.network.xml10
-rw-r--r--src/network/networkd-dhcp6.c98
-rw-r--r--src/network/networkd-dhcp6.h1
-rw-r--r--src/network/networkd-network-gperf.gperf1
-rw-r--r--src/network/networkd-network.h1
-rw-r--r--test/fuzz/fuzz-network-parser/directives.network1
6 files changed, 88 insertions, 24 deletions
diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index ae93a39eb4..851570e723 100644
--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -1820,6 +1820,16 @@
</varlistentry>
<varlistentry>
+ <term><varname>AssignAcquiredDelegatedPrefixToken=</varname></term>
+ <listitem>
+ <para>Specifies an optional address generation mode for <varname>AssignAcquiredDelegatedPrefixAddress=</varname>.
+ Takes an IPv6 address. When set, the lower bits of the supplied address are combined with the upper bits of a
+ delegatad prefix received from the WAN interface by the <varname>IPv6PrefixDelegation=</varname> prefixes to
+ form a complete address.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><varname>PrefixDelegationHint=</varname></term>
<listitem>
<para>Takes an IPv6 address with prefix length as <varname>Address=</varname> in
diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c
index f86fdc2103..f0766f0af7 100644
--- a/src/network/networkd-dhcp6.c
+++ b/src/network/networkd-dhcp6.c
@@ -55,23 +55,25 @@ static int dhcp6_get_preferred_delegated_prefix(
const struct in6_addr *pd_prefix,
uint8_t pd_prefix_len,
struct in6_addr *ret_addr) {
- int r;
- union in_addr_union pd_prefix_union = {
- .in6 = *pd_prefix,
- };
- int64_t subnet_id = link->network->router_prefix_subnet_id;
-
- assert(pd_prefix_len <= 64);
+ int64_t subnet_id = link->network->router_prefix_subnet_id;
uint8_t prefix_bits = 64 - pd_prefix_len;
uint64_t n_prefixes = UINT64_C(1) << prefix_bits;
_cleanup_free_ char *assigned_buf = NULL;
-
+ union in_addr_union pd_prefix_union = {
+ .in6 = *pd_prefix,
+ };
/* We start off with the original PD prefix we have been assigned and
* iterate from there */
union in_addr_union prefix = {
.in6 = *pd_prefix,
};
+ int r;
+
+ assert(pd_prefix_len <= 64);
+ assert(manager);
+ assert(link);
+ assert(link->network);
if (subnet_id >= 0) {
/* If the link has a preference for a particular subnet id try to allocate that */
@@ -222,11 +224,11 @@ static int dhcp6_route_remove_handler(sd_netlink *nl, sd_netlink_message *m, Lin
}
int dhcp6_lease_pd_prefix_lost(sd_dhcp6_client *client, Link* link) {
- int r;
- sd_dhcp6_lease *lease;
+ uint32_t lifetime_preferred, lifetime_valid;
union in_addr_union pd_prefix;
uint8_t pd_prefix_len;
- uint32_t lifetime_preferred, lifetime_valid;
+ sd_dhcp6_lease *lease;
+ int r;
r = sd_dhcp6_client_get_lease(client, &lease);
if (r < 0)
@@ -275,17 +277,17 @@ static int dhcp6_pd_prefix_distribute(Link *dhcp6_link,
uint32_t lifetime_preferred,
uint32_t lifetime_valid,
bool assign_preferred_subnet_id) {
- Iterator i;
- Link *link;
+
+ _cleanup_free_ char *assigned_buf = NULL, *buf = NULL;
Manager *manager = dhcp6_link->manager;
union in_addr_union prefix = {
.in6 = *pd_prefix,
};
+ bool pool_depleted = false;
uint64_t n_prefixes;
- _cleanup_free_ char *buf = NULL;
- _cleanup_free_ char *assigned_buf = NULL;
+ Iterator i;
+ Link *link;
int r;
- bool pool_depleted = false;
assert(manager);
assert(pd_prefix_len <= 64);
@@ -364,11 +366,11 @@ static int dhcp6_route_handler(sd_netlink *nl, sd_netlink_message *m, Link *link
}
static int dhcp6_lease_pd_prefix_acquired(sd_dhcp6_client *client, Link *link) {
- int r;
- sd_dhcp6_lease *lease;
+ uint32_t lifetime_preferred, lifetime_valid;
union in_addr_union pd_prefix;
+ sd_dhcp6_lease *lease;
uint8_t pd_prefix_len;
- uint32_t lifetime_preferred, lifetime_valid;
+ int r;
r = sd_dhcp6_client_get_lease(client, &lease);
if (r < 0)
@@ -1045,6 +1047,7 @@ static int dhcp6_assign_delegated_prefix(Link *link,
uint8_t prefix_len,
uint32_t lifetime_preferred,
uint32_t lifetime_valid) {
+
_cleanup_(address_freep) Address *address = NULL;
int r;
@@ -1057,12 +1060,17 @@ static int dhcp6_assign_delegated_prefix(Link *link,
r = address_new(&address);
if (r < 0)
- return log_link_error_errno(link, r, "Could not allocate address: %m");
+ return log_link_error_errno(link, r, "Failed to allocate address for DHCPv6 delegated prefix: %m");
address->in_addr.in6 = *prefix;
- r = generate_ipv6_eui_64_address(link, &address->in_addr.in6);
- if (r < 0)
- return log_link_warning_errno(link, r, "Failed to generate EUI64 address for DHCPv6 acquired delegated prefix: %m");
+
+ if (!in_addr_is_null(AF_INET6, &link->network->dhcp6_delegation_prefix_token))
+ memcpy(&address->in_addr.in6.s6_addr + 8, &link->network->dhcp6_delegation_prefix_token.in6.s6_addr + 8, 8);
+ else {
+ r = generate_ipv6_eui_64_address(link, &address->in_addr.in6);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Failed to generate EUI64 address for acquired DHCPv6 delegated prefix: %m");
+ }
address->prefixlen = prefix_len;
address->family = AF_INET6;
@@ -1073,7 +1081,7 @@ static int dhcp6_assign_delegated_prefix(Link *link,
r = address_configure(address, link, address_handler, true);
if (r < 0)
- return log_link_warning_errno(link, r, "Could not set addresses: %m");
+ return log_link_warning_errno(link, r, "Failed to set acquired DHCPv6 delegated prefix address: %m");
if (r > 0)
link->address_messages++;
@@ -1126,6 +1134,7 @@ int config_parse_dhcp6_mud_url(
const char *rvalue,
void *data,
void *userdata) {
+
_cleanup_free_ char *unescaped = NULL;
Network *network = data;
int r;
@@ -1155,3 +1164,44 @@ int config_parse_dhcp6_mud_url(
return free_and_replace(network->dhcp6_mudurl, unescaped);
}
+
+int config_parse_dhcp6_delegated_prefix_token(
+ 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);
+
+ if (isempty(rvalue)) {
+ network->dhcp6_delegation_prefix_token = IN_ADDR_NULL;
+ return 0;
+ }
+
+ r = in_addr_from_string(AF_INET6, rvalue, &network->dhcp6_delegation_prefix_token);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Failed to parse DHCPv6 %s, ignoring: %s", lvalue, rvalue);
+ return 0;
+ }
+
+ if (in_addr_is_null(AF_INET6, &network->dhcp6_delegation_prefix_token)) {
+ log_syntax(unit, LOG_ERR, filename, line, 0,
+ "DHCPv6 %s cannot be the ANY address, ignoring: %s", lvalue, rvalue);
+ return 0;
+ }
+
+ return 0;
+}
diff --git a/src/network/networkd-dhcp6.h b/src/network/networkd-dhcp6.h
index e7c180897b..913410fe77 100644
--- a/src/network/networkd-dhcp6.h
+++ b/src/network/networkd-dhcp6.h
@@ -16,3 +16,4 @@ int dhcp6_prefix_remove(Manager *m, struct in6_addr *addr);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_pd_hint);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_mud_url);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_delegated_prefix_token);
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index 5c2a4d36a1..84ea5d552e 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -203,6 +203,7 @@ DHCPv6.VendorClass, config_parse_dhcp_vendor_class,
DHCPv6.SendVendorOption, config_parse_dhcp_send_option, AF_INET6, offsetof(Network, dhcp6_client_send_vendor_options)
DHCPv6.ForceDHCPv6PDOtherInformation, config_parse_bool, 0, offsetof(Network, dhcp6_force_pd_other_information)
DHCPv6.AssignAcquiredDelegatedPrefixAddress, config_parse_bool, 0, offsetof(Network, dhcp6_pd_assign_prefix)
+DHCPv6.AssignAcquiredDelegatedPrefixToken, config_parse_dhcp6_delegated_prefix_token, 0, 0
DHCPv6.PrefixDelegationHint, config_parse_dhcp6_pd_hint, 0, 0
DHCPv6.WithoutRA, config_parse_bool, 0, offsetof(Network, dhcp6_without_ra)
DHCPv6.SendOption, config_parse_dhcp_send_option, AF_INET6, offsetof(Network, dhcp6_client_send_options)
diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
index 5901622862..00ecac6ca9 100644
--- a/src/network/networkd-network.h
+++ b/src/network/networkd-network.h
@@ -201,6 +201,7 @@ struct Network {
RA flag is set, see RFC 7084,
WPD-4 */
bool dhcp6_pd_assign_prefix;
+ union in_addr_union dhcp6_delegation_prefix_token;
/* Bridge Support */
int use_bpdu;
diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network
index 478b574418..a6ef817360 100644
--- a/test/fuzz/fuzz-network-parser/directives.network
+++ b/test/fuzz/fuzz-network-parser/directives.network
@@ -120,6 +120,7 @@ RequestOptions=
UserClass=
VendorClass=
AssignAcquiredDelegatedPrefixAddress=
+AssignAcquiredDelegatedPrefixToken=
SendVendorOption=
RouteMetric=
[Route]