Merge pull request #21625 from yuwata/network-dhcp-6rd

network: dhcp: add 6rd support
This commit is contained in:
Zbigniew Jędrzejewski-Szmek
2021-12-07 17:26:37 +01:00
committed by GitHub
44 changed files with 1333 additions and 317 deletions

View File

@@ -854,18 +854,19 @@ Table=1234</programlisting></para>
<listitem><para>Whether to enable or disable Router Advertisement sending on a link. Takes a
boolean value. When enabled, prefixes configured in [IPv6Prefix] sections and routes
configured in [IPv6RoutePrefix] sections are distributed as defined in the [IPv6SendRA]
section. If <varname>DHCPv6PrefixDelegation=</varname> is enabled, then the delegated
prefixes are also distributed. See <varname>DHCPv6PrefixDelegation=</varname> setting and the
[IPv6SendRA], [IPv6Prefix], [IPv6RoutePrefix], and [DHCPv6PrefixDelegation] sections for more
section. If <varname>DHCPPrefixDelegation=</varname> is enabled, then the delegated prefixes
are also distributed. See <varname>DCHPPrefixDelegation=</varname> setting and the
[IPv6SendRA], [IPv6Prefix], [IPv6RoutePrefix], and [DHCPPrefixDelegation] sections for more
configuration options.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>DHCPv6PrefixDelegation=</varname></term>
<listitem><para>Takes a boolean value. When enabled, requests prefixes using a DHCPv6 client
configured on another link. By default, an address within each delegated prefix will be
assigned, and the prefixes will be announced through IPv6 Router Advertisement when
<varname>IPv6SendRA=</varname> is enabled. Such default settings can be configured in
[DHCPv6PrefixDelegation] section. Defaults to disabled.</para></listitem>
<term><varname>DHCPPrefixDelegation=</varname></term>
<listitem><para>Takes a boolean value. When enabled, requests subnet prefixes acquired by a
DHCPv6 client, or by a DHCPv4 client through the 6RD option configured on another link. By
default, an address within each delegated prefix will be assigned, and the prefixes will be
announced through IPv6 Router Advertisement when <varname>IPv6SendRA=</varname> is enabled.
Such default settings can be configured in [DHCPPrefixDelegation] section. Defaults to
disabled.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>IPv6MTUBytes=</varname></term>
@@ -1900,6 +1901,15 @@ Table=1234</programlisting></para>
the local system. Defaults to false.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>Use6RD=</varname></term>
<listitem><para>When true, subnets of the received IPv6 prefix are assigned to downstream
interfaces which enables <varname>DHCPPrefixDelegation=</varname>. See also
<varname>DHCPPrefixDelegation=</varname> in the [Network] section, the [DHCPPrefixDelegation]
section, and <ulink url="https://tools.ietf.org/html/rfc5969">RFC 5969</ulink>. Defaults to
false.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>FallbackLeaseLifetimeSec=</varname></term>
<listitem>
@@ -2076,9 +2086,9 @@ Table=1234</programlisting></para>
<listitem>
<para>When true (the default), the client will request the DHCPv6 server to delegate
prefixes. If the server provides prefixes to be delegated, then subnets of the prefixes are
assigned to the interfaces which enables <varname>DHCPv6PrefixDelegation=</varname>.
See also <varname>DHCPv6PrefixDelegation=</varname> in [Network] section,
[DHCPv6PrefixDelegation] section, and
assigned to the interfaces which enables <varname>DHCPPrefixDelegation=</varname>.
See also <varname>DHCPPrefixDelegation=</varname> in [Network] section,
[DHCPPrefixDelegation] section, and
<ulink url="https://www.rfc-editor.org/rfc/rfc8415.html#section-6.3">RFC 8415</ulink>.
</para>
</listitem>
@@ -2102,9 +2112,9 @@ Table=1234</programlisting></para>
<para>Allows DHCPv6 client to start without router advertisements's managed or other
address configuration flag. Takes one of <literal>no</literal>, <literal>solicit</literal>
or <literal>information-request</literal>. If this is not specified,
<literal>solicit</literal> is used when <varname>DHCPv6PrefixDelegation=</varname> is
<literal>solicit</literal> is used when <varname>DHCPPrefixDelegation=</varname> is
enabled and <varname>UplinkInterface=:self</varname> is specified in the
[DHCPv6PrefixDelegation] section. Otherwise, defaults to <literal>no</literal>, and the
[DHCPPrefixDelegation] section. Otherwise, defaults to <literal>no</literal>, and the
DHCPv6 client will be started when an RA is received. See also
<varname>DHCPv6Client=</varname> setting in the [IPv6AcceptRA] section.</para>
</listitem>
@@ -2113,10 +2123,11 @@ Table=1234</programlisting></para>
</refsect1>
<refsect1>
<title>[DHCPv6PrefixDelegation] Section Options</title>
<para>The [DHCPv6PrefixDelegation] section configures delegated prefixes assigned by DHCPv6 server.
The settings in this section are used only when <varname>DHCPv6PrefixDelegation=</varname> setting
is enabled.</para>
<title>[DHCPPrefixDelegation] Section Options</title>
<para>The [DHCPPrefixDelegation] section configures subnet prefixes of the delegated prefixes
acquired by a DHCPv6 client, or by a DHCPv4 client through the 6RD option on another interface.
The settings in this section are used only when the <varname>DHCPPrefixDelegation=</varname>
setting in the [Network] section is enabled.</para>
<variablelist class='network-directives'>
<varlistentry>
@@ -2127,7 +2138,7 @@ Table=1234</programlisting></para>
interface itself is considered the uplink interface, and
<varname>WithoutRA=solicit</varname> is implied if the setting is not explicitly specified.
When <literal>:auto</literal>, the first link which acquired prefixes to be delegated from
the DHCPv6 server is selected. Defaults to <literal>:auto</literal>.</para>
the DHCPv6 or DHCPv4 server is selected. Defaults to <literal>:auto</literal>.</para>
</listitem>
</varlistentry>
@@ -2147,7 +2158,8 @@ Table=1234</programlisting></para>
<listitem>
<para>Takes a boolean. When enabled, and <varname>IPv6SendRA=</varname> in [Network] section
is enabled, the delegated prefixes are distributed through the IPv6 Router Advertisement.
Defaults to yes.</para>
This setting will be ignored when the <varname>DHCPPrefixDelegation=</varname> setting is
enabled on the upstream interface. Defaults to yes.</para>
</listitem>
</varlistentry>
@@ -2436,7 +2448,7 @@ Token=prefixstable:2002:da8:1::</programlisting></para>
to <literal>always</literal>, the DHCPv6 client will be started in managed mode when an RA
is received, even if neither managed nor other information flag is set in the RA. This will
be ignored when <varname>WithoutRA=</varname> in the [DHCPv6] section is enabled, or
<varname>UplinkInterface=:self</varname> in the [DHCPv6PrefixDelegation] section is
<varname>UplinkInterface=:self</varname> in the [DHCPPrefixDelegation] section is
specified. Defaults to true.</para>
</listitem>
</varlistentry>
@@ -2710,8 +2722,8 @@ Token=prefixstable:2002:da8:1::</programlisting></para>
values <literal>:none</literal> and <literal>:auto</literal>. When emitting DNS servers or
search domains is enabled but no servers are specified, the servers configured in the uplink
interface will be emitted. When <literal>:auto</literal>, the value specified to the same
setting in the [DHCPv6PrefixDelegation] section will be used if
<varname>DHCPv6PrefixDelegation=</varname> is enabled, otherwise the link which has a default
setting in the [DHCPPrefixDelegation] section will be used if
<varname>DHCPPrefixDelegation=</varname> is enabled, otherwise the link which has a default
gateway with the highest priority will be automatically selected. When <literal>:none</literal>,
no uplink interface will be selected. Defaults to <literal>:auto</literal>.</para></listitem>
</varlistentry>
@@ -4375,7 +4387,7 @@ Name=enp2s0
[Network]
IPv6SendRA=yes
DHCPv6PrefixDelegation=yes</programlisting>
DHCPPrefixDelegation=yes</programlisting>
<para>This will enable DHCPv6-PD on the interface enp1s0 as an upstream interface where the
DHCPv6 client is running and enp2s0 as a downstream interface where the prefix is delegated to.

View File

@@ -0,0 +1,18 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
# This network file matches 6rd-* SIT devices which is automatically created by
# systemd-networkd when DHCPv4 6RD option is received.
[Match]
Name=6rd-*
Type=sit
[Network]
DHCPPrefixDelegation=yes

View File

@@ -1,7 +1,8 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
if conf.get('ENABLE_NETWORKD') == 1
install_data('80-container-host0.network',
install_data('80-6rd-tunnel.network',
'80-container-host0.network',
'80-container-ve.network',
'80-container-vz.network',
'80-vm-vt.network',

View File

@@ -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);
};

View File

@@ -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)

View File

@@ -8,9 +8,12 @@
#include <linux/ip6_tunnel.h>
#include "conf-parser.h"
#include "hexdecoct.h"
#include "missing_network.h"
#include "netlink-util.h"
#include "networkd-manager.h"
#include "parse-util.h"
#include "siphash24.h"
#include "string-table.h"
#include "string-util.h"
#include "tunnel.h"
@@ -29,6 +32,146 @@ static const char* const ip6tnl_mode_table[_NETDEV_IP6_TNL_MODE_MAX] = {
DEFINE_STRING_TABLE_LOOKUP(ip6tnl_mode, Ip6TnlMode);
DEFINE_CONFIG_PARSE_ENUM(config_parse_ip6tnl_mode, ip6tnl_mode, Ip6TnlMode, "Failed to parse ip6 tunnel Mode");
#define HASH_KEY SD_ID128_MAKE(74,c4,de,12,f3,d9,41,34,bb,3d,c1,a4,42,93,50,87)
int dhcp4_pd_create_6rd_tunnel_name(Link *link, char **ret) {
_cleanup_free_ char *ifname_alloc = NULL;
uint8_t ipv4masklen, sixrd_prefixlen, *buf, *p;
struct in_addr ipv4address;
struct in6_addr sixrd_prefix;
char ifname[IFNAMSIZ];
uint64_t result;
size_t sz;
int r;
assert(link);
assert(link->dhcp_lease);
r = sd_dhcp_lease_get_address(link->dhcp_lease, &ipv4address);
if (r < 0)
return log_link_debug_errno(link, r, "Failed to get DHCPv4 address: %m");
r = sd_dhcp_lease_get_6rd(link->dhcp_lease, &ipv4masklen, &sixrd_prefixlen, &sixrd_prefix, NULL, NULL);
if (r < 0)
return log_link_debug_errno(link, r, "Failed to get 6rd option: %m");
sz = sizeof(uint8_t) * 2 + sizeof(struct in6_addr) + sizeof(struct in_addr);
buf = newa(uint8_t, sz);
p = buf;
p = mempcpy(p, &ipv4masklen, sizeof(uint8_t));
p = mempcpy(p, &ipv4address, sizeof(struct in_addr));
p = mempcpy(p, &sixrd_prefixlen, sizeof(uint8_t));
p = mempcpy(p, &sixrd_prefix, sizeof(struct in6_addr));
result = siphash24(buf, sz, HASH_KEY.bytes);
memcpy(ifname, "6rd-", STRLEN("6rd-"));
ifname[STRLEN("6rd-") ] = urlsafe_base64char(result >> 54);
ifname[STRLEN("6rd-") + 1] = urlsafe_base64char(result >> 48);
ifname[STRLEN("6rd-") + 2] = urlsafe_base64char(result >> 42);
ifname[STRLEN("6rd-") + 3] = urlsafe_base64char(result >> 36);
ifname[STRLEN("6rd-") + 4] = urlsafe_base64char(result >> 30);
ifname[STRLEN("6rd-") + 5] = urlsafe_base64char(result >> 24);
ifname[STRLEN("6rd-") + 6] = urlsafe_base64char(result >> 18);
ifname[STRLEN("6rd-") + 7] = urlsafe_base64char(result >> 12);
ifname[STRLEN("6rd-") + 8] = urlsafe_base64char(result >> 6);
ifname[STRLEN("6rd-") + 9] = urlsafe_base64char(result);
ifname[STRLEN("6rd-") + 10] = '\0';
assert_cc(STRLEN("6rd-") + 10 <= IFNAMSIZ);
ifname_alloc = strdup(ifname);
if (!ifname_alloc)
return log_oom_debug();
*ret = TAKE_PTR(ifname_alloc);
return 0;
}
int dhcp4_pd_create_6rd_tunnel(Link *link, link_netlink_message_handler_t callback) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
uint8_t ipv4masklen, sixrd_prefixlen;
struct in_addr ipv4address, relay_prefix;
struct in6_addr sixrd_prefix;
int r;
assert(link);
assert(link->ifindex > 0);
assert(link->manager);
assert(link->dhcp_lease);
assert(link->dhcp4_6rd_tunnel_name);
assert(callback);
r = sd_dhcp_lease_get_address(link->dhcp_lease, &ipv4address);
if (r < 0)
return log_link_debug_errno(link, r, "Failed to get DHCPv4 address: %m");
r = sd_dhcp_lease_get_6rd(link->dhcp_lease, &ipv4masklen, &sixrd_prefixlen, &sixrd_prefix, NULL, NULL);
if (r < 0)
return log_link_debug_errno(link, r, "Failed to get 6rd option: %m");
r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_NEWLINK, 0);
if (r < 0)
return log_link_debug_errno(link, r, "Could not allocate RTM_NEWLINK message: %m");
r = sd_netlink_message_append_string(m, IFLA_IFNAME, link->dhcp4_6rd_tunnel_name);
if (r < 0)
return log_link_debug_errno(link, r, "Could not append IFLA_IFNAME, attribute: %m");
r = sd_netlink_message_open_container(m, IFLA_LINKINFO);
if (r < 0)
return log_link_debug_errno(link, r, "Could not append IFLA_LINKINFO attribute: %m");
r = sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, "sit");
if (r < 0)
return log_link_debug_errno(link, r, "Could not append IFLA_INFO_DATA attribute: %m");
r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex);
if (r < 0)
return log_link_debug_errno(link, r, "Could not append IFLA_IPTUN_LINK attribute: %m");
r = sd_netlink_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &ipv4address);
if (r < 0)
return log_link_debug_errno(link, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m");
r = sd_netlink_message_append_u8(m, IFLA_IPTUN_TTL, 64);
if (r < 0)
return log_link_debug_errno(link, r, "Could not append IFLA_IPTUN_TTL attribute: %m");
r = sd_netlink_message_append_in6_addr(m, IFLA_IPTUN_6RD_PREFIX, &sixrd_prefix);
if (r < 0)
return log_link_debug_errno(link, r, "Could not append IFLA_IPTUN_6RD_PREFIX attribute: %m");
r = sd_netlink_message_append_u16(m, IFLA_IPTUN_6RD_PREFIXLEN, sixrd_prefixlen);
if (r < 0)
return log_link_debug_errno(link, r, "Could not append IFLA_IPTUN_6RD_PREFIXLEN attribute: %m");
relay_prefix = ipv4address;
(void) in4_addr_mask(&relay_prefix, ipv4masklen);
r = sd_netlink_message_append_u32(m, IFLA_IPTUN_6RD_RELAY_PREFIX, relay_prefix.s_addr);
if (r < 0)
return log_link_debug_errno(link, r, "Could not append IFLA_IPTUN_6RD_RELAY_PREFIX attribute: %m");
r = sd_netlink_message_append_u16(m, IFLA_IPTUN_6RD_RELAY_PREFIXLEN, ipv4masklen);
if (r < 0)
return log_link_debug_errno(link, r, "Could not append IFLA_IPTUN_6RD_RELAY_PREFIXLEN attribute: %m");
r = sd_netlink_message_close_container(m);
if (r < 0)
return log_link_debug_errno(link, r, "Could not append IFLA_INFO_DATA attribute: %m");
r = sd_netlink_message_close_container(m);
if (r < 0)
return log_link_debug_errno(link, r, "Could not append IFLA_LINKINFO attribute: %m");
r = netlink_call_async(link->manager->rtnl, NULL, m, callback,
link_netlink_destroy_callback, link);
if (r < 0)
return log_link_debug_errno(link, r, "Could not send rtnetlink message: %m");
link_ref(link);
return 0;
}
static int netdev_ipip_sit_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
Tunnel *t;
int r;

View File

@@ -6,6 +6,7 @@
#include "conf-parser.h"
#include "fou-tunnel.h"
#include "netdev.h"
#include "networkd-link.h"
typedef enum Ip6TnlMode {
NETDEV_IP6_TNL_MODE_IP6IP6,
@@ -60,6 +61,9 @@ typedef struct Tunnel {
uint8_t sixrd_prefixlen;
} Tunnel;
int dhcp4_pd_create_6rd_tunnel_name(Link *link, char **ret);
int dhcp4_pd_create_6rd_tunnel(Link *link, link_netlink_message_handler_t callback);
DEFINE_NETDEV_CAST(IPIP, Tunnel);
DEFINE_NETDEV_CAST(GRE, Tunnel);
DEFINE_NETDEV_CAST(GRETAP, Tunnel);

View File

@@ -22,7 +22,7 @@
#define RESERVED_SUBNET_ANYCAST_ADDRESSES ((const struct in6_addr) { .s6_addr = { 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80 } })
#define RESERVED_SUBNET_ANYCAST_PREFIXLEN 57
#define DHCP6PD_APP_ID SD_ID128_MAKE(fb,b9,37,ca,4a,ed,4a,4d,b0,70,7f,aa,71,c0,c9,85)
#define DHCP_PD_APP_ID SD_ID128_MAKE(fb,b9,37,ca,4a,ed,4a,4d,b0,70,7f,aa,71,c0,c9,85)
#define NDISC_APP_ID SD_ID128_MAKE(13,ac,81,a7,d5,3f,49,78,92,79,5d,0c,29,3a,bc,7e)
#define RADV_APP_ID SD_ID128_MAKE(1f,1e,90,c8,5c,78,4f,dc,8e,61,2d,59,0d,53,c1,25)
@@ -252,8 +252,8 @@ static int generate_addresses(
return 0;
}
int dhcp6_pd_generate_addresses(Link *link, const struct in6_addr *prefix, uint8_t prefixlen, Set **ret) {
return generate_addresses(link, link->network->dhcp6_pd_tokens, &DHCP6PD_APP_ID, prefix, prefixlen, ret);
int dhcp_pd_generate_addresses(Link *link, const struct in6_addr *prefix, uint8_t prefixlen, Set **ret) {
return generate_addresses(link, link->network->dhcp_pd_tokens, &DHCP_PD_APP_ID, prefix, prefixlen, ret);
}
int ndisc_generate_addresses(Link *link, const struct in6_addr *prefix, uint8_t prefixlen, Set **ret) {

View File

@@ -7,7 +7,7 @@
typedef struct Link Link;
int dhcp6_pd_generate_addresses(Link *link, const struct in6_addr *prefix, uint8_t prefixlen, Set **ret);
int dhcp_pd_generate_addresses(Link *link, const struct in6_addr *prefix, uint8_t prefixlen, Set **ret);
int ndisc_generate_addresses(Link *link, const struct in6_addr *prefix, uint8_t prefixlen, Set **ret);
int radv_generate_addresses(Link *link, Set *tokens, const struct in6_addr *prefix, uint8_t prefixlen, Set **ret);

View File

@@ -1267,9 +1267,9 @@ int config_parse_uplink(
} else if (streq(section, "IPv6SendRA")) {
index = &network->router_uplink_index;
name = &network->router_uplink_name;
} else if (streq(section, "DHCPv6PrefixDelegation")) {
index = &network->dhcp6_pd_uplink_index;
name = &network->dhcp6_pd_uplink_name;
} else if (STR_IN_SET(section, "DHCPv6PrefixDelegation", "DHCPPrefixDelegation")) {
index = &network->dhcp_pd_uplink_index;
name = &network->dhcp_pd_uplink_name;
accept_none = false;
} else
assert_not_reached();

File diff suppressed because it is too large Load Diff

View File

@@ -3,17 +3,23 @@
#include <stdbool.h>
#include "sd-dhcp-lease.h"
#include "sd-dhcp6-lease.h"
#include "conf-parser.h"
typedef struct Link Link;
bool link_dhcp6_pd_is_enabled(Link *link);
bool dhcp6_pd_is_uplink(Link *link, Link *target, bool accept_auto);
int dhcp6_pd_find_uplink(Link *link, Link **ret);
bool link_dhcp_pd_is_enabled(Link *link);
bool dhcp_pd_is_uplink(Link *link, Link *target, bool accept_auto);
int dhcp_pd_find_uplink(Link *link, Link **ret);
bool dhcp4_lease_has_pd_prefix(sd_dhcp_lease *lease);
bool dhcp6_lease_has_pd_prefix(sd_dhcp6_lease *lease);
int dhcp6_pd_remove(Link *link, bool only_marked);
int dhcp6_request_prefix_delegation(Link *link);
int dhcp6_pd_prefix_acquired(Link *dhcp6_link);
void dhcp6_pd_prefix_lost(Link *dhcp6_link);
int dhcp_pd_remove(Link *link, bool only_marked);
int dhcp_request_prefix_delegation(Link *link);
int dhcp4_pd_prefix_acquired(Link *uplink);
int dhcp6_pd_prefix_acquired(Link *uplink);
void dhcp_pd_prefix_lost(Link *uplink);
void dhcp4_pd_prefix_lost(Link *uplink);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_pd_subnet_id);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_pd_subnet_id);

View File

@@ -12,6 +12,7 @@
#include "parse-util.h"
#include "network-internal.h"
#include "networkd-address.h"
#include "networkd-dhcp-prefix-delegation.h"
#include "networkd-dhcp4.h"
#include "networkd-ipv4acd.h"
#include "networkd-link.h"
@@ -27,7 +28,6 @@
#include "sysctl-util.h"
static int dhcp4_request_address_and_routes(Link *link, bool announce);
static int dhcp4_check_ready(Link *link);
void network_adjust_dhcp4(Network *network) {
assert(network);
@@ -119,7 +119,7 @@ static int dhcp4_address_ready_callback(Address *address) {
return dhcp4_check_ready(address->link);
}
static int dhcp4_check_ready(Link *link) {
int dhcp4_check_ready(Link *link) {
Address *address;
int r;
@@ -789,11 +789,16 @@ int dhcp4_lease_lost(Link *link) {
assert(link);
assert(link->dhcp_lease);
assert(link->network);
log_link_info(link, "DHCP lease lost");
link->dhcp4_configured = false;
if (link->network->dhcp_use_6rd &&
dhcp4_lease_has_pd_prefix(link->dhcp_lease))
dhcp4_pd_prefix_lost(link);
k = dhcp4_remove_address_and_routes(link, /* only_marked = */ false);
if (k < 0)
r = k;
@@ -964,20 +969,31 @@ static int dhcp4_request_address_and_routes(Link *link, bool announce) {
}
static int dhcp_lease_renew(sd_dhcp_client *client, Link *link) {
_cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *old_lease = NULL;
sd_dhcp_lease *lease;
int r;
assert(link);
assert(link->network);
assert(client);
r = sd_dhcp_client_get_lease(client, &lease);
if (r < 0)
return log_link_warning_errno(link, r, "DHCP error: no lease: %m");
sd_dhcp_lease_unref(link->dhcp_lease);
old_lease = TAKE_PTR(link->dhcp_lease);
link->dhcp_lease = sd_dhcp_lease_ref(lease);
link_dirty(link);
if (link->network->dhcp_use_6rd) {
if (dhcp4_lease_has_pd_prefix(link->dhcp_lease)) {
r = dhcp4_pd_prefix_acquired(link);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to process 6rd option: %m");
} else if (dhcp4_lease_has_pd_prefix(old_lease))
dhcp4_pd_prefix_lost(link);
}
return dhcp4_request_address_and_routes(link, false);
}
@@ -1043,6 +1059,13 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
}
}
if (link->network->dhcp_use_6rd &&
dhcp4_lease_has_pd_prefix(link->dhcp_lease)) {
r = dhcp4_pd_prefix_acquired(link);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to process 6rd option: %m");
}
return dhcp4_request_address_and_routes(link, true);
}
@@ -1439,6 +1462,12 @@ static int dhcp4_configure(Link *link) {
return log_link_debug_errno(link, r, "DHCPv4 CLIENT: Failed to set request flag for timezone: %m");
}
if (link->network->dhcp_use_6rd) {
r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_6RD);
if (r < 0)
return log_link_debug_errno(link, r, "DHCPv4 CLIENT: Failed to set request flag for 6rd: %m");
}
SET_FOREACH(request_options, link->network->dhcp_request_options) {
uint32_t option = PTR_TO_UINT32(request_options);

View File

@@ -23,6 +23,7 @@ void network_adjust_dhcp4(Network *network);
int dhcp4_update_mac(Link *link);
int dhcp4_start(Link *link);
int dhcp4_lease_lost(Link *link);
int dhcp4_check_ready(Link *link);
int request_process_dhcp4_client(Request *req);
int link_request_dhcp4_client(Link *link);

View File

@@ -36,7 +36,7 @@ static DHCP6ClientStartMode link_get_dhcp6_client_start_mode(Link *link) {
return link->network->dhcp6_client_start_mode;
/* When this interface itself is an uplink interface, then start dhcp6 client in managed mode. */
if (dhcp6_pd_is_uplink(link, link, /* accept_auto = */ false))
if (dhcp_pd_is_uplink(link, link, /* accept_auto = */ false))
return DHCP6_CLIENT_START_MODE_SOLICIT;
/* Otherwise, start dhcp6 client when RA is received. */
@@ -323,7 +323,7 @@ static int dhcp6_lease_ip_acquired(sd_dhcp6_client *client, Link *link) {
return r;
} else if (dhcp6_lease_has_pd_prefix(lease_old))
/* When we had PD prefixes but not now, we need to remove them. */
dhcp6_pd_prefix_lost(link);
dhcp_pd_prefix_lost(link);
if (link->dhcp6_messages == 0) {
link->dhcp6_configured = true;
@@ -354,7 +354,7 @@ static int dhcp6_lease_lost(Link *link) {
log_link_info(link, "DHCPv6 lease lost");
if (dhcp6_lease_has_pd_prefix(link->dhcp6_lease))
dhcp6_pd_prefix_lost(link);
dhcp_pd_prefix_lost(link);
link->dhcp6_lease = sd_dhcp6_lease_unref(link->dhcp6_lease);

View File

@@ -208,6 +208,7 @@ static void link_free_engines(Link *link) {
link->dhcp_server = sd_dhcp_server_unref(link->dhcp_server);
link->dhcp_client = sd_dhcp_client_unref(link->dhcp_client);
link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease);
link->dhcp4_6rd_tunnel_name = mfree(link->dhcp4_6rd_tunnel_name);
link->lldp_rx = sd_lldp_rx_unref(link->lldp_rx);
link->lldp_tx = sd_lldp_tx_unref(link->lldp_tx);
@@ -235,7 +236,7 @@ static Link *link_free(Link *link) {
link->addresses = set_free(link->addresses);
link->dhcp6_pd_prefixes = set_free(link->dhcp6_pd_prefixes);
link->dhcp_pd_prefixes = set_free(link->dhcp_pd_prefixes);
link_free_engines(link);
@@ -381,7 +382,7 @@ int link_stop_engines(Link *link, bool may_keep_dhcp) {
if (k < 0)
r = log_link_warning_errno(link, k, "Could not stop DHCPv6 client: %m");
k = dhcp6_pd_remove(link, /* only_marked = */ false);
k = dhcp_pd_remove(link, /* only_marked = */ false);
if (k < 0)
r = log_link_warning_errno(link, k, "Could not remove DHCPv6 PD addresses and routes: %m");
@@ -495,7 +496,7 @@ void link_check_ready(Link *link) {
NETWORK_CONFIG_SOURCE_IPV4LL,
NETWORK_CONFIG_SOURCE_DHCP4,
NETWORK_CONFIG_SOURCE_DHCP6,
NETWORK_CONFIG_SOURCE_DHCP6PD,
NETWORK_CONFIG_SOURCE_DHCP_PD,
NETWORK_CONFIG_SOURCE_NDISC)) {
has_dynamic_address = true;
break;
@@ -503,26 +504,26 @@ void link_check_ready(Link *link) {
}
if ((link_ipv4ll_enabled(link) || link_dhcp4_enabled(link) || link_dhcp6_with_address_enabled(link) ||
(link_dhcp6_pd_is_enabled(link) && link->network->dhcp6_pd_assign)) && !has_dynamic_address)
(link_dhcp_pd_is_enabled(link) && link->network->dhcp_pd_assign)) && !has_dynamic_address)
/* When DHCP[46] or IPv4LL is enabled, at least one address is acquired by them. */
return (void) log_link_debug(link, "%s(): DHCPv4, DHCPv6, DHCPv6PD or IPv4LL is enabled but no dynamic address is assigned yet.", __func__);
return (void) log_link_debug(link, "%s(): DHCPv4, DHCPv6, DHCP-PD or IPv4LL is enabled but no dynamic address is assigned yet.", __func__);
/* Ignore NDisc when ConfigureWithoutCarrier= is enabled, as IPv6AcceptRA= is enabled by default. */
if (link_ipv4ll_enabled(link) || link_dhcp4_enabled(link) ||
link_dhcp6_enabled(link) || link_dhcp6_pd_is_enabled(link) ||
link_dhcp6_enabled(link) || link_dhcp_pd_is_enabled(link) ||
(!link->network->configure_without_carrier && link_ipv6_accept_ra_enabled(link))) {
if (!link->ipv4ll_address_configured && !link->dhcp4_configured &&
!link->dhcp6_configured && !link->dhcp6_pd_configured && !link->ndisc_configured)
!link->dhcp6_configured && !link->dhcp_pd_configured && !link->ndisc_configured)
/* When DHCP[46], NDisc, or IPv4LL is enabled, at least one protocol must be finished. */
return (void) log_link_debug(link, "%s(): dynamic addresses or routes are not configured.", __func__);
log_link_debug(link, "%s(): IPv4LL:%s DHCPv4:%s DHCPv6:%s DHCPv6PD:%s NDisc:%s",
log_link_debug(link, "%s(): IPv4LL:%s DHCPv4:%s DHCPv6:%s DHCP-PD:%s NDisc:%s",
__func__,
yes_no(link->ipv4ll_address_configured),
yes_no(link->dhcp4_configured),
yes_no(link->dhcp6_configured),
yes_no(link->dhcp6_pd_configured),
yes_no(link->dhcp_pd_configured),
yes_no(link->ndisc_configured));
}
@@ -669,14 +670,14 @@ static int link_acquire_dynamic_conf(Link *link) {
return r;
}
if (!link_radv_enabled(link) || !link->network->dhcp6_pd_announce) {
if (!link_radv_enabled(link) || !link->network->dhcp_pd_announce) {
/* DHCPv6PD downstream does not require IPv6LL address. But may require RADV to be
* configured, and RADV may not be configured yet here. Only acquire subnet prefix when
* RADV is disabled, or the announcement of the prefix is disabled. Otherwise, the
* below will be called in radv_start(). */
r = dhcp6_request_prefix_delegation(link);
r = dhcp_request_prefix_delegation(link);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to request DHCPv6 prefix delegation: %m");
return log_link_warning_errno(link, r, "Failed to request DHCP delegated subnet prefix: %m");
}
if (link->lldp_tx) {

View File

@@ -114,6 +114,7 @@ typedef struct Link {
bool dhcp4_route_failed:1;
bool dhcp4_route_retrying:1;
bool dhcp4_configured:1;
char *dhcp4_6rd_tunnel_name;
sd_ipv4ll *ipv4ll;
bool ipv4ll_address_configured:1;
@@ -146,11 +147,12 @@ typedef struct Link {
sd_dhcp6_client *dhcp6_client;
sd_dhcp6_lease *dhcp6_lease;
Set *dhcp6_pd_prefixes;
unsigned dhcp6_messages;
unsigned dhcp6_pd_messages;
bool dhcp6_configured:1;
bool dhcp6_pd_configured:1;
bool dhcp6_configured;
Set *dhcp_pd_prefixes;
unsigned dhcp_pd_messages;
bool dhcp_pd_configured;
/* This is about LLDP reception */
sd_lldp_rx *lldp_rx;

View File

@@ -499,10 +499,10 @@ Manager* manager_free(Manager *m) {
m->dirty_links = set_free_with_destructor(m->dirty_links, link_unref);
m->links_by_name = hashmap_free(m->links_by_name);
m->links_by_hw_addr = hashmap_free(m->links_by_hw_addr);
m->links_by_dhcp6_pd_prefix = hashmap_free(m->links_by_dhcp6_pd_prefix);
m->links_by_dhcp_pd_subnet_prefix = hashmap_free(m->links_by_dhcp_pd_subnet_prefix);
m->links_by_index = hashmap_free_with_destructor(m->links_by_index, link_unref);
m->dhcp6_pd_subnet_ids = set_free(m->dhcp6_pd_subnet_ids);
m->dhcp_pd_subnet_ids = set_free(m->dhcp_pd_subnet_ids);
m->networks = ordered_hashmap_free_with_destructor(m->networks, network_unref);
m->netdevs = hashmap_free_with_destructor(m->netdevs, netdev_unref);
@@ -586,7 +586,7 @@ int manager_load_config(Manager *m) {
if (r < 0)
return r;
return manager_build_dhcp6_pd_subnet_ids(m);
return manager_build_dhcp_pd_subnet_ids(m);
}
bool manager_should_reload(Manager *m) {

View File

@@ -48,11 +48,11 @@ struct Manager {
Hashmap *links_by_index;
Hashmap *links_by_name;
Hashmap *links_by_hw_addr;
Hashmap *links_by_dhcp6_pd_prefix;
Hashmap *links_by_dhcp_pd_subnet_prefix;
Hashmap *netdevs;
OrderedHashmap *networks;
OrderedSet *address_pools;
Set *dhcp6_pd_subnet_ids;
Set *dhcp_pd_subnet_ids;
usec_t network_dirs_ts_usec;

View File

@@ -140,7 +140,7 @@ Network.ConfigureWithoutCarrier, config_parse_bool,
Network.IgnoreCarrierLoss, config_parse_ignore_carrier_loss, 0, 0
Network.KeepConfiguration, config_parse_keep_configuration, 0, offsetof(Network, keep_configuration)
Network.IPv6SendRA, config_parse_router_prefix_delegation, 0, offsetof(Network, router_prefix_delegation)
Network.DHCPv6PrefixDelegation, config_parse_tristate, 0, offsetof(Network, dhcp6_pd)
Network.DHCPPrefixDelegation, config_parse_tristate, 0, offsetof(Network, dhcp_pd)
Address.Address, config_parse_address, 0, 0
Address.Peer, config_parse_address, 0, 0
Address.Broadcast, config_parse_broadcast, 0, 0
@@ -240,6 +240,7 @@ DHCPv4.SendOption, config_parse_dhcp_send_option,
DHCPv4.SendVendorOption, config_parse_dhcp_send_option, 0, offsetof(Network, dhcp_client_send_vendor_options)
DHCPv4.RouteMTUBytes, config_parse_mtu, AF_INET, offsetof(Network, dhcp_route_mtu)
DHCPv4.FallbackLeaseLifetimeSec, config_parse_dhcp_fallback_lease_lifetime, 0, 0
DHCPv4.Use6RD, config_parse_bool, 0, offsetof(Network, dhcp_use_6rd)
DHCPv6.UseAddress, config_parse_bool, 0, offsetof(Network, dhcp6_use_address)
DHCPv6.UseDelegatedPrefix, config_parse_bool, 0, offsetof(Network, dhcp6_use_pd_prefix)
DHCPv6.UseDNS, config_parse_dhcp_use_dns, AF_INET6, 0
@@ -329,13 +330,13 @@ BridgeMDB.VLANId, config_parse_mdb_vlan_id,
BridgeVLAN.PVID, config_parse_brvlan_pvid, 0, 0
BridgeVLAN.VLAN, config_parse_brvlan_vlan, 0, 0
BridgeVLAN.EgressUntagged, config_parse_brvlan_untagged, 0, 0
DHCPv6PrefixDelegation.UplinkInterface, config_parse_uplink, 0, 0
DHCPv6PrefixDelegation.SubnetId, config_parse_dhcp6_pd_subnet_id, 0, offsetof(Network, dhcp6_pd_subnet_id)
DHCPv6PrefixDelegation.Announce, config_parse_bool, 0, offsetof(Network, dhcp6_pd_announce)
DHCPv6PrefixDelegation.Assign, config_parse_bool, 0, offsetof(Network, dhcp6_pd_assign)
DHCPv6PrefixDelegation.ManageTemporaryAddress, config_parse_bool, 0, offsetof(Network, dhcp6_pd_manage_temporary_address)
DHCPv6PrefixDelegation.Token, config_parse_address_generation_type, 0, offsetof(Network, dhcp6_pd_tokens)
DHCPv6PrefixDelegation.RouteMetric, config_parse_uint32, 0, offsetof(Network, dhcp6_pd_route_metric)
DHCPPrefixDelegation.UplinkInterface, config_parse_uplink, 0, 0
DHCPPrefixDelegation.SubnetId, config_parse_dhcp_pd_subnet_id, 0, offsetof(Network, dhcp_pd_subnet_id)
DHCPPrefixDelegation.Announce, config_parse_bool, 0, offsetof(Network, dhcp_pd_announce)
DHCPPrefixDelegation.Assign, config_parse_bool, 0, offsetof(Network, dhcp_pd_assign)
DHCPPrefixDelegation.ManageTemporaryAddress, config_parse_bool, 0, offsetof(Network, dhcp_pd_manage_temporary_address)
DHCPPrefixDelegation.Token, config_parse_address_generation_type, 0, offsetof(Network, dhcp_pd_tokens)
DHCPPrefixDelegation.RouteMetric, config_parse_uint32, 0, offsetof(Network, dhcp_pd_route_metric)
IPv6SendRA.RouterLifetimeSec, config_parse_router_lifetime, 0, offsetof(Network, router_lifetime_usec)
IPv6SendRA.Managed, config_parse_bool, 0, offsetof(Network, router_managed)
IPv6SendRA.OtherInformation, config_parse_bool, 0, offsetof(Network, router_other_information)
@@ -513,6 +514,7 @@ TrivialLinkEqualizer.Id, config_parse_trivial_link_equalizer
Network.IPv4LL, config_parse_ipv4ll, 0, offsetof(Network, link_local)
Network.IPv6Token, config_parse_address_generation_type, 0, offsetof(Network, ndisc_tokens)
Network.IPv6PrefixDelegation, config_parse_router_prefix_delegation, 0, offsetof(Network, router_prefix_delegation)
Network.DHCPv6PrefixDelegation, config_parse_tristate, 0, offsetof(Network, dhcp_pd)
IPv6PrefixDelegation.RouterLifetimeSec, config_parse_sec, 0, offsetof(Network, router_lifetime_usec)
IPv6PrefixDelegation.Managed, config_parse_bool, 0, offsetof(Network, router_managed)
IPv6PrefixDelegation.OtherInformation, config_parse_bool, 0, offsetof(Network, router_other_information)
@@ -552,6 +554,12 @@ DHCPv4.CriticalConnection, config_parse_tristate,
DHCPv6.RouteMetric, config_parse_dhcp_or_ra_route_metric, AF_INET6, 0
DHCPv6.RapidCommit, config_parse_warn_compat, DISABLED_LEGACY, 0
DHCPv6.ForceDHCPv6PDOtherInformation, config_parse_warn_compat, DISABLED_LEGACY, 0
DHCPv6PrefixDelegation.SubnetId, config_parse_dhcp_pd_subnet_id, 0, offsetof(Network, dhcp_pd_subnet_id)
DHCPv6PrefixDelegation.Announce, config_parse_bool, 0, offsetof(Network, dhcp_pd_announce)
DHCPv6PrefixDelegation.Assign, config_parse_bool, 0, offsetof(Network, dhcp_pd_assign)
DHCPv6PrefixDelegation.ManageTemporaryAddress, config_parse_bool, 0, offsetof(Network, dhcp_pd_manage_temporary_address)
DHCPv6PrefixDelegation.Token, config_parse_address_generation_type, 0, offsetof(Network, dhcp_pd_tokens)
DHCPv6PrefixDelegation.RouteMetric, config_parse_uint32, 0, offsetof(Network, dhcp_pd_route_metric)
IPv6AcceptRA.DenyList, config_parse_in_addr_prefixes, AF_INET6, offsetof(Network, ndisc_deny_listed_prefix)
IPv6AcceptRA.BlackList, config_parse_in_addr_prefixes, AF_INET6, offsetof(Network, ndisc_deny_listed_prefix)
TrafficControlQueueingDiscipline.Parent, config_parse_qdisc_parent, _QDISC_KIND_INVALID, 0

Some files were not shown because too many files have changed in this diff Show More