Compare commits

...

11 Commits

Author SHA1 Message Date
Zbigniew Jędrzejewski-Szmek 93a59b1ae5 sd-bus: break the loop in bus_ensure_running() if the bus is not connecting
This might fix #17025:
> the call trace is
> bus_ensure_running -> sd_bus_process -> bus_process_internal -> process_closeing --> sd_bus_close
>                                                                                  |
>                                                                                  \-> process_match

We ended doing callouts to the Disconnected matches from bus_ensure_running()
and shouldn't. bus_ensure_running() should never do callouts. This change
should fix this however: once we notice that the connection is going down we
will now fail instantly with ENOTOCONN instead of calling any callbacks.
2020-10-15 11:15:03 +09:00
Yu Watanabe 720f477f2d
Merge pull request #17317 from yuwata/network-gateway-dhcp4-ra
network: about Gateway=_dhcp4 or _ipv6ra
2020-10-15 09:11:59 +09:00
Yu Watanabe 9087e3d609 test-network: do not use deprecated value 2020-10-15 07:08:27 +09:00
Yu Watanabe 956dbf361b network: warn if dynamic gateway is specified but corresponding protocol is disabled 2020-10-15 07:07:46 +09:00
Yu Watanabe 22d37e5df6 network: introduce network_adjust_dhcp() 2020-10-15 07:06:58 +09:00
Yu Watanabe 3773eb5485 network: introduce network_adjust_ipv6_accept_ra() 2020-10-15 07:06:36 +09:00
Yu Watanabe c27abcf4fb network: when Gateway=_dhcp4, set several properties based on lease if they are not explicitly specified
Before this commit, event when Gateway=_dhcp4 or _ra is set, the
route was configured with 'protocol static', and other properties
specified by RouteTable=, RouteMTU=, or etc, were ignored.

This commit makes set the route protocol based on the protocol the
gateway address is obtained, and apply other settings if it is not
explicitly specified in the [Route] section.
2020-10-15 07:06:23 +09:00
Yu Watanabe 5bb80a4603 network: determine a [Route] section will be used or not by gateway family instead of route family
By this commit, user can configure dynamic IPv6 Gateway with IPv4
destination.
2020-10-15 07:06:03 +09:00
Yu Watanabe c3d679c43f network: when Gateway=_dhcp, assume gateway family based on other settings 2020-10-15 07:05:58 +09:00
Yu Watanabe b8caa4ef34 network: rename Gateway=_dhcp6 -> Gateway=_ipv6ra 2020-10-15 07:04:02 +09:00
Yu Watanabe 1a3a6309a7 network: rename gateway_from_dhcp -> gateway_from_dhcp_or_ra
As for IPv6 case gateway is given by RA.
2020-10-15 06:58:53 +09:00
15 changed files with 147 additions and 85 deletions

View File

@ -1283,9 +1283,8 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
<term><varname>Gateway=</varname></term>
<listitem>
<para>Takes the gateway address or the special values <literal>_dhcp4</literal> and
<literal>_dhcp6</literal>. If <literal>_dhcp4</literal> or <literal>_dhcp6</literal> is
set, then the gateway address provided by DHCP (or in the IPv6 case, provided by IPv6 RA)
is used.</para>
<literal>_ipv6ra</literal>. If <literal>_dhcp4</literal> or <literal>_ipv6ra</literal> is
set, then the gateway address provided by DHCPv4 or IPv6 RA is used.</para>
</listitem>
</varlistentry>
<varlistentry>

View File

@ -2120,12 +2120,13 @@ int bus_ensure_running(sd_bus *bus) {
assert(bus);
if (IN_SET(bus->state, BUS_UNSET, BUS_CLOSED, BUS_CLOSING))
return -ENOTCONN;
if (bus->state == BUS_RUNNING)
return 1;
for (;;) {
if (IN_SET(bus->state, BUS_UNSET, BUS_CLOSED, BUS_CLOSING))
return -ENOTCONN;
r = sd_bus_process(bus, NULL);
if (r < 0)
return r;

View File

@ -26,18 +26,38 @@ bool link_dhcp_enabled(Link *link, int family) {
if (link->flags & IFF_LOOPBACK)
return false;
if (!link->network)
return false;
if (link->network->bond)
return false;
if (link->iftype == ARPHRD_CAN)
return false;
if (!link->network)
return false;
return link->network->dhcp & (family == AF_INET ? ADDRESS_FAMILY_IPV4 : ADDRESS_FAMILY_IPV6);
}
void network_adjust_dhcp(Network *network) {
assert(network);
assert(network->dhcp >= 0);
if (network->dhcp == ADDRESS_FAMILY_NO)
return;
/* Bonding slave does not support addressing. */
if (network->bond) {
log_warning("%s: Cannot enable DHCP= when Bond= is specified, disabling DHCP=.",
network->filename);
network->dhcp = ADDRESS_FAMILY_NO;
return;
}
if (!FLAGS_SET(network->link_local, ADDRESS_FAMILY_IPV6) &&
FLAGS_SET(network->dhcp, ADDRESS_FAMILY_IPV6)) {
log_warning("%s: DHCPv6 client is enabled but IPv6 link local addressing is disabled. "
"Disabling DHCPv6 client.", network->filename);
SET_FLAG(network->dhcp, ADDRESS_FAMILY_IPV6, false);
}
}
DUID* link_get_duid(Link *link) {
if (link->network->duid.type != _DUID_TYPE_INVALID)
return &link->network->duid;

View File

@ -9,6 +9,7 @@
typedef struct Link Link;
typedef struct Manager Manager;
typedef struct Network Network;
typedef enum DHCPUseDomains {
DHCP_USE_DOMAINS_NO,
@ -46,6 +47,8 @@ static inline bool link_dhcp6_enabled(Link *link) {
return link_dhcp_enabled(link, AF_INET6);
}
void network_adjust_dhcp(Network *network);
DUID* link_get_duid(Link *link);
int link_configure_duid(Link *link);
int manager_request_product_uuid(Manager *m, Link *link);

View File

@ -388,14 +388,21 @@ static int link_set_dhcp_routes(Link *link) {
return log_link_error_errno(link, r, "Could not set router: %m");
HASHMAP_FOREACH(rt, link->network->routes_by_section) {
if (!rt->gateway_from_dhcp)
if (!rt->gateway_from_dhcp_or_ra)
continue;
if (rt->family != AF_INET)
if (rt->gw_family != AF_INET)
continue;
rt->gw_family = AF_INET;
rt->gw.in = router[0];
if (!rt->protocol_set)
rt->protocol = RTPROT_DHCP;
if (!rt->priority_set)
rt->priority = link->network->dhcp_route_metric;
if (!rt->table_set)
rt->table = table;
if (rt->mtu == 0)
rt->mtu = link->network->dhcp_route_mtu;
r = dhcp_route_configure(rt, link);
if (r < 0)

View File

@ -14,7 +14,6 @@
#include "networkd-dhcp6.h"
#include "networkd-manager.h"
#include "networkd-ndisc.h"
#include "networkd-sysctl.h"
#include "string-table.h"
#include "string-util.h"
#include "strv.h"
@ -52,19 +51,23 @@ bool link_ipv6_accept_ra_enabled(Link *link) {
if (!link_ipv6ll_enabled(link))
return false;
/* If unset use system default (enabled if local forwarding is disabled.
* disabled if local forwarding is enabled).
* If set, ignore or enforce RA independent of local forwarding state.
*/
if (link->network->ipv6_accept_ra < 0)
assert(link->network->ipv6_accept_ra >= 0);
return link->network->ipv6_accept_ra;
}
void network_adjust_ipv6_accept_ra(Network *network) {
assert(network);
if (!FLAGS_SET(network->link_local, ADDRESS_FAMILY_IPV6)) {
if (network->ipv6_accept_ra > 0)
log_warning("%s: IPv6AcceptRA= is enabled but IPv6 link local addressing is disabled or not supported. "
"Disabling IPv6AcceptRA=.", network->filename);
network->ipv6_accept_ra = false;
}
if (network->ipv6_accept_ra < 0)
/* default to accept RA if ip_forward is disabled and ignore RA if ip_forward is enabled */
return !link_ip_forward_enabled(link, AF_INET6);
else if (link->network->ipv6_accept_ra > 0)
/* accept RA even if ip_forward is enabled */
return true;
else
/* ignore RA */
return false;
network->ipv6_accept_ra = !FLAGS_SET(network->ip_forward, ADDRESS_FAMILY_IPV6);
}
static int ndisc_remove_old_one(Link *link, const struct in6_addr *router, bool force);
@ -461,7 +464,7 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
union in_addr_union gateway;
uint16_t lifetime;
unsigned preference;
uint32_t mtu;
uint32_t table, mtu;
usec_t time_now;
int r;
@ -504,12 +507,14 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
else if (r < 0)
return log_link_error_errno(link, r, "Failed to get default router MTU from RA: %m");
table = link_get_ipv6_accept_ra_route_table(link);
r = route_new(&route);
if (r < 0)
return log_oom();
route->family = AF_INET6;
route->table = link_get_ipv6_accept_ra_route_table(link);
route->table = table;
route->priority = link->network->dhcp6_route_metric;
route->protocol = RTPROT_RA;
route->pref = preference;
@ -524,14 +529,24 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
Route *route_gw;
HASHMAP_FOREACH(route_gw, link->network->routes_by_section) {
if (!route_gw->gateway_from_dhcp)
if (!route_gw->gateway_from_dhcp_or_ra)
continue;
if (route_gw->family != AF_INET6)
if (route_gw->gw_family != AF_INET6)
continue;
route_gw->gw = gateway;
route_gw->gw_family = AF_INET6;
if (!route_gw->table_set)
route_gw->table = table;
if (!route_gw->priority_set)
route_gw->priority = link->network->dhcp6_route_metric;
if (!route_gw->protocol_set)
route_gw->protocol = RTPROT_RA;
if (!route_gw->pref_set)
route->pref = preference;
route_gw->lifetime = time_now + lifetime * USEC_PER_SEC;
if (route_gw->mtu == 0)
route_gw->mtu = mtu;
r = ndisc_route_configure(route_gw, link, rt);
if (r < 0)

View File

@ -71,6 +71,8 @@ static inline char* NDISC_DNSSL_DOMAIN(const NDiscDNSSL *n) {
bool link_ipv6_accept_ra_enabled(Link *link);
void network_adjust_ipv6_accept_ra(Network *network);
int ndisc_configure(Link *link);
void ndisc_vacuum(Link *link);
void ndisc_flush(Link *link);

View File

@ -16,9 +16,11 @@
#include "network-internal.h"
#include "networkd-address-label.h"
#include "networkd-address.h"
#include "networkd-dhcp-common.h"
#include "networkd-fdb.h"
#include "networkd-manager.h"
#include "networkd-mdb.h"
#include "networkd-ndisc.h"
#include "networkd-neighbor.h"
#include "networkd-network.h"
#include "networkd-nexthop.h"
@ -188,21 +190,11 @@ int network_verify(Network *network) {
if (network->bond) {
/* Bonding slave does not support addressing. */
if (network->ipv6_accept_ra > 0) {
log_warning("%s: Cannot enable IPv6AcceptRA= when Bond= is specified, disabling IPv6AcceptRA=.",
network->filename);
network->ipv6_accept_ra = 0;
}
if (network->link_local >= 0 && network->link_local != ADDRESS_FAMILY_NO) {
log_warning("%s: Cannot enable LinkLocalAddressing= when Bond= is specified, disabling LinkLocalAddressing=.",
network->filename);
network->link_local = ADDRESS_FAMILY_NO;
}
if (network->dhcp != ADDRESS_FAMILY_NO) {
log_warning("%s: Cannot enable DHCP= when Bond= is specified, disabling DHCP=.",
network->filename);
network->dhcp = ADDRESS_FAMILY_NO;
}
if (network->dhcp_server) {
log_warning("%s: Cannot enable DHCPServer= when Bond= is specified, disabling DHCPServer=.",
network->filename);
@ -223,18 +215,6 @@ int network_verify(Network *network) {
network->link_local = network->bridge ? ADDRESS_FAMILY_NO : ADDRESS_FAMILY_IPV6;
if (!FLAGS_SET(network->link_local, ADDRESS_FAMILY_IPV6)) {
if (network->ipv6_accept_ra > 0) {
log_warning("%s: IPv6AcceptRA= is enabled by the .network file but IPv6 link local addressing is disabled. "
"Disabling IPv6AcceptRA=.", network->filename);
network->ipv6_accept_ra = false;
}
if (FLAGS_SET(network->dhcp, ADDRESS_FAMILY_IPV6)) {
log_warning("%s: DHCPv6 client is enabled by the .network file but IPv6 link local addressing is disabled. "
"Disabling DHCPv6 client.", network->filename);
SET_FLAG(network->dhcp, ADDRESS_FAMILY_IPV6, false);
}
if (network->router_prefix_delegation != RADV_PREFIX_DELEGATION_NONE) {
log_warning("%s: IPv6PrefixDelegation= is enabled but IPv6 link local addressing is disabled. "
"Disabling IPv6PrefixDelegation=.", network->filename);
@ -249,13 +229,13 @@ int network_verify(Network *network) {
SET_FLAG(network->link_local, ADDRESS_FAMILY_FALLBACK_IPV4, false);
}
if (network->ipv6_accept_ra < 0 && network->bridge)
network->ipv6_accept_ra = false;
/* IPMasquerade=yes implies IPForward=yes */
if (network->ip_masquerade)
network->ip_forward |= ADDRESS_FAMILY_IPV4;
network_adjust_ipv6_accept_ra(network);
network_adjust_dhcp(network);
if (network->mtu > 0 && network->dhcp_use_mtu) {
log_warning("%s: MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set. "
"Disabling UseMTU=.", network->filename);

View File

@ -1192,7 +1192,7 @@ int link_set_routes(Link *link) {
/* First add the routes that enable us to talk to gateways, then add in the others that need a gateway. */
for (phase = 0; phase < _PHASE_MAX; phase++)
HASHMAP_FOREACH(rt, link->network->routes_by_section) {
if (rt->gateway_from_dhcp)
if (rt->gateway_from_dhcp_or_ra)
continue;
if ((in_addr_is_null(rt->gw_family, &rt->gw) && ordered_set_isempty(rt->multipath_routes)) != (phase == PHASE_NON_GATEWAY))
@ -1723,7 +1723,7 @@ int config_parse_gateway(
}
if (isempty(rvalue)) {
n->gateway_from_dhcp = false;
n->gateway_from_dhcp_or_ra = false;
n->gw_family = AF_UNSPEC;
n->gw = IN_ADDR_NULL;
TAKE_PTR(n);
@ -1731,21 +1731,21 @@ int config_parse_gateway(
}
if (streq(rvalue, "_dhcp")) {
n->gateway_from_dhcp = true;
n->gateway_from_dhcp_or_ra = true;
TAKE_PTR(n);
return 0;
}
if (streq(rvalue, "_dhcp4")) {
n->gw_family = AF_INET;
n->gateway_from_dhcp = true;
n->gateway_from_dhcp_or_ra = true;
TAKE_PTR(n);
return 0;
}
if (streq(rvalue, "_dhcp6")) {
if (streq(rvalue, "_ipv6ra")) {
n->gw_family = AF_INET6;
n->gateway_from_dhcp = true;
n->gateway_from_dhcp_or_ra = true;
TAKE_PTR(n);
return 0;
}
@ -1758,7 +1758,7 @@ int config_parse_gateway(
return 0;
}
n->gateway_from_dhcp = false;
n->gateway_from_dhcp_or_ra = false;
TAKE_PTR(n);
return 0;
}
@ -1902,6 +1902,7 @@ int config_parse_route_priority(
return 0;
}
n->priority_set = true;
TAKE_PTR(n);
return 0;
}
@ -2086,6 +2087,7 @@ int config_parse_ipv6_route_preference(
return 0;
}
n->pref_set = true;
TAKE_PTR(n);
return 0;
}
@ -2380,20 +2382,50 @@ static int route_section_verify(Route *route, Network *network) {
if (section_is_invalid(route->section))
return -EINVAL;
if (route->gateway_from_dhcp_or_ra) {
if (route->gw_family == AF_UNSPEC) {
/* When deprecated Gateway=_dhcp is set, then assume gateway family based on other settings. */
switch (route->family) {
case AF_UNSPEC:
log_warning("%s: Deprecated value \"_dhcp\" is specified for Gateway= in [Route] section from line %u. "
"Please use \"_dhcp4\" or \"_ipv6ra\" instead. Assuming \"_dhcp4\".",
route->section->filename, route->section->line);
route->family = AF_INET;
break;
case AF_INET:
case AF_INET6:
log_warning("%s: Deprecated value \"_dhcp\" is specified for Gateway= in [Route] section from line %u. "
"Assuming \"%s\" based on Destination=, Source=, or PreferredSource= setting.",
route->section->filename, route->section->line, route->family == AF_INET ? "_dhcp4" : "_ipv6ra");
break;
default:
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: Invalid route family. Ignoring [Route] section from line %u.",
route->section->filename, route->section->line);
}
route->gw_family = route->family;
}
if (route->gw_family == AF_INET && !FLAGS_SET(network->dhcp, ADDRESS_FAMILY_IPV4))
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: Gateway=\"_dhcp4\" is specified but DHCPv4 client is disabled. "
"Ignoring [Route] section from line %u.",
route->section->filename, route->section->line);
if (route->gw_family == AF_INET6 && !network->ipv6_accept_ra)
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: Gateway=\"_ipv6ra\" is specified but IPv6AcceptRA= is disabled. "
"Ignoring [Route] section from line %u.",
route->section->filename, route->section->line);
}
/* When only Gateway= is specified, assume the route family based on the Gateway address. */
if (route->family == AF_UNSPEC)
route->family = route->gw_family;
if (route->family == AF_UNSPEC) {
assert(route->section);
if (route->gateway_from_dhcp) {
log_warning("%s: Deprecated value \"_dhcp\" is specified for Gateway= in [Route] section from line %u. "
"Please use \"_dhcp4\" or \"_dhcp6\" instead. Assuming \"_dhcp4\".",
route->section->filename, route->section->line);
route->family = AF_INET;
route->gw_family = AF_INET;
} else
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: Route section without Gateway=, Destination=, Source=, "
"or PreferredSource= field configured. "

View File

@ -32,20 +32,24 @@ typedef struct Route {
unsigned char dst_prefixlen;
unsigned char src_prefixlen;
unsigned char scope;
bool scope_set;
unsigned char protocol; /* RTPROT_* */
unsigned char type; /* RTN_* */
unsigned char tos;
uint32_t priority; /* note that ip(8) calls this 'metric' */
uint32_t table;
bool table_set;
uint32_t mtu;
uint32_t initcwnd;
uint32_t initrwnd;
unsigned char pref;
unsigned flags;
int gateway_onlink;
bool gateway_from_dhcp;
bool scope_set:1;
bool table_set:1;
bool priority_set:1;
bool protocol_set:1;
bool pref_set:1;
bool gateway_from_dhcp_or_ra:1;
union in_addr_union gw;
union in_addr_union dst;

View File

@ -38,7 +38,7 @@ static int link_set_proxy_arp(Link *link) {
return sysctl_write_ip_property_boolean(AF_INET, link->ifname, "proxy_arp", link->network->proxy_arp > 0);
}
bool link_ip_forward_enabled(Link *link, int family) {
static bool link_ip_forward_enabled(Link *link, int family) {
assert(link);
assert(IN_SET(family, AF_INET, AF_INET6));

View File

@ -16,7 +16,6 @@ typedef enum IPv6PrivacyExtensions {
_IPV6_PRIVACY_EXTENSIONS_INVALID = -1,
} IPv6PrivacyExtensions;
bool link_ip_forward_enabled(Link *link, int family);
int link_set_sysctl(Link *link);
int link_set_ipv6_mtu(Link *link);

View File

@ -6,5 +6,5 @@ DHCP=ipv4
IPv6AcceptRA=no
[Route]
Gateway=_dhcp
Gateway=_dhcp4
Destination=10.0.0.0/8

View File

@ -5,5 +5,5 @@ Name=veth99
DHCP=ipv6
[Route]
Gateway=_dhcp
Gateway=_ipv6ra
Destination=2001:1234:5:9fff:ff:ff:ff:ff/128

View File

@ -3899,7 +3899,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
output = check_output('ip route list dev veth99 10.0.0.0/8')
print(output)
self.assertRegex(output, '10.0.0.0/8 via 192.168.5.1 proto static')
self.assertRegex(output, '10.0.0.0/8 via 192.168.5.1 proto dhcp')
def test_dhcp_client_gateway_ipv6(self):
copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',