1
0
mirror of https://github.com/systemd/systemd synced 2026-03-24 15:55:00 +01:00

Compare commits

..

No commits in common. "801cf85935074421d19e0ff0beec090b7482c821" and "57777c9e612bee8b3a885518a8b71aec93c01f50" have entirely different histories.

22 changed files with 135 additions and 365 deletions

View File

@ -2382,12 +2382,12 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
<varlistentry> <varlistentry>
<term><varname>UplinkInterface=</varname></term> <term><varname>UplinkInterface=</varname></term>
<listitem><para>Specifies the name or the index of the uplink interface, or one of the special <listitem><para>Specifies name or index of uplink interface, or one of the special values
values <literal>:none</literal> and <literal>:auto</literal>. When emitting DNS, NTP, or SIP <literal>:none</literal> and <literal>:auto</literal>. When emitting DNS, NTP, or SIP servers
servers is enabled but no servers are specified, the servers configured in the uplink interface are enabled but no servers are specified, the servers configured in the uplink interface will
will be emitted. When <literal>:auto</literal>, the link which has a default gateway with the be emitted. When <literal>:auto</literal>, the link which has default gateway with higher
highest priority will be automatically selected. When <literal>:none</literal>, no uplink priority will be automatically selected. When <literal>:none</literal>, no uplink interface
interface will be selected. Defaults to <literal>:auto</literal>.</para></listitem> will be selected. Defaults to <literal>:auto</literal>.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
@ -2586,28 +2586,18 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
for details. Defaults to <literal>medium</literal>.</para></listitem> for details. Defaults to <literal>medium</literal>.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><varname>UplinkInterface=</varname></term>
<listitem><para>Specifies the name or the index of the uplink interface, or one of the special
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 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>
<varlistentry> <varlistentry>
<term><varname>EmitDNS=</varname></term> <term><varname>EmitDNS=</varname></term>
<term><varname>DNS=</varname></term> <term><varname>DNS=</varname></term>
<listitem><para><varname>DNS=</varname> specifies a list of recursive DNS server IPv6 addresses <listitem><para><varname>DNS=</varname> specifies a list of recursive DNS server IPv6 addresses that
that are distributed via Router Advertisement messages when <varname>EmitDNS=</varname> is true. are distributed via Router Advertisement messages when <varname>EmitDNS=</varname> is
<varname>DNS=</varname> also takes special value <literal>_link_local</literal>; in that case true. <varname>DNS=</varname> also takes special value <literal>_link_local</literal>; in that case
the IPv6 link local address is distributed. If <varname>DNS=</varname> is empty, DNS servers are the IPv6 link local address is distributed. If <varname>DNS=</varname> is empty, DNS servers are read
read from the [Network] section. If the [Network] section does not contain any DNS servers from the [Network] section. If the [Network] section does not contain any DNS servers either, DNS
either, DNS servers from the uplink interface specified in <varname>UplinkInterface=</varname> servers from the uplink with the highest priority default route are used. When
will be used. When <varname>EmitDNS=</varname> is false, no DNS server information is sent in <varname>EmitDNS=</varname> is false, no DNS server information is sent in Router Advertisement
Router Advertisement messages. <varname>EmitDNS=</varname> defaults to true.</para></listitem> messages. <varname>EmitDNS=</varname> defaults to true.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
@ -2615,12 +2605,11 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
<term><varname>Domains=</varname></term> <term><varname>Domains=</varname></term>
<listitem><para>A list of DNS search domains distributed via Router Advertisement messages when <listitem><para>A list of DNS search domains distributed via Router Advertisement messages when
<varname>EmitDomains=</varname> is true. If <varname>Domains=</varname> is empty, DNS search <varname>EmitDomains=</varname> is true. If <varname>Domains=</varname> is empty, DNS search domains
domains are read from the [Network] section. If the [Network] section does not contain any DNS are read from the [Network] section. If the [Network] section does not contain any DNS search domains
search domains either, DNS search domains from the uplink interface specified in either, DNS search domains from the uplink with the highest priority default route are used. When
<varname>UplinkInterface=</varname> will be used. When <varname>EmitDomains=</varname> is false, <varname>EmitDomains=</varname> is false, no DNS search domain information is sent in Router
no DNS search domain information is sent in Router Advertisement messages. Advertisement messages. <varname>EmitDomains=</varname> defaults to true.</para></listitem>
<varname>EmitDomains=</varname> defaults to true.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>

View File

@ -443,12 +443,8 @@ int sd_rtnl_message_new_neigh(sd_netlink *rtnl, sd_netlink_message **ret, uint16
if (r < 0) if (r < 0)
return r; return r;
if (nlmsg_type == RTM_NEWNEIGH) { if (nlmsg_type == RTM_NEWNEIGH)
if (ndm_family == AF_BRIDGE) (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE;
(*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
else
(*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE;
}
ndm = NLMSG_DATA((*ret)->hdr); ndm = NLMSG_DATA((*ret)->hdr);

View File

@ -106,7 +106,7 @@ static int dhcp_server_find_uplink(Link *link, Link **ret) {
if (link->network->dhcp_server_uplink_index > 0) if (link->network->dhcp_server_uplink_index > 0)
return link_get_by_index(link->manager, link->network->dhcp_server_uplink_index, ret); return link_get_by_index(link->manager, link->network->dhcp_server_uplink_index, ret);
if (link->network->dhcp_server_uplink_index == UPLINK_INDEX_AUTO) { if (link->network->dhcp_server_uplink_index == 0) {
/* It is not necessary to propagate error in automatic selection. */ /* It is not necessary to propagate error in automatic selection. */
if (manager_find_uplink(link->manager, AF_INET, link, ret) < 0) if (manager_find_uplink(link->manager, AF_INET, link, ret) < 0)
*ret = NULL; *ret = NULL;
@ -663,3 +663,55 @@ int config_parse_dhcp_server_address(
network->dhcp_server_address_prefixlen = prefixlen; network->dhcp_server_address_prefixlen = prefixlen;
return 0; return 0;
} }
int config_parse_dhcp_server_uplink(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
Network *network = userdata;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
if (isempty(rvalue) || streq(rvalue, ":auto")) {
network->dhcp_server_uplink_index = 0; /* uplink will be selected automatically */
network->dhcp_server_uplink_name = mfree(network->dhcp_server_uplink_name);
return 0;
}
if (streq(rvalue, ":none")) {
network->dhcp_server_uplink_index = -1; /* uplink will not be selected automatically */
network->dhcp_server_uplink_name = mfree(network->dhcp_server_uplink_name);
return 0;
}
r = parse_ifindex(rvalue);
if (r > 0) {
network->dhcp_server_uplink_index = r;
network->dhcp_server_uplink_name = mfree(network->dhcp_server_uplink_name);
return 0;
}
if (!ifname_valid_full(rvalue, IFNAME_VALID_ALTERNATIVE)) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Invalid interface name in %s=, ignoring assignment: %s", lvalue, rvalue);
return 0;
}
r = free_and_strdup_warn(&network->dhcp_server_uplink_name, rvalue);
if (r < 0)
return r;
network->dhcp_server_uplink_index = 0;
return 0;
}

View File

@ -15,3 +15,4 @@ int request_process_dhcp_server(Request *req);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_relay_agent_suboption); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_relay_agent_suboption);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_emit); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_emit);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_address); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_address);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_uplink);

View File

@ -618,8 +618,12 @@ static int link_acquire_dynamic_ipv6_conf(Link *link) {
log_link_debug(link, "Starting IPv6 Router Advertisements"); log_link_debug(link, "Starting IPv6 Router Advertisements");
r = sd_radv_start(link->radv); r = radv_emit_dns(link);
if (r < 0) if (r < 0)
return log_link_warning_errno(link, r, "Failed to configure DNS or Domains in IPv6 Router Advertisement: %m");
r = sd_radv_start(link->radv);
if (r < 0 && r != -EBUSY)
return log_link_warning_errno(link, r, "Could not start IPv6 Router Advertisement: %m"); return log_link_warning_errno(link, r, "Could not start IPv6 Router Advertisement: %m");
} }
@ -1143,7 +1147,7 @@ static int link_configure(Link *link) {
if (r < 0) if (r < 0)
return r; return r;
r = link_request_radv(link); r = radv_configure(link);
if (r < 0) if (r < 0)
return r; return r;

View File

@ -265,7 +265,7 @@ IPv6AcceptRA.PrefixDenyList, config_parse_ndisc_address_filter,
IPv6AcceptRA.RouteAllowList, config_parse_ndisc_address_filter, 0, offsetof(Network, ndisc_allow_listed_route_prefix) IPv6AcceptRA.RouteAllowList, config_parse_ndisc_address_filter, 0, offsetof(Network, ndisc_allow_listed_route_prefix)
IPv6AcceptRA.RouteDenyList, config_parse_ndisc_address_filter, 0, offsetof(Network, ndisc_deny_listed_route_prefix) IPv6AcceptRA.RouteDenyList, config_parse_ndisc_address_filter, 0, offsetof(Network, ndisc_deny_listed_route_prefix)
DHCPServer.ServerAddress, config_parse_dhcp_server_address, 0, 0 DHCPServer.ServerAddress, config_parse_dhcp_server_address, 0, 0
DHCPServer.UplinkInterface, config_parse_uplink, 0, 0 DHCPServer.UplinkInterface, config_parse_dhcp_server_uplink, 0, 0
DHCPServer.RelayTarget, config_parse_in_addr_non_null, AF_INET, offsetof(Network, dhcp_server_relay_target) DHCPServer.RelayTarget, config_parse_in_addr_non_null, AF_INET, offsetof(Network, dhcp_server_relay_target)
DHCPServer.RelayAgentCircuitId, config_parse_dhcp_server_relay_agent_suboption, 0, offsetof(Network, dhcp_server_relay_agent_circuit_id) DHCPServer.RelayAgentCircuitId, config_parse_dhcp_server_relay_agent_suboption, 0, offsetof(Network, dhcp_server_relay_agent_circuit_id)
DHCPServer.RelayAgentRemoteId, config_parse_dhcp_server_relay_agent_suboption, 0, offsetof(Network, dhcp_server_relay_agent_remote_id) DHCPServer.RelayAgentRemoteId, config_parse_dhcp_server_relay_agent_suboption, 0, offsetof(Network, dhcp_server_relay_agent_remote_id)
@ -333,7 +333,6 @@ IPv6SendRA.DNS, config_parse_radv_dns,
IPv6SendRA.EmitDomains, config_parse_bool, 0, offsetof(Network, router_emit_domains) IPv6SendRA.EmitDomains, config_parse_bool, 0, offsetof(Network, router_emit_domains)
IPv6SendRA.Domains, config_parse_radv_search_domains, 0, 0 IPv6SendRA.Domains, config_parse_radv_search_domains, 0, 0
IPv6SendRA.DNSLifetimeSec, config_parse_sec, 0, offsetof(Network, router_dns_lifetime_usec) IPv6SendRA.DNSLifetimeSec, config_parse_sec, 0, offsetof(Network, router_dns_lifetime_usec)
IPv6SendRA.UplinkInterface, config_parse_uplink, 0, 0
IPv6Prefix.Prefix, config_parse_prefix, 0, 0 IPv6Prefix.Prefix, config_parse_prefix, 0, 0
IPv6Prefix.OnLink, config_parse_prefix_flags, 0, 0 IPv6Prefix.OnLink, config_parse_prefix_flags, 0, 0
IPv6Prefix.AddressAutoconfiguration, config_parse_prefix_flags, 0, 0 IPv6Prefix.AddressAutoconfiguration, config_parse_prefix_flags, 0, 0

View File

@ -640,7 +640,6 @@ static Network *network_free(Network *network) {
free(network->dhcp_server_timezone); free(network->dhcp_server_timezone);
free(network->dhcp_server_uplink_name); free(network->dhcp_server_uplink_name);
free(network->router_uplink_name);
for (sd_dhcp_lease_server_type_t t = 0; t < _SD_DHCP_LEASE_SERVER_TYPE_MAX; t++) for (sd_dhcp_lease_server_type_t t = 0; t < _SD_DHCP_LEASE_SERVER_TYPE_MAX; t++)
free(network->dhcp_server_emit[t].addresses); free(network->dhcp_server_emit[t].addresses);
@ -1186,73 +1185,6 @@ int config_parse_link_group(
return 0; return 0;
} }
int config_parse_uplink(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
Network *network = userdata;
int *index, r;
char **name;
assert(filename);
assert(section);
assert(lvalue);
assert(rvalue);
if (streq(section, "DHCPServer")) {
index = &network->dhcp_server_uplink_index;
name = &network->dhcp_server_uplink_name;
} else if (streq(section, "IPv6SendRA")) {
index = &network->router_uplink_index;
name = &network->router_uplink_name;
} else
assert_not_reached();
if (isempty(rvalue) || streq(rvalue, ":auto")) {
*index = UPLINK_INDEX_AUTO;
*name = mfree(*name);
return 0;
}
if (streq(rvalue, ":none")) {
*index = UPLINK_INDEX_NONE;
*name = mfree(*name);
return 0;
}
r = parse_ifindex(rvalue);
if (r > 0) {
*index = r;
*name = mfree(*name);
return 0;
}
if (!ifname_valid_full(rvalue, IFNAME_VALID_ALTERNATIVE)) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Invalid interface name in %s=, ignoring assignment: %s", lvalue, rvalue);
return 0;
}
/* The interface name will be resolved later. */
r = free_and_strdup_warn(name, rvalue);
if (r < 0)
return r;
/* Note, if uplink_name is set, then uplink_index will be ignored. So, the below does not mean
* an uplink interface will be selected automatically. */
*index = UPLINK_INDEX_AUTO;
return 0;
}
DEFINE_CONFIG_PARSE_ENUM(config_parse_required_family_for_online, link_required_address_family, AddressFamily, DEFINE_CONFIG_PARSE_ENUM(config_parse_required_family_for_online, link_required_address_family, AddressFamily,
"Failed to parse RequiredFamilyForOnline= setting"); "Failed to parse RequiredFamilyForOnline= setting");

View File

@ -26,10 +26,6 @@
#include "resolve-util.h" #include "resolve-util.h"
#include "socket-netlink.h" #include "socket-netlink.h"
/* Special values for *_uplink_index. */
#define UPLINK_INDEX_AUTO 0 /* uplink will be selected automatically */
#define UPLINK_INDEX_NONE -1 /* uplink will not be selected automatically */
typedef enum KeepConfiguration { typedef enum KeepConfiguration {
KEEP_CONFIGURATION_NO = 0, KEEP_CONFIGURATION_NO = 0,
KEEP_CONFIGURATION_DHCP_ON_START = 1 << 0, KEEP_CONFIGURATION_DHCP_ON_START = 1 << 0,
@ -228,8 +224,6 @@ struct Network {
struct in6_addr *router_dns; struct in6_addr *router_dns;
unsigned n_router_dns; unsigned n_router_dns;
OrderedSet *router_search_domains; OrderedSet *router_search_domains;
int router_uplink_index;
char *router_uplink_name;
/* DHCPv6 Prefix Delegation support */ /* DHCPv6 Prefix Delegation support */
int dhcp6_pd; int dhcp6_pd;
@ -370,7 +364,6 @@ CONFIG_PARSER_PROTOTYPE(config_parse_keep_configuration);
CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_link_local_address_gen_mode); CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_link_local_address_gen_mode);
CONFIG_PARSER_PROTOTYPE(config_parse_activation_policy); CONFIG_PARSER_PROTOTYPE(config_parse_activation_policy);
CONFIG_PARSER_PROTOTYPE(config_parse_link_group); CONFIG_PARSER_PROTOTYPE(config_parse_link_group);
CONFIG_PARSER_PROTOTYPE(config_parse_uplink);
const struct ConfigPerfItem* network_network_gperf_lookup(const char *key, GPERF_LEN_TYPE length); const struct ConfigPerfItem* network_network_gperf_lookup(const char *key, GPERF_LEN_TYPE length);

View File

@ -43,8 +43,6 @@ static void request_free_object(RequestType type, void *object) {
case REQUEST_TYPE_NEXTHOP: case REQUEST_TYPE_NEXTHOP:
nexthop_free(object); nexthop_free(object);
break; break;
case REQUEST_TYPE_RADV:
break;
case REQUEST_TYPE_ROUTE: case REQUEST_TYPE_ROUTE:
route_free(object); route_free(object);
break; break;
@ -112,7 +110,7 @@ static void request_hash_func(const Request *req, struct siphash *state) {
trivial_hash_func(req->object, state); trivial_hash_func(req->object, state);
break; break;
case REQUEST_TYPE_DHCP_SERVER: case REQUEST_TYPE_DHCP_SERVER:
/* This type does not have an object. */ /* This type does not have object. */
break; break;
case REQUEST_TYPE_IPV6_PROXY_NDP: case REQUEST_TYPE_IPV6_PROXY_NDP:
in6_addr_hash_func(req->ipv6_proxy_ndp, state); in6_addr_hash_func(req->ipv6_proxy_ndp, state);
@ -123,9 +121,6 @@ static void request_hash_func(const Request *req, struct siphash *state) {
case REQUEST_TYPE_NEXTHOP: case REQUEST_TYPE_NEXTHOP:
nexthop_hash_func(req->nexthop, state); nexthop_hash_func(req->nexthop, state);
break; break;
case REQUEST_TYPE_RADV:
/* This type does not have an object. */
break;
case REQUEST_TYPE_ROUTE: case REQUEST_TYPE_ROUTE:
route_hash_func(req->route, state); route_hash_func(req->route, state);
break; break;
@ -179,8 +174,6 @@ static int request_compare_func(const struct Request *a, const struct Request *b
return nexthop_compare_func(a->nexthop, b->nexthop); return nexthop_compare_func(a->nexthop, b->nexthop);
case REQUEST_TYPE_ROUTE: case REQUEST_TYPE_ROUTE:
return route_compare_func(a->route, b->route); return route_compare_func(a->route, b->route);
case REQUEST_TYPE_RADV:
return 0;
case REQUEST_TYPE_ROUTING_POLICY_RULE: case REQUEST_TYPE_ROUTING_POLICY_RULE:
return routing_policy_rule_compare_func(a->rule, b->rule); return routing_policy_rule_compare_func(a->rule, b->rule);
case REQUEST_TYPE_SET_LINK: case REQUEST_TYPE_SET_LINK:
@ -218,14 +211,10 @@ int link_queue_request(
assert(IN_SET(type, assert(IN_SET(type,
REQUEST_TYPE_ACTIVATE_LINK, REQUEST_TYPE_ACTIVATE_LINK,
REQUEST_TYPE_DHCP_SERVER, REQUEST_TYPE_DHCP_SERVER,
REQUEST_TYPE_RADV,
REQUEST_TYPE_SET_LINK, REQUEST_TYPE_SET_LINK,
REQUEST_TYPE_UP_DOWN) || REQUEST_TYPE_UP_DOWN) ||
object); object);
assert(IN_SET(type, assert(type == REQUEST_TYPE_DHCP_SERVER || netlink_handler);
REQUEST_TYPE_DHCP_SERVER,
REQUEST_TYPE_RADV) ||
netlink_handler);
req = new(Request, 1); req = new(Request, 1);
if (!req) { if (!req) {
@ -309,9 +298,6 @@ int manager_process_requests(sd_event_source *s, void *userdata) {
case REQUEST_TYPE_NEXTHOP: case REQUEST_TYPE_NEXTHOP:
r = request_process_nexthop(req); r = request_process_nexthop(req);
break; break;
case REQUEST_TYPE_RADV:
r = request_process_radv(req);
break;
case REQUEST_TYPE_ROUTE: case REQUEST_TYPE_ROUTE:
r = request_process_route(req); r = request_process_route(req);
break; break;

View File

@ -31,7 +31,6 @@ typedef enum RequestType {
REQUEST_TYPE_IPV6_PROXY_NDP, REQUEST_TYPE_IPV6_PROXY_NDP,
REQUEST_TYPE_NEIGHBOR, REQUEST_TYPE_NEIGHBOR,
REQUEST_TYPE_NEXTHOP, REQUEST_TYPE_NEXTHOP,
REQUEST_TYPE_RADV,
REQUEST_TYPE_ROUTE, REQUEST_TYPE_ROUTE,
REQUEST_TYPE_ROUTING_POLICY_RULE, REQUEST_TYPE_ROUTING_POLICY_RULE,
REQUEST_TYPE_SET_LINK, REQUEST_TYPE_SET_LINK,

View File

@ -10,7 +10,6 @@
#include "networkd-link.h" #include "networkd-link.h"
#include "networkd-manager.h" #include "networkd-manager.h"
#include "networkd-network.h" #include "networkd-network.h"
#include "networkd-queue.h"
#include "networkd-radv.h" #include "networkd-radv.h"
#include "parse-util.h" #include "parse-util.h"
#include "string-util.h" #include "string-util.h"
@ -584,7 +583,10 @@ static int radv_set_dns(Link *link, Link *uplink) {
goto set_dns; goto set_dns;
if (uplink) { if (uplink) {
assert(uplink->network); if (!uplink->network) {
log_link_debug(uplink, "Cannot fetch DNS servers as uplink interface is not managed by us");
return 0;
}
r = network_get_ipv6_dns(uplink->network, &dns, &n_dns); r = network_get_ipv6_dns(uplink->network, &dns, &n_dns);
if (r > 0) if (r > 0)
@ -593,7 +595,7 @@ static int radv_set_dns(Link *link, Link *uplink) {
return 0; return 0;
set_dns: set_dns:
return sd_radv_set_rdnss(link->radv, return sd_radv_set_rdnss(link->radv,
DIV_ROUND_UP(lifetime_usec, USEC_PER_SEC), DIV_ROUND_UP(lifetime_usec, USEC_PER_SEC),
dns, n_dns); dns, n_dns);
@ -620,7 +622,10 @@ static int radv_set_domains(Link *link, Link *uplink) {
goto set_domains; goto set_domains;
if (uplink) { if (uplink) {
assert(uplink->network); if (!uplink->network) {
log_link_debug(uplink, "Cannot fetch DNS search domains as uplink interface is not managed by us");
return 0;
}
search_domains = uplink->network->search_domains; search_domains = uplink->network->search_domains;
if (search_domains) if (search_domains)
@ -629,7 +634,7 @@ static int radv_set_domains(Link *link, Link *uplink) {
return 0; return 0;
set_domains: set_domains:
s = ordered_set_get_strv(search_domains); s = ordered_set_get_strv(search_domains);
if (!s) if (!s)
return log_oom(); return log_oom();
@ -640,23 +645,20 @@ set_domains:
} }
static int radv_find_uplink(Link *link, Link **ret) { int radv_emit_dns(Link *link) {
assert(link); Link *uplink = NULL;
int r;
if (link->network->router_uplink_name) (void) manager_find_uplink(link->manager, AF_INET6, link, &uplink);
return link_get_by_name(link->manager, link->network->router_uplink_name, ret);
if (link->network->router_uplink_index > 0) r = radv_set_dns(link, uplink);
return link_get_by_index(link->manager, link->network->router_uplink_index, ret); if (r < 0)
log_link_warning_errno(link, r, "Could not set RA DNS: %m");
if (link->network->router_uplink_index == UPLINK_INDEX_AUTO) { r = radv_set_domains(link, uplink);
/* It is not necessary to propagate error in automatic selection. */ if (r < 0)
if (manager_find_uplink(link->manager, AF_INET6, link, ret) < 0) log_link_warning_errno(link, r, "Could not set RA Domains: %m");
*ret = NULL;
return 0;
}
*ret = NULL;
return 0; return 0;
} }
@ -669,9 +671,8 @@ static bool link_radv_enabled(Link *link) {
return link->network->router_prefix_delegation; return link->network->router_prefix_delegation;
} }
static int radv_configure(Link *link) { int radv_configure(Link *link) {
uint16_t router_lifetime; uint16_t router_lifetime;
Link *uplink = NULL;
RoutePrefix *q; RoutePrefix *q;
Prefix *p; Prefix *p;
int r; int r;
@ -679,6 +680,9 @@ static int radv_configure(Link *link) {
assert(link); assert(link);
assert(link->network); assert(link->network);
if (!link_radv_enabled(link))
return 0;
if (link->radv) if (link->radv)
return -EBUSY; return -EBUSY;
@ -744,16 +748,6 @@ static int radv_configure(Link *link) {
return r; return r;
} }
(void) radv_find_uplink(link, &uplink);
r = radv_set_dns(link, uplink);
if (r < 0)
return log_link_debug_errno(link, r, "Could not set RA DNS: %m");
r = radv_set_domains(link, uplink);
if (r < 0)
return log_link_debug_errno(link, r, "Could not set RA Domains: %m");
return 0; return 0;
} }
@ -785,96 +779,6 @@ int radv_update_mac(Link *link) {
return 0; return 0;
} }
static int radv_is_ready_to_configure(Link *link) {
bool needs_uplink = false;
int r;
assert(link);
assert(link->network);
if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
return false;
if (in6_addr_is_null(&link->ipv6ll_address))
return false;
if (link->network->router_emit_dns && !link->network->router_dns) {
_cleanup_free_ struct in6_addr *dns = NULL;
size_t n_dns;
r = network_get_ipv6_dns(link->network, &dns, &n_dns);
if (r < 0)
return r;
needs_uplink = r == 0;
}
if (link->network->router_emit_domains &&
!link->network->router_search_domains &&
!link->network->search_domains)
needs_uplink = true;
if (needs_uplink) {
Link *uplink = NULL;
if (radv_find_uplink(link, &uplink) < 0)
return false;
if (uplink && !uplink->network)
return false;
}
return true;
}
int request_process_radv(Request *req) {
Link *link;
int r;
assert(req);
assert(req->link);
assert(req->type == REQUEST_TYPE_RADV);
link = req->link;
r = radv_is_ready_to_configure(link);
if (r <= 0)
return r;
r = radv_configure(link);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to configure IPv6 Router Advertisement engine: %m");
if (link_has_carrier(link)) {
r = sd_radv_start(link->radv);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to start IPv6 Router Advertisement engine: %m");
}
log_link_debug(link, "IPv6 Router Advertisement engine is configured%s.",
link_has_carrier(link) ? " and started." : "");
return 1;
}
int link_request_radv(Link *link) {
int r;
assert(link);
if (!link_radv_enabled(link))
return 0;
if (link->radv)
return 0;
r = link_queue_request(link, REQUEST_TYPE_RADV, NULL, false, NULL, NULL, NULL);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to request IPv6 Router Advertisement engine: %m");
log_link_debug(link, "IPv6 Router Advertisement engine is requested.");
return 0;
}
int radv_add_prefix( int radv_add_prefix(
Link *link, Link *link,
const struct in6_addr *prefix, const struct in6_addr *prefix,

View File

@ -14,9 +14,8 @@
#include "conf-parser.h" #include "conf-parser.h"
#include "networkd-util.h" #include "networkd-util.h"
typedef struct Link Link;
typedef struct Network Network; typedef struct Network Network;
typedef struct Request Request; typedef struct Link Link;
typedef enum RADVPrefixDelegation { typedef enum RADVPrefixDelegation {
RADV_PREFIX_DELEGATION_NONE = 0, RADV_PREFIX_DELEGATION_NONE = 0,
@ -51,13 +50,12 @@ void network_drop_invalid_prefixes(Network *network);
void network_drop_invalid_route_prefixes(Network *network); void network_drop_invalid_route_prefixes(Network *network);
void network_adjust_radv(Network *network); void network_adjust_radv(Network *network);
int radv_emit_dns(Link *link);
int radv_configure(Link *link);
int radv_update_mac(Link *link); int radv_update_mac(Link *link);
int radv_add_prefix(Link *link, const struct in6_addr *prefix, uint8_t prefix_len, int radv_add_prefix(Link *link, const struct in6_addr *prefix, uint8_t prefix_len,
uint32_t lifetime_preferred, uint32_t lifetime_valid); uint32_t lifetime_preferred, uint32_t lifetime_valid);
int request_process_radv(Request *req);
int link_request_radv(Link *link);
const char* radv_prefix_delegation_to_string(RADVPrefixDelegation i) _const_; const char* radv_prefix_delegation_to_string(RADVPrefixDelegation i) _const_;
RADVPrefixDelegation radv_prefix_delegation_from_string(const char *s) _pure_; RADVPrefixDelegation radv_prefix_delegation_from_string(const char *s) _pure_;

View File

@ -307,7 +307,6 @@ EmitDNS=
EmitDomains= EmitDomains=
Managed= Managed=
OtherInformation= OtherInformation=
UplinkInterface=
[IPv6PrefixDelegation] [IPv6PrefixDelegation]
RouterPreference= RouterPreference=
DNSLifetimeSec= DNSLifetimeSec=

View File

@ -1,7 +0,0 @@
[NetDev]
Name=vxlan97
Kind=vxlan
[VXLAN]
VNI=4831583
Local=fe80::281:8eff:fef0:73aa

View File

@ -13,7 +13,3 @@ Prefix=2002:da8:1:0::/64
[DHCPServer] [DHCPServer]
DNS=192.168.5.1 DNS=192.168.5.1
NTP=192.168.5.1 NTP=192.168.5.1
[IPv6SendRA]
EmitDNS=no
EmitDomains=no

View File

@ -9,4 +9,3 @@ IPv6AcceptRA=yes
RouterDenyList=2001::1 RouterDenyList=2001::1
PrefixDenyList=2001:db8:0:2:: PrefixDenyList=2001:db8:0:2::
RouteDenyList=2001:db1:fff:: RouteDenyList=2001:db1:fff::
UseDomains=yes

View File

@ -11,4 +11,3 @@ PrefixAllowList=2001:db8:0:1:: 2001:db8:0:1::
PrefixDenyList=2001:db8:0:1:: 2001:db8:0:1:: PrefixDenyList=2001:db8:0:1:: 2001:db8:0:1::
RouteAllowList=2001:db0:fff:: 2001:db0:fff:: RouteAllowList=2001:db0:fff:: 2001:db0:fff::
RouteDenyList=2001:db0:fff:: 2001:db0:fff:: RouteDenyList=2001:db0:fff:: 2001:db0:fff::
UseDomains=yes

View File

@ -5,9 +5,6 @@ Name=veth99
DHCP=no DHCP=no
IPv6SendRA=yes IPv6SendRA=yes
[IPv6SendRA]
UplinkInterface=dummy98
[IPv6Prefix] [IPv6Prefix]
Prefix=2001:db8:0:1::/64 Prefix=2001:db8:0:1::/64

View File

@ -1,8 +0,0 @@
[Match]
Name=dummy98
[Network]
IPv6AcceptRA=no
Address=2001:db8:1:1::1/64
DNS=2001:db8:1:1::2
Domains=example.com

View File

@ -1,24 +0,0 @@
[Match]
Name=vxlan97
[Network]
IPv6AcceptRA=no
LinkLocalAddressing=yes
[BridgeFDB]
MACAddress=00:00:00:00:00:00
Destination=fe80::27c:16ff:fec0:6c74
OutgoingInterface=test1
VNI=4831583
[BridgeFDB]
MACAddress=00:00:00:00:00:00
Destination=fe80::2a2:e4ff:fef9:2269
OutgoingInterface=test1
VNI=4831583
[BridgeFDB]
MACAddress=00:00:00:00:00:00
Destination=fe80::23b:d2ff:fe95:967f
OutgoingInterface=test1
VNI=4831583

View File

@ -5,4 +5,3 @@ Name=test1
IPv6AcceptRA=false IPv6AcceptRA=false
LinkLocalAddressing=yes LinkLocalAddressing=yes
VXLAN=vxlan99 VXLAN=vxlan99
VXLAN=vxlan97

View File

@ -854,7 +854,6 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
'vtitun98', 'vtitun98',
'vtitun99', 'vtitun99',
'vxcan99', 'vxcan99',
'vxlan97',
'vxlan98', 'vxlan98',
'vxlan99', 'vxlan99',
'wg97', 'wg97',
@ -945,7 +944,6 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
'25-vti-tunnel.netdev', '25-vti-tunnel.netdev',
'25-vxcan.netdev', '25-vxcan.netdev',
'25-vxlan-independent.netdev', '25-vxlan-independent.netdev',
'25-vxlan-ipv6.netdev',
'25-vxlan.netdev', '25-vxlan.netdev',
'25-wireguard-23-peers.netdev', '25-wireguard-23-peers.netdev',
'25-wireguard-23-peers.network', '25-wireguard-23-peers.network',
@ -976,7 +974,6 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
'sit.network', 'sit.network',
'vti6.network', 'vti6.network',
'vti.network', 'vti.network',
'vxlan-ipv6.network',
'vxlan-test1.network', 'vxlan-test1.network',
'vxlan.network', 'vxlan.network',
'xfrm.network', 'xfrm.network',
@ -1638,43 +1635,36 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
def test_vxlan(self): def test_vxlan(self):
copy_unit_to_networkd_unit_path('25-vxlan.netdev', 'vxlan.network', copy_unit_to_networkd_unit_path('25-vxlan.netdev', 'vxlan.network',
'25-vxlan-ipv6.netdev', 'vxlan-ipv6.network',
'25-vxlan-independent.netdev', 'netdev-link-local-addressing-yes.network', '25-vxlan-independent.netdev', 'netdev-link-local-addressing-yes.network',
'11-dummy.netdev', 'vxlan-test1.network') '11-dummy.netdev', 'vxlan-test1.network')
start_networkd() start_networkd()
self.wait_online(['test1:degraded', 'vxlan99:degraded', 'vxlan98:degraded', 'vxlan97:degraded']) self.wait_online(['test1:degraded', 'vxlan99:degraded', 'vxlan98:degraded'])
output = check_output('ip -d link show vxlan99') output = check_output('ip -d link show vxlan99')
print(output) print(output)
self.assertIn('999', output) self.assertRegex(output, '999')
self.assertIn('5555', output) self.assertRegex(output, '5555')
self.assertIn('l2miss', output) self.assertRegex(output, 'l2miss')
self.assertIn('l3miss', output) self.assertRegex(output, 'l3miss')
self.assertIn('udpcsum', output) self.assertRegex(output, 'udpcsum')
self.assertIn('udp6zerocsumtx', output) self.assertRegex(output, 'udp6zerocsumtx')
self.assertIn('udp6zerocsumrx', output) self.assertRegex(output, 'udp6zerocsumrx')
self.assertIn('remcsumtx', output) self.assertRegex(output, 'remcsumtx')
self.assertIn('remcsumrx', output) self.assertRegex(output, 'remcsumrx')
self.assertIn('gbp', output) self.assertRegex(output, 'gbp')
output = check_output('bridge fdb show dev vxlan99') output = check_output('bridge fdb show dev vxlan99')
print(output) print(output)
self.assertIn('00:11:22:33:44:55 dst 10.0.0.5 self permanent', output) self.assertRegex(output, '00:11:22:33:44:55 dst 10.0.0.5 self permanent')
self.assertIn('00:11:22:33:44:66 dst 10.0.0.6 self permanent', output) self.assertRegex(output, '00:11:22:33:44:66 dst 10.0.0.6 self permanent')
self.assertIn('00:11:22:33:44:77 dst 10.0.0.7 via test1 self permanent', output) self.assertRegex(output, '00:11:22:33:44:77 dst 10.0.0.7 via test1 self permanent')
output = check_output(*networkctl_cmd, '-n', '0', 'status', 'vxlan99', env=env) output = check_output(*networkctl_cmd, '-n', '0', 'status', 'vxlan99', env=env)
print(output) print(output)
self.assertIn('VNI: 999', output) self.assertRegex(output, 'VNI: 999')
self.assertIn('Destination Port: 5555', output) self.assertRegex(output, 'Destination Port: 5555')
self.assertIn('Underlying Device: test1', output) self.assertRegex(output, 'Underlying Device: test1')
output = check_output('bridge fdb show dev vxlan97')
print(output)
self.assertIn('00:00:00:00:00:00 dst fe80::23b:d2ff:fe95:967f via test1 self permanent', output)
self.assertIn('00:00:00:00:00:00 dst fe80::27c:16ff:fec0:6c74 via test1 self permanent', output)
self.assertIn('00:00:00:00:00:00 dst fe80::2a2:e4ff:fef9:2269 via test1 self permanent', output)
def test_macsec(self): def test_macsec(self):
copy_unit_to_networkd_unit_path('25-macsec.netdev', '25-macsec.network', '25-macsec.key', copy_unit_to_networkd_unit_path('25-macsec.netdev', '25-macsec.network', '25-macsec.key',
@ -4695,19 +4685,14 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99') self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
class NetworkdIPv6PrefixTests(unittest.TestCase, Utilities): class NetworkdIPv6PrefixTests(unittest.TestCase, Utilities):
links = [ links = ['veth99']
'dummy98',
'veth99',
]
units = [ units = [
'12-dummy.netdev',
'25-veth.netdev', '25-veth.netdev',
'ipv6ra-prefix-client-deny-list.network', 'ipv6ra-prefix-client-deny-list.network',
'ipv6ra-prefix-client.network', 'ipv6ra-prefix-client.network',
'ipv6ra-prefix.network', 'ipv6ra-prefix.network'
'ipv6ra-uplink.network', ]
]
def setUp(self): def setUp(self):
remove_links(self.links) remove_links(self.links)
@ -4720,11 +4705,10 @@ class NetworkdIPv6PrefixTests(unittest.TestCase, Utilities):
stop_networkd(show_logs=True) stop_networkd(show_logs=True)
def test_ipv6_route_prefix(self): def test_ipv6_route_prefix(self):
copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6ra-prefix-client.network', 'ipv6ra-prefix.network', copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6ra-prefix-client.network', 'ipv6ra-prefix.network')
'12-dummy.netdev', 'ipv6ra-uplink.network')
start_networkd() start_networkd()
self.wait_online(['veth99:routable', 'veth-peer:routable', 'dummy98:routable']) self.wait_online(['veth99:routable', 'veth-peer:routable'])
output = check_output('ip address show dev veth-peer') output = check_output('ip address show dev veth-peer')
print(output) print(output)
@ -4743,20 +4727,11 @@ class NetworkdIPv6PrefixTests(unittest.TestCase, Utilities):
self.assertNotIn('inet6 2001:db8:0:1:', output) self.assertNotIn('inet6 2001:db8:0:1:', output)
self.assertIn('inet6 2001:db8:0:2:', output) self.assertIn('inet6 2001:db8:0:2:', output)
output = check_output(*resolvectl_cmd, 'dns', 'veth-peer', env=env)
print(output)
self.assertRegex(output, '2001:db8:1:1::2')
output = check_output(*resolvectl_cmd, 'domain', 'veth-peer', env=env)
print(output)
self.assertIn('example.com', output)
def test_ipv6_route_prefix_deny_list(self): def test_ipv6_route_prefix_deny_list(self):
copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6ra-prefix-client-deny-list.network', 'ipv6ra-prefix.network', copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6ra-prefix-client-deny-list.network', 'ipv6ra-prefix.network')
'12-dummy.netdev', 'ipv6ra-uplink.network')
start_networkd() start_networkd()
self.wait_online(['veth99:routable', 'veth-peer:routable', 'dummy98:routable']) self.wait_online(['veth99:routable', 'veth-peer:routable'])
output = check_output('ip address show dev veth-peer') output = check_output('ip address show dev veth-peer')
print(output) print(output)
@ -4775,14 +4750,6 @@ class NetworkdIPv6PrefixTests(unittest.TestCase, Utilities):
self.assertNotIn('inet6 2001:db8:0:1:', output) self.assertNotIn('inet6 2001:db8:0:1:', output)
self.assertIn('inet6 2001:db8:0:2:', output) self.assertIn('inet6 2001:db8:0:2:', output)
output = check_output(*resolvectl_cmd, 'dns', 'veth-peer', env=env)
print(output)
self.assertRegex(output, '2001:db8:1:1::2')
output = check_output(*resolvectl_cmd, 'domain', 'veth-peer', env=env)
print(output)
self.assertIn('example.com', output)
class NetworkdMTUTests(unittest.TestCase, Utilities): class NetworkdMTUTests(unittest.TestCase, Utilities):
links = ['dummy98'] links = ['dummy98']