mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-12-22 13:33:56 +03:00
network: introduce UplinkInterface= in [IPv6SendRA]
This commit is contained in:
parent
a254fab20d
commit
63295b42ae
@ -2586,18 +2586,28 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
|
||||
for details. Defaults to <literal>medium</literal>.</para></listitem>
|
||||
</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>
|
||||
<term><varname>EmitDNS=</varname></term>
|
||||
<term><varname>DNS=</varname></term>
|
||||
|
||||
<listitem><para><varname>DNS=</varname> specifies a list of recursive DNS server IPv6 addresses that
|
||||
are distributed via Router Advertisement messages when <varname>EmitDNS=</varname> is
|
||||
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 read
|
||||
from the [Network] section. If the [Network] section does not contain any DNS servers either, DNS
|
||||
servers from the uplink with the highest priority default route are used. When
|
||||
<varname>EmitDNS=</varname> is false, no DNS server information is sent in Router Advertisement
|
||||
messages. <varname>EmitDNS=</varname> defaults to true.</para></listitem>
|
||||
<listitem><para><varname>DNS=</varname> specifies a list of recursive DNS server IPv6 addresses
|
||||
that are distributed via Router Advertisement messages when <varname>EmitDNS=</varname> is 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
|
||||
read from the [Network] section. If the [Network] section does not contain any DNS servers
|
||||
either, DNS servers from the uplink interface specified in <varname>UplinkInterface=</varname>
|
||||
will be used. When <varname>EmitDNS=</varname> is false, no DNS server information is sent in
|
||||
Router Advertisement messages. <varname>EmitDNS=</varname> defaults to true.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
@ -2605,11 +2615,12 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
|
||||
<term><varname>Domains=</varname></term>
|
||||
|
||||
<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 domains
|
||||
are read from the [Network] section. If the [Network] section does not contain any DNS search domains
|
||||
either, DNS search domains from the uplink with the highest priority default route are used. When
|
||||
<varname>EmitDomains=</varname> is false, no DNS search domain information is sent in Router
|
||||
Advertisement messages. <varname>EmitDomains=</varname> defaults to true.</para></listitem>
|
||||
<varname>EmitDomains=</varname> is true. If <varname>Domains=</varname> is empty, DNS search
|
||||
domains are read from the [Network] section. If the [Network] section does not contain any DNS
|
||||
search domains either, DNS search domains from the uplink interface specified in
|
||||
<varname>UplinkInterface=</varname> will be used. When <varname>EmitDomains=</varname> is false,
|
||||
no DNS search domain information is sent in Router Advertisement messages.
|
||||
<varname>EmitDomains=</varname> defaults to true.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
|
@ -106,7 +106,7 @@ static int dhcp_server_find_uplink(Link *link, Link **ret) {
|
||||
if (link->network->dhcp_server_uplink_index > 0)
|
||||
return link_get_by_index(link->manager, link->network->dhcp_server_uplink_index, ret);
|
||||
|
||||
if (link->network->dhcp_server_uplink_index == 0) {
|
||||
if (link->network->dhcp_server_uplink_index == UPLINK_INDEX_AUTO) {
|
||||
/* It is not necessary to propagate error in automatic selection. */
|
||||
if (manager_find_uplink(link->manager, AF_INET, link, ret) < 0)
|
||||
*ret = NULL;
|
||||
@ -663,55 +663,3 @@ int config_parse_dhcp_server_address(
|
||||
network->dhcp_server_address_prefixlen = prefixlen;
|
||||
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;
|
||||
}
|
||||
|
@ -15,4 +15,3 @@ int request_process_dhcp_server(Request *req);
|
||||
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_address);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_uplink);
|
||||
|
@ -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.RouteDenyList, config_parse_ndisc_address_filter, 0, offsetof(Network, ndisc_deny_listed_route_prefix)
|
||||
DHCPServer.ServerAddress, config_parse_dhcp_server_address, 0, 0
|
||||
DHCPServer.UplinkInterface, config_parse_dhcp_server_uplink, 0, 0
|
||||
DHCPServer.UplinkInterface, config_parse_uplink, 0, 0
|
||||
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.RelayAgentRemoteId, config_parse_dhcp_server_relay_agent_suboption, 0, offsetof(Network, dhcp_server_relay_agent_remote_id)
|
||||
@ -333,6 +333,7 @@ IPv6SendRA.DNS, config_parse_radv_dns,
|
||||
IPv6SendRA.EmitDomains, config_parse_bool, 0, offsetof(Network, router_emit_domains)
|
||||
IPv6SendRA.Domains, config_parse_radv_search_domains, 0, 0
|
||||
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.OnLink, config_parse_prefix_flags, 0, 0
|
||||
IPv6Prefix.AddressAutoconfiguration, config_parse_prefix_flags, 0, 0
|
||||
|
@ -640,6 +640,7 @@ static Network *network_free(Network *network) {
|
||||
|
||||
free(network->dhcp_server_timezone);
|
||||
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++)
|
||||
free(network->dhcp_server_emit[t].addresses);
|
||||
@ -1185,6 +1186,73 @@ int config_parse_link_group(
|
||||
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,
|
||||
"Failed to parse RequiredFamilyForOnline= setting");
|
||||
|
||||
|
@ -26,6 +26,10 @@
|
||||
#include "resolve-util.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 {
|
||||
KEEP_CONFIGURATION_NO = 0,
|
||||
KEEP_CONFIGURATION_DHCP_ON_START = 1 << 0,
|
||||
@ -224,6 +228,8 @@ struct Network {
|
||||
struct in6_addr *router_dns;
|
||||
unsigned n_router_dns;
|
||||
OrderedSet *router_search_domains;
|
||||
int router_uplink_index;
|
||||
char *router_uplink_name;
|
||||
|
||||
/* DHCPv6 Prefix Delegation support */
|
||||
int dhcp6_pd;
|
||||
@ -364,6 +370,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_keep_configuration);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_link_local_address_gen_mode);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_activation_policy);
|
||||
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);
|
||||
|
||||
|
@ -584,10 +584,7 @@ static int radv_set_dns(Link *link, Link *uplink) {
|
||||
goto set_dns;
|
||||
|
||||
if (uplink) {
|
||||
if (!uplink->network) {
|
||||
log_link_debug(uplink, "Cannot fetch DNS servers as uplink interface is not managed by us");
|
||||
return 0;
|
||||
}
|
||||
assert(uplink->network);
|
||||
|
||||
r = network_get_ipv6_dns(uplink->network, &dns, &n_dns);
|
||||
if (r > 0)
|
||||
@ -623,10 +620,7 @@ static int radv_set_domains(Link *link, Link *uplink) {
|
||||
goto set_domains;
|
||||
|
||||
if (uplink) {
|
||||
if (!uplink->network) {
|
||||
log_link_debug(uplink, "Cannot fetch DNS search domains as uplink interface is not managed by us");
|
||||
return 0;
|
||||
}
|
||||
assert(uplink->network);
|
||||
|
||||
search_domains = uplink->network->search_domains;
|
||||
if (search_domains)
|
||||
@ -646,6 +640,26 @@ set_domains:
|
||||
|
||||
}
|
||||
|
||||
static int radv_find_uplink(Link *link, Link **ret) {
|
||||
assert(link);
|
||||
|
||||
if (link->network->router_uplink_name)
|
||||
return link_get_by_name(link->manager, link->network->router_uplink_name, ret);
|
||||
|
||||
if (link->network->router_uplink_index > 0)
|
||||
return link_get_by_index(link->manager, link->network->router_uplink_index, ret);
|
||||
|
||||
if (link->network->router_uplink_index == UPLINK_INDEX_AUTO) {
|
||||
/* It is not necessary to propagate error in automatic selection. */
|
||||
if (manager_find_uplink(link->manager, AF_INET6, link, ret) < 0)
|
||||
*ret = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*ret = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool link_radv_enabled(Link *link) {
|
||||
assert(link);
|
||||
|
||||
@ -730,7 +744,7 @@ static int radv_configure(Link *link) {
|
||||
return r;
|
||||
}
|
||||
|
||||
(void) manager_find_uplink(link->manager, AF_INET6, link, &uplink);
|
||||
(void) radv_find_uplink(link, &uplink);
|
||||
|
||||
r = radv_set_dns(link, uplink);
|
||||
if (r < 0)
|
||||
@ -771,7 +785,10 @@ int radv_update_mac(Link *link) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool radv_is_ready_to_configure(Link *link) {
|
||||
static int radv_is_ready_to_configure(Link *link) {
|
||||
bool needs_uplink = false;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->network);
|
||||
|
||||
@ -781,6 +798,32 @@ static bool radv_is_ready_to_configure(Link *link) {
|
||||
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;
|
||||
}
|
||||
|
||||
@ -794,8 +837,9 @@ int request_process_radv(Request *req) {
|
||||
|
||||
link = req->link;
|
||||
|
||||
if (!radv_is_ready_to_configure(link))
|
||||
return 0;
|
||||
r = radv_is_ready_to_configure(link);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
r = radv_configure(link);
|
||||
if (r < 0)
|
||||
|
@ -307,6 +307,7 @@ EmitDNS=
|
||||
EmitDomains=
|
||||
Managed=
|
||||
OtherInformation=
|
||||
UplinkInterface=
|
||||
[IPv6PrefixDelegation]
|
||||
RouterPreference=
|
||||
DNSLifetimeSec=
|
||||
|
Loading…
Reference in New Issue
Block a user