mirror of
https://github.com/systemd/systemd.git
synced 2025-01-10 05:18:17 +03:00
Merge pull request #21625 from yuwata/network-dhcp-6rd
network: dhcp: add 6rd support
This commit is contained in:
commit
d4f8cd4d83
@ -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.
|
||||
|
18
network/80-6rd-tunnel.network
Normal file
18
network/80-6rd-tunnel.network
Normal 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
|
@ -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',
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -412,12 +412,12 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
|
||||
.dhcp6_duid.type = _DUID_TYPE_INVALID,
|
||||
.dhcp6_client_start_mode = _DHCP6_CLIENT_START_MODE_INVALID,
|
||||
|
||||
.dhcp6_pd = -1,
|
||||
.dhcp6_pd_announce = true,
|
||||
.dhcp6_pd_assign = true,
|
||||
.dhcp6_pd_manage_temporary_address = true,
|
||||
.dhcp6_pd_subnet_id = -1,
|
||||
.dhcp6_pd_route_metric = DHCP6PD_ROUTE_METRIC,
|
||||
.dhcp_pd = -1,
|
||||
.dhcp_pd_announce = true,
|
||||
.dhcp_pd_assign = true,
|
||||
.dhcp_pd_manage_temporary_address = true,
|
||||
.dhcp_pd_subnet_id = -1,
|
||||
.dhcp_pd_route_metric = DHCP6PD_ROUTE_METRIC,
|
||||
|
||||
.dhcp_server_bind_to_interface = true,
|
||||
.dhcp_server_emit[SD_DHCP_LEASE_DNS].emit = true,
|
||||
@ -498,7 +498,8 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
|
||||
"DHCP\0" /* compat */
|
||||
"DHCPv4\0"
|
||||
"DHCPv6\0"
|
||||
"DHCPv6PrefixDelegation\0"
|
||||
"DHCPv6PrefixDelegation\0" /* compat */
|
||||
"DHCPPrefixDelegation\0"
|
||||
"DHCPServer\0"
|
||||
"DHCPServerStaticLease\0"
|
||||
"IPv6AcceptRA\0"
|
||||
@ -648,7 +649,7 @@ int network_reload(Manager *manager) {
|
||||
ordered_hashmap_free_with_destructor(manager->networks, network_unref);
|
||||
manager->networks = new_networks;
|
||||
|
||||
return manager_build_dhcp6_pd_subnet_ids(manager);
|
||||
return manager_build_dhcp_pd_subnet_ids(manager);
|
||||
|
||||
failure:
|
||||
ordered_hashmap_free_with_destructor(new_networks, network_unref);
|
||||
@ -656,25 +657,25 @@ failure:
|
||||
return r;
|
||||
}
|
||||
|
||||
int manager_build_dhcp6_pd_subnet_ids(Manager *manager) {
|
||||
int manager_build_dhcp_pd_subnet_ids(Manager *manager) {
|
||||
Network *n;
|
||||
int r;
|
||||
|
||||
assert(manager);
|
||||
|
||||
set_clear(manager->dhcp6_pd_subnet_ids);
|
||||
set_clear(manager->dhcp_pd_subnet_ids);
|
||||
|
||||
ORDERED_HASHMAP_FOREACH(n, manager->networks) {
|
||||
if (n->unmanaged)
|
||||
continue;
|
||||
|
||||
if (!n->dhcp6_pd)
|
||||
if (!n->dhcp_pd)
|
||||
continue;
|
||||
|
||||
if (n->dhcp6_pd_subnet_id < 0)
|
||||
if (n->dhcp_pd_subnet_id < 0)
|
||||
continue;
|
||||
|
||||
r = set_ensure_put(&manager->dhcp6_pd_subnet_ids, &uint64_hash_ops, &n->dhcp6_pd_subnet_id);
|
||||
r = set_ensure_put(&manager->dhcp_pd_subnet_ids, &uint64_hash_ops, &n->dhcp_pd_subnet_id);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@ -756,7 +757,7 @@ static Network *network_free(Network *network) {
|
||||
free(network->dhcp_server_timezone);
|
||||
free(network->dhcp_server_uplink_name);
|
||||
free(network->router_uplink_name);
|
||||
free(network->dhcp6_pd_uplink_name);
|
||||
free(network->dhcp_pd_uplink_name);
|
||||
|
||||
for (sd_dhcp_lease_server_type_t t = 0; t < _SD_DHCP_LEASE_SERVER_TYPE_MAX; t++)
|
||||
free(network->dhcp_server_emit[t].addresses);
|
||||
@ -771,7 +772,7 @@ static Network *network_free(Network *network) {
|
||||
ordered_hashmap_free(network->dhcp_server_send_vendor_options);
|
||||
ordered_hashmap_free(network->dhcp6_client_send_options);
|
||||
ordered_hashmap_free(network->dhcp6_client_send_vendor_options);
|
||||
set_free(network->dhcp6_pd_tokens);
|
||||
set_free(network->dhcp_pd_tokens);
|
||||
set_free(network->ndisc_tokens);
|
||||
|
||||
return mfree(network);
|
||||
|
@ -153,6 +153,7 @@ struct Network {
|
||||
int dhcp_use_gateway;
|
||||
bool dhcp_use_timezone;
|
||||
bool dhcp_use_hostname;
|
||||
bool dhcp_use_6rd;
|
||||
bool dhcp_send_release;
|
||||
bool dhcp_send_decline;
|
||||
DHCPUseDomains dhcp_use_domains;
|
||||
@ -229,16 +230,16 @@ struct Network {
|
||||
int router_uplink_index;
|
||||
char *router_uplink_name;
|
||||
|
||||
/* DHCPv6 Prefix Delegation support */
|
||||
int dhcp6_pd;
|
||||
bool dhcp6_pd_announce;
|
||||
bool dhcp6_pd_assign;
|
||||
bool dhcp6_pd_manage_temporary_address;
|
||||
int64_t dhcp6_pd_subnet_id;
|
||||
uint32_t dhcp6_pd_route_metric;
|
||||
Set *dhcp6_pd_tokens;
|
||||
int dhcp6_pd_uplink_index;
|
||||
char *dhcp6_pd_uplink_name;
|
||||
/* DHCP Prefix Delegation support */
|
||||
int dhcp_pd;
|
||||
bool dhcp_pd_announce;
|
||||
bool dhcp_pd_assign;
|
||||
bool dhcp_pd_manage_temporary_address;
|
||||
int64_t dhcp_pd_subnet_id;
|
||||
uint32_t dhcp_pd_route_metric;
|
||||
Set *dhcp_pd_tokens;
|
||||
int dhcp_pd_uplink_index;
|
||||
char *dhcp_pd_uplink_name;
|
||||
|
||||
/* Bridge Support */
|
||||
int use_bpdu;
|
||||
@ -366,7 +367,7 @@ int network_reload(Manager *manager);
|
||||
int network_load_one(Manager *manager, OrderedHashmap **networks, const char *filename);
|
||||
int network_verify(Network *network);
|
||||
|
||||
int manager_build_dhcp6_pd_subnet_ids(Manager *manager);
|
||||
int manager_build_dhcp_pd_subnet_ids(Manager *manager);
|
||||
|
||||
int network_get_by_name(Manager *manager, const char *name, Network **ret);
|
||||
void network_apply_anonymize_if_set(Network *network);
|
||||
|
@ -27,9 +27,9 @@ void network_adjust_radv(Network *network) {
|
||||
|
||||
/* After this function is called, network->router_prefix_delegation can be treated as a boolean. */
|
||||
|
||||
if (network->dhcp6_pd < 0)
|
||||
if (network->dhcp_pd < 0)
|
||||
/* For backward compatibility. */
|
||||
network->dhcp6_pd = FLAGS_SET(network->router_prefix_delegation, RADV_PREFIX_DELEGATION_DHCP6);
|
||||
network->dhcp_pd = FLAGS_SET(network->router_prefix_delegation, RADV_PREFIX_DELEGATION_DHCP6);
|
||||
|
||||
if (!FLAGS_SET(network->link_local, ADDRESS_FAMILY_IPV6)) {
|
||||
if (network->router_prefix_delegation != RADV_PREFIX_DELEGATION_NONE)
|
||||
@ -421,8 +421,8 @@ static int radv_find_uplink(Link *link, Link **ret) {
|
||||
return link_get_by_index(link->manager, link->network->router_uplink_index, ret);
|
||||
|
||||
if (link->network->router_uplink_index == UPLINK_INDEX_AUTO) {
|
||||
if (link_dhcp6_pd_is_enabled(link))
|
||||
r = dhcp6_pd_find_uplink(link, ret); /* When DHCPv6PD is enabled, use its uplink. */
|
||||
if (link_dhcp_pd_is_enabled(link))
|
||||
r = dhcp_pd_find_uplink(link, ret); /* When DHCP-PD is enabled, use its uplink. */
|
||||
else
|
||||
r = manager_find_uplink(link->manager, AF_INET6, link, ret);
|
||||
if (r < 0)
|
||||
@ -642,10 +642,10 @@ int radv_start(Link *link) {
|
||||
if (sd_radv_is_running(link->radv))
|
||||
return 0;
|
||||
|
||||
if (link->network->dhcp6_pd_announce) {
|
||||
r = dhcp6_request_prefix_delegation(link);
|
||||
if (link->network->dhcp_pd_announce) {
|
||||
r = dhcp_request_prefix_delegation(link);
|
||||
if (r < 0)
|
||||
return log_link_debug_errno(link, r, "Failed to request DHCPv6 prefix delegation: %m");
|
||||
return log_link_debug_errno(link, r, "Failed to request DHCP delegated subnet prefix: %m");
|
||||
}
|
||||
|
||||
log_link_debug(link, "Starting IPv6 Router Advertisements");
|
||||
|
@ -1180,3 +1180,43 @@ int link_request_to_bring_up_or_down(Link *link, bool up) {
|
||||
log_link_debug(link, "Requested to bring link %s", up_or_down(up));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int link_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(link);
|
||||
|
||||
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
|
||||
return 0;
|
||||
|
||||
r = sd_netlink_message_get_errno(m);
|
||||
if (r < 0)
|
||||
log_link_message_warning_errno(link, m, r, "Could not remove interface, ignoring");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int link_remove(Link *link) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
assert(link->manager->rtnl);
|
||||
|
||||
log_link_debug(link, "Removing link.");
|
||||
|
||||
r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_DELLINK, link->ifindex);
|
||||
if (r < 0)
|
||||
return log_link_debug_errno(link, r, "Could not allocate RTM_DELLINK message: %m");
|
||||
|
||||
r = netlink_call_async(link->manager->rtnl, NULL, req, link_remove_handler,
|
||||
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;
|
||||
}
|
||||
|
@ -49,3 +49,5 @@ int link_request_to_activate(Link *link);
|
||||
|
||||
int request_process_link_up_or_down(Request *req);
|
||||
int link_request_to_bring_up_or_down(Link *link, bool up);
|
||||
|
||||
int link_remove(Link *link);
|
||||
|
@ -17,7 +17,7 @@ static const char * const network_config_source_table[_NETWORK_CONFIG_SOURCE_MAX
|
||||
[NETWORK_CONFIG_SOURCE_IPV4LL] = "IPv4LL",
|
||||
[NETWORK_CONFIG_SOURCE_DHCP4] = "DHCPv4",
|
||||
[NETWORK_CONFIG_SOURCE_DHCP6] = "DHCPv6",
|
||||
[NETWORK_CONFIG_SOURCE_DHCP6PD] = "DHCPv6-PD",
|
||||
[NETWORK_CONFIG_SOURCE_DHCP_PD] = "DHCP-PD",
|
||||
[NETWORK_CONFIG_SOURCE_NDISC] = "NDisc",
|
||||
[NETWORK_CONFIG_SOURCE_RUNTIME] = "runtime",
|
||||
};
|
||||
|
@ -25,7 +25,7 @@ typedef enum NetworkConfigSource {
|
||||
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,
|
||||
NETWORK_CONFIG_SOURCE_RUNTIME, /* through D-Bus method */
|
||||
_NETWORK_CONFIG_SOURCE_MAX,
|
||||
|
@ -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);
|
||||
|
@ -128,6 +128,7 @@ SendDecline=
|
||||
MUDURL=
|
||||
RouteMTUBytes=
|
||||
FallbackLeaseLifetimeSec=
|
||||
Use6RD=
|
||||
[DHCPv6]
|
||||
UseAddress=
|
||||
UseDelegatedPrefix=
|
||||
@ -150,6 +151,13 @@ IAID=
|
||||
DUIDType=
|
||||
DUIDRawData=
|
||||
[DHCPv6PrefixDelegation]
|
||||
SubnetId=
|
||||
Announce=
|
||||
Assign=
|
||||
ManageTemporaryAddress=
|
||||
Token=
|
||||
RouteMetric=
|
||||
[DHCPPrefixDelegation]
|
||||
UplinkInterface=
|
||||
SubnetId=
|
||||
Announce=
|
||||
@ -240,6 +248,7 @@ VRF=
|
||||
IgnoreCarrierLoss=
|
||||
KeepConfiguration=
|
||||
DHCPv6PrefixDelegation=
|
||||
DHCPPrefixDelegation=
|
||||
BatmanAdvanced=
|
||||
IPoIB=
|
||||
[IPv6Prefix]
|
||||
|
18
test/test-network/conf/80-6rd-tunnel.network
Normal file
18
test/test-network/conf/80-6rd-tunnel.network
Normal 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
|
@ -6,9 +6,9 @@ Name=dummy97
|
||||
IPv6PrivacyExtensions=yes
|
||||
IPv6AcceptRA=no
|
||||
DHCP=no
|
||||
DHCPv6PrefixDelegation=yes
|
||||
DHCPPrefixDelegation=yes
|
||||
|
||||
[DHCPv6PrefixDelegation]
|
||||
[DHCPPrefixDelegation]
|
||||
UplinkInterface=veth99
|
||||
SubnetId=1
|
||||
Announce=no
|
@ -6,9 +6,9 @@ Name=dummy98
|
||||
IPv6PrivacyExtensions=yes
|
||||
IPv6AcceptRA=no
|
||||
DHCP=no
|
||||
DHCPv6PrefixDelegation=yes
|
||||
DHCPPrefixDelegation=yes
|
||||
|
||||
[DHCPv6PrefixDelegation]
|
||||
[DHCPPrefixDelegation]
|
||||
UplinkInterface=veth99
|
||||
SubnetId=2
|
||||
Announce=no
|
@ -6,9 +6,9 @@ Name=dummy99
|
||||
IPv6PrivacyExtensions=yes
|
||||
IPv6AcceptRA=no
|
||||
DHCP=no
|
||||
DHCPv6PrefixDelegation=yes
|
||||
DHCPPrefixDelegation=yes
|
||||
|
||||
[DHCPv6PrefixDelegation]
|
||||
[DHCPPrefixDelegation]
|
||||
UplinkInterface=veth99
|
||||
Assign=no
|
||||
Announce=no
|
@ -6,9 +6,9 @@ Name=test1
|
||||
IPv6PrivacyExtensions=yes
|
||||
IPv6AcceptRA=no
|
||||
DHCP=no
|
||||
DHCPv6PrefixDelegation=yes
|
||||
DHCPPrefixDelegation=yes
|
||||
|
||||
[DHCPv6PrefixDelegation]
|
||||
[DHCPPrefixDelegation]
|
||||
UplinkInterface=veth99
|
||||
SubnetId=0
|
||||
Announce=no
|
@ -6,10 +6,10 @@ Name=veth97
|
||||
IPv6PrivacyExtensions=yes
|
||||
IPv6AcceptRA=no
|
||||
DHCP=no
|
||||
DHCPv6PrefixDelegation=yes
|
||||
DHCPPrefixDelegation=yes
|
||||
IPv6SendRA=yes
|
||||
|
||||
[DHCPv6PrefixDelegation]
|
||||
[DHCPPrefixDelegation]
|
||||
SubnetId=8
|
||||
Announce=yes
|
||||
Token=eui64
|
@ -6,10 +6,10 @@ Name=veth98
|
||||
IPv6PrivacyExtensions=yes
|
||||
IPv6AcceptRA=no
|
||||
DHCP=no
|
||||
DHCPv6PrefixDelegation=yes
|
||||
DHCPPrefixDelegation=yes
|
||||
IPv6SendRA=yes
|
||||
|
||||
[DHCPv6PrefixDelegation]
|
||||
[DHCPPrefixDelegation]
|
||||
UplinkInterface=veth99
|
||||
SubnetId=9
|
||||
Announce=yes
|
7
test/test-network/conf/dhcp4-6rd-server.network
Normal file
7
test/test-network/conf/dhcp4-6rd-server.network
Normal file
@ -0,0 +1,7 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
[Match]
|
||||
Name=veth-peer
|
||||
|
||||
[Network]
|
||||
IPv6AcceptRA=no
|
||||
Address=10.0.0.1/8
|
19
test/test-network/conf/dhcp4-6rd-upstream.network
Normal file
19
test/test-network/conf/dhcp4-6rd-upstream.network
Normal file
@ -0,0 +1,19 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
[Match]
|
||||
Name=veth99
|
||||
|
||||
[Network]
|
||||
IPv6PrivacyExtensions=yes
|
||||
IPv6AcceptRA=no
|
||||
DHCP=ipv4
|
||||
DHCPPrefixDelegation=yes
|
||||
|
||||
[DHCPv4]
|
||||
Use6RD=yes
|
||||
|
||||
[DHCPPrefixDelegation]
|
||||
UplinkInterface=:self
|
||||
SubnetId=10
|
||||
Announce=no
|
||||
Token=eui64
|
||||
Token=::1a:2b:3c:4d
|
@ -6,12 +6,12 @@ Name=veth99
|
||||
IPv6PrivacyExtensions=yes
|
||||
IPv6AcceptRA=no
|
||||
DHCP=ipv6
|
||||
DHCPv6PrefixDelegation=yes
|
||||
DHCPPrefixDelegation=yes
|
||||
|
||||
[DHCPv6]
|
||||
WithoutRA=solicit
|
||||
|
||||
[DHCPv6PrefixDelegation]
|
||||
[DHCPPrefixDelegation]
|
||||
UplinkInterface=:self
|
||||
SubnetId=10
|
||||
Announce=no
|
||||
|
22
test/test-network/conf/isc-dhcpd-6rd.conf
Normal file
22
test/test-network/conf/isc-dhcpd-6rd.conf
Normal file
@ -0,0 +1,22 @@
|
||||
default-lease-time 2592000;
|
||||
preferred-lifetime 604800;
|
||||
|
||||
default-lease-time 600;
|
||||
max-lease-time 7200;
|
||||
|
||||
option domain-name-servers 10.0.0.2;
|
||||
option domain-search "test.example.com","example.com";
|
||||
|
||||
# ipv4masklen = 8
|
||||
# 6rd prefix = 2001:db8::/32
|
||||
# BR address = 10.0.0.1
|
||||
option option-6rd code 212 = {
|
||||
integer 8, integer 8, ip6-address, array of ip-address
|
||||
};
|
||||
|
||||
option option-6rd 8 32 2001:db8:: 10.0.0.1;
|
||||
|
||||
subnet 10.0.0.0 netmask 255.0.0.0 {
|
||||
# Addresses available to clients
|
||||
range 10.100.100.100 10.100.100.199;
|
||||
}
|
@ -4994,7 +4994,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
|
||||
print(output)
|
||||
self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
|
||||
|
||||
class NetworkdDHCP6PDTests(unittest.TestCase, Utilities):
|
||||
class NetworkdDHCPPDTests(unittest.TestCase, Utilities):
|
||||
links = [
|
||||
'dummy97',
|
||||
'dummy98',
|
||||
@ -5012,14 +5012,17 @@ class NetworkdDHCP6PDTests(unittest.TestCase, Utilities):
|
||||
'25-veth.netdev',
|
||||
'25-veth-downstream-veth97.netdev',
|
||||
'25-veth-downstream-veth98.netdev',
|
||||
'dhcp6pd-downstream-dummy97.network',
|
||||
'dhcp6pd-downstream-dummy98.network',
|
||||
'dhcp6pd-downstream-dummy99.network',
|
||||
'dhcp6pd-downstream-test1.network',
|
||||
'dhcp6pd-downstream-veth97.network',
|
||||
'dhcp6pd-downstream-veth97-peer.network',
|
||||
'dhcp6pd-downstream-veth98.network',
|
||||
'dhcp6pd-downstream-veth98-peer.network',
|
||||
'80-6rd-tunnel.network',
|
||||
'dhcp-pd-downstream-dummy97.network',
|
||||
'dhcp-pd-downstream-dummy98.network',
|
||||
'dhcp-pd-downstream-dummy99.network',
|
||||
'dhcp-pd-downstream-test1.network',
|
||||
'dhcp-pd-downstream-veth97.network',
|
||||
'dhcp-pd-downstream-veth97-peer.network',
|
||||
'dhcp-pd-downstream-veth98.network',
|
||||
'dhcp-pd-downstream-veth98-peer.network',
|
||||
'dhcp4-6rd-server.network',
|
||||
'dhcp4-6rd-upstream.network',
|
||||
'dhcp6pd-server.network',
|
||||
'dhcp6pd-upstream.network',
|
||||
]
|
||||
@ -5037,12 +5040,12 @@ class NetworkdDHCP6PDTests(unittest.TestCase, Utilities):
|
||||
|
||||
def test_dhcp6pd(self):
|
||||
copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp6pd-server.network', 'dhcp6pd-upstream.network',
|
||||
'25-veth-downstream-veth97.netdev', 'dhcp6pd-downstream-veth97.network', 'dhcp6pd-downstream-veth97-peer.network',
|
||||
'25-veth-downstream-veth98.netdev', 'dhcp6pd-downstream-veth98.network', 'dhcp6pd-downstream-veth98-peer.network',
|
||||
'11-dummy.netdev', 'dhcp6pd-downstream-test1.network',
|
||||
'dhcp6pd-downstream-dummy97.network',
|
||||
'12-dummy.netdev', 'dhcp6pd-downstream-dummy98.network',
|
||||
'13-dummy.netdev', 'dhcp6pd-downstream-dummy99.network')
|
||||
'25-veth-downstream-veth97.netdev', 'dhcp-pd-downstream-veth97.network', 'dhcp-pd-downstream-veth97-peer.network',
|
||||
'25-veth-downstream-veth98.netdev', 'dhcp-pd-downstream-veth98.network', 'dhcp-pd-downstream-veth98-peer.network',
|
||||
'11-dummy.netdev', 'dhcp-pd-downstream-test1.network',
|
||||
'dhcp-pd-downstream-dummy97.network',
|
||||
'12-dummy.netdev', 'dhcp-pd-downstream-dummy98.network',
|
||||
'13-dummy.netdev', 'dhcp-pd-downstream-dummy99.network')
|
||||
|
||||
start_networkd()
|
||||
self.wait_online(['veth-peer:routable'])
|
||||
@ -5229,6 +5232,242 @@ class NetworkdDHCP6PDTests(unittest.TestCase, Utilities):
|
||||
print(output)
|
||||
self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]03::/64 proto dhcp metric [0-9]* expires')
|
||||
|
||||
def test_dhcp4_6rd(self):
|
||||
copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp4-6rd-server.network', 'dhcp4-6rd-upstream.network',
|
||||
'25-veth-downstream-veth97.netdev', 'dhcp-pd-downstream-veth97.network', 'dhcp-pd-downstream-veth97-peer.network',
|
||||
'25-veth-downstream-veth98.netdev', 'dhcp-pd-downstream-veth98.network', 'dhcp-pd-downstream-veth98-peer.network',
|
||||
'11-dummy.netdev', 'dhcp-pd-downstream-test1.network',
|
||||
'dhcp-pd-downstream-dummy97.network',
|
||||
'12-dummy.netdev', 'dhcp-pd-downstream-dummy98.network',
|
||||
'13-dummy.netdev', 'dhcp-pd-downstream-dummy99.network',
|
||||
'80-6rd-tunnel.network')
|
||||
|
||||
start_networkd()
|
||||
self.wait_online(['veth-peer:routable'])
|
||||
start_isc_dhcpd('veth-peer', 'isc-dhcpd-6rd.conf', ip='-4')
|
||||
self.wait_online(['veth99:routable', 'test1:routable', 'dummy98:routable', 'dummy99:degraded',
|
||||
'veth97:routable', 'veth97-peer:routable', 'veth98:routable', 'veth98-peer:routable'])
|
||||
|
||||
print('### ip -4 address show dev veth-peer scope global')
|
||||
output = check_output('ip -4 address show dev veth-peer scope global')
|
||||
print(output)
|
||||
self.assertIn('inet 10.0.0.1/8 brd 10.255.255.255 scope global veth-peer', output)
|
||||
|
||||
'''
|
||||
Link Subnet IDs
|
||||
test1: 0x00
|
||||
dummy97: 0x01 (The link will appear later)
|
||||
dummy98: 0x02
|
||||
dummy99: auto -> 0x03 (No address assignment)
|
||||
veth97: 0x08
|
||||
veth98: 0x09
|
||||
veth99: 0x10
|
||||
'''
|
||||
|
||||
print('### ip -4 address show dev veth99 scope global')
|
||||
output = check_output('ip -4 address show dev veth99 scope global')
|
||||
print(output)
|
||||
self.assertRegex(output, 'inet 10.100.100.[0-9]*/8 (metric 1024 |)brd 10.255.255.255 scope global dynamic veth99')
|
||||
|
||||
print('### ip -6 address show dev veth99 scope global')
|
||||
output = check_output('ip -6 address show dev veth99 scope global')
|
||||
print(output)
|
||||
# address in IA_PD (Token=static)
|
||||
self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+10:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
|
||||
# address in IA_PD (Token=eui64)
|
||||
self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+10:1034:56ff:fe78:9abc/64 (metric 256 |)scope global dynamic mngtmpaddr')
|
||||
# address in IA_PD (temporary)
|
||||
# Note that the temporary addresses may appear after the link enters configured state
|
||||
self.wait_address('veth99', 'inet6 2001:db8:6464:[0-9a-f]+10:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
|
||||
|
||||
print('### ip -6 address show dev test1 scope global')
|
||||
output = check_output('ip -6 address show dev test1 scope global')
|
||||
print(output)
|
||||
# address in IA_PD (Token=static)
|
||||
self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+00:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
|
||||
# address in IA_PD (temporary)
|
||||
self.wait_address('test1', 'inet6 2001:db8:6464:[0-9a-f]+00:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
|
||||
|
||||
print('### ip -6 address show dev dummy98 scope global')
|
||||
output = check_output('ip -6 address show dev dummy98 scope global')
|
||||
print(output)
|
||||
# address in IA_PD (Token=static)
|
||||
self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+02:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
|
||||
# address in IA_PD (temporary)
|
||||
self.wait_address('dummy98', 'inet6 2001:db8:6464:[0-9a-f]+02:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
|
||||
|
||||
print('### ip -6 address show dev dummy99 scope global')
|
||||
output = check_output('ip -6 address show dev dummy99 scope global')
|
||||
print(output)
|
||||
# Assign=no
|
||||
self.assertNotRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+03')
|
||||
|
||||
print('### ip -6 address show dev veth97 scope global')
|
||||
output = check_output('ip -6 address show dev veth97 scope global')
|
||||
print(output)
|
||||
# address in IA_PD (Token=static)
|
||||
self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+08:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
|
||||
# address in IA_PD (Token=eui64)
|
||||
self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+08:1034:56ff:fe78:9ace/64 (metric 256 |)scope global dynamic mngtmpaddr')
|
||||
# address in IA_PD (temporary)
|
||||
self.wait_address('veth97', 'inet6 2001:db8:6464:[0-9a-f]+08:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
|
||||
|
||||
print('### ip -6 address show dev veth97-peer scope global')
|
||||
output = check_output('ip -6 address show dev veth97-peer scope global')
|
||||
print(output)
|
||||
# NDisc address (Token=static)
|
||||
self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+08:1a:2b:3c:4e/64 (metric 256 |)scope global dynamic mngtmpaddr')
|
||||
# NDisc address (Token=eui64)
|
||||
self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+08:1034:56ff:fe78:9acf/64 (metric 256 |)scope global dynamic mngtmpaddr')
|
||||
# NDisc address (temporary)
|
||||
self.wait_address('veth97-peer', 'inet6 2001:db8:6464:[0-9a-f]+08:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
|
||||
|
||||
print('### ip -6 address show dev veth98 scope global')
|
||||
output = check_output('ip -6 address show dev veth98 scope global')
|
||||
print(output)
|
||||
# address in IA_PD (Token=static)
|
||||
self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+09:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
|
||||
# address in IA_PD (Token=eui64)
|
||||
self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+09:1034:56ff:fe78:9abe/64 (metric 256 |)scope global dynamic mngtmpaddr')
|
||||
# address in IA_PD (temporary)
|
||||
self.wait_address('veth98', 'inet6 2001:db8:6464:[0-9a-f]+09:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
|
||||
|
||||
print('### ip -6 address show dev veth98-peer scope global')
|
||||
output = check_output('ip -6 address show dev veth98-peer scope global')
|
||||
print(output)
|
||||
# NDisc address (Token=static)
|
||||
self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+09:1a:2b:3c:4e/64 (metric 256 |)scope global dynamic mngtmpaddr')
|
||||
# NDisc address (Token=eui64)
|
||||
self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+09:1034:56ff:fe78:9abf/64 (metric 256 |)scope global dynamic mngtmpaddr')
|
||||
# NDisc address (temporary)
|
||||
self.wait_address('veth98-peer', 'inet6 2001:db8:6464:[0-9a-f]+09:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
|
||||
|
||||
print('### ip -6 route show type unreachable')
|
||||
output = check_output('ip -6 route show type unreachable')
|
||||
print(output)
|
||||
self.assertRegex(output, 'unreachable 2001:db8:6464:[0-9a-f]+00::/56 dev lo proto dhcp')
|
||||
|
||||
print('### ip -6 route show dev veth99')
|
||||
output = check_output('ip -6 route show dev veth99')
|
||||
print(output)
|
||||
self.assertRegex(output, '2001:db8:6464:[0-9a-f]+10::/64 proto kernel metric [0-9]* expires')
|
||||
|
||||
print('### ip -6 route show dev test1')
|
||||
output = check_output('ip -6 route show dev test1')
|
||||
print(output)
|
||||
self.assertRegex(output, '2001:db8:6464:[0-9a-f]+00::/64 proto kernel metric [0-9]* expires')
|
||||
|
||||
print('### ip -6 route show dev dummy98')
|
||||
output = check_output('ip -6 route show dev dummy98')
|
||||
print(output)
|
||||
self.assertRegex(output, '2001:db8:6464:[0-9a-f]+02::/64 proto kernel metric [0-9]* expires')
|
||||
|
||||
print('### ip -6 route show dev dummy99')
|
||||
output = check_output('ip -6 route show dev dummy99')
|
||||
print(output)
|
||||
self.assertRegex(output, '2001:db8:6464:[0-9a-f]+03::/64 proto dhcp metric [0-9]* expires')
|
||||
|
||||
print('### ip -6 route show dev veth97')
|
||||
output = check_output('ip -6 route show dev veth97')
|
||||
print(output)
|
||||
self.assertRegex(output, '2001:db8:6464:[0-9a-f]+08::/64 proto kernel metric [0-9]* expires')
|
||||
|
||||
print('### ip -6 route show dev veth97-peer')
|
||||
output = check_output('ip -6 route show dev veth97-peer')
|
||||
print(output)
|
||||
self.assertRegex(output, '2001:db8:6464:[0-9a-f]+08::/64 proto ra metric [0-9]* expires')
|
||||
|
||||
print('### ip -6 route show dev veth98')
|
||||
output = check_output('ip -6 route show dev veth98')
|
||||
print(output)
|
||||
self.assertRegex(output, '2001:db8:6464:[0-9a-f]+09::/64 proto kernel metric [0-9]* expires')
|
||||
|
||||
print('### ip -6 route show dev veth98-peer')
|
||||
output = check_output('ip -6 route show dev veth98-peer')
|
||||
print(output)
|
||||
self.assertRegex(output, '2001:db8:6464:[0-9a-f]+09::/64 proto ra metric [0-9]* expires')
|
||||
|
||||
# Test case for a downstream which appears later
|
||||
check_output('ip link add dummy97 type dummy')
|
||||
self.wait_online(['dummy97:routable'])
|
||||
|
||||
print('### ip -6 address show dev dummy97 scope global')
|
||||
output = check_output('ip -6 address show dev dummy97 scope global')
|
||||
print(output)
|
||||
# address in IA_PD (Token=static)
|
||||
self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+01:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
|
||||
# address in IA_PD (temporary)
|
||||
self.wait_address('dummy97', 'inet6 2001:db8:6464:[0-9a-f]+01:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
|
||||
|
||||
print('### ip -6 route show dev dummy97')
|
||||
output = check_output('ip -6 route show dev dummy97')
|
||||
print(output)
|
||||
self.assertRegex(output, '2001:db8:6464:[0-9a-f]+01::/64 proto kernel metric [0-9]* expires')
|
||||
|
||||
# Test case for reconfigure
|
||||
check_output(*networkctl_cmd, 'reconfigure', 'dummy98', 'dummy99', env=env)
|
||||
self.wait_online(['dummy98:routable'])
|
||||
|
||||
print('### ip -6 address show dev dummy98 scope global')
|
||||
output = check_output('ip -6 address show dev dummy98 scope global')
|
||||
print(output)
|
||||
# address in IA_PD (Token=static)
|
||||
self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+02:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
|
||||
# address in IA_PD (temporary)
|
||||
self.wait_address('dummy98', 'inet6 2001:db8:6464:[0-9a-f]+02:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
|
||||
|
||||
print('### ip -6 address show dev dummy99 scope global')
|
||||
output = check_output('ip -6 address show dev dummy99 scope global')
|
||||
print(output)
|
||||
# Assign=no
|
||||
self.assertNotRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+03')
|
||||
|
||||
print('### ip -6 route show dev dummy98')
|
||||
output = check_output('ip -6 route show dev dummy98')
|
||||
print(output)
|
||||
self.assertRegex(output, '2001:db8:6464:[0-9a-f]+02::/64 proto kernel metric [0-9]* expires')
|
||||
|
||||
print('### ip -6 route show dev dummy99')
|
||||
output = check_output('ip -6 route show dev dummy99')
|
||||
print(output)
|
||||
self.assertRegex(output, '2001:db8:6464:[0-9a-f]+03::/64 proto dhcp metric [0-9]* expires')
|
||||
|
||||
tunnel_name = None
|
||||
for name in os.listdir('/sys/class/net/'):
|
||||
if name.startswith('6rd-'):
|
||||
tunnel_name = name
|
||||
break
|
||||
|
||||
self.wait_online(['{}:routable'.format(tunnel_name)])
|
||||
|
||||
print('### ip -d link show dev {}'.format(tunnel_name))
|
||||
output = check_output('ip -d link show dev {}'.format(tunnel_name))
|
||||
print(output)
|
||||
self.assertIn('link/sit 10.100.100.', output)
|
||||
self.assertIn('local 10.100.100.', output)
|
||||
self.assertIn('dev veth99', output)
|
||||
self.assertIn('ttl 64', output)
|
||||
self.assertIn('6rd-prefix 2001:db8::/32', output)
|
||||
self.assertIn('6rd-relay_prefix 10.0.0.0/8', output)
|
||||
|
||||
print('### ip -6 address show dev {}'.format(tunnel_name))
|
||||
output = check_output('ip -6 address show dev {}'.format(tunnel_name))
|
||||
print(output)
|
||||
self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+00:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/56 (metric 256 |)scope global dynamic')
|
||||
self.assertRegex(output, 'inet6 ::10.100.100.[0-9]+/96 scope global')
|
||||
|
||||
print('### ip -6 route show dev {}'.format(tunnel_name))
|
||||
output = check_output('ip -6 route show dev {}'.format(tunnel_name))
|
||||
print(output)
|
||||
self.assertRegex(output, '2001:db8:6464:[0-9a-f]+00::/56 proto kernel metric [0-9]* expires')
|
||||
self.assertRegex(output, '::/96 proto kernel metric [0-9]*')
|
||||
|
||||
print('### ip -6 route show default')
|
||||
output = check_output('ip -6 route show default')
|
||||
print(output)
|
||||
self.assertIn('default', output)
|
||||
self.assertIn('via ::10.0.0.1 dev {}'.format(tunnel_name), output)
|
||||
|
||||
class NetworkdIPv6PrefixTests(unittest.TestCase, Utilities):
|
||||
links = [
|
||||
'dummy98',
|
||||
|
Loading…
Reference in New Issue
Block a user