From: Yu Watanabe Date: Sun, 14 Feb 2021 05:49:35 +0000 (+0900) Subject: network: nexthop: add OnLink= setting X-Git-Tag: v248-rc1~25^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2ddd52d1e2098c801231b2af1dbcf802e5d01a31;p=thirdparty%2Fsystemd.git network: nexthop: add OnLink= setting --- diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 015fcf01f99..4741e873181 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -1340,6 +1340,15 @@ IPv6Token=prefixstable:2002:da8:1:: to ipv4. + + OnLink= + + Takes a boolean. If set to true, the kernel does not have to check if the gateway is + reachable directly by the current machine (i.e., attached to the local network), so that we + can insert the nexthop in the kernel table without it being complained about. Defaults to + no. + + @@ -1361,9 +1370,9 @@ IPv6Token=prefixstable:2002:da8:1:: GatewayOnLink= Takes a boolean. If set to true, the kernel does not have to check if the gateway is - reachable directly by the current machine (i.e., the kernel does not need to check if the - gateway is attached to the local network), so that we can insert the route in the kernel - table without it being complained about. Defaults to no. + reachable directly by the current machine (i.e., attached to the local network), so that we + can insert the route in the kernel table without it being complained about. Defaults to + no. diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index e74a44b2a64..6e70e979891 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -189,6 +189,7 @@ Route.NextHop, config_parse_route_nexthop, NextHop.Id, config_parse_nexthop_id, 0, 0 NextHop.Gateway, config_parse_nexthop_gateway, 0, 0 NextHop.Family, config_parse_nexthop_family, 0, 0 +NextHop.OnLink, config_parse_nexthop_onlink, 0, 0 DHCPv4.ClientIdentifier, config_parse_dhcp_client_identifier, 0, offsetof(Network, dhcp_client_identifier) DHCPv4.UseDNS, config_parse_dhcp_use_dns, 0, 0 DHCPv4.RoutesToDNS, config_parse_bool, 0, offsetof(Network, dhcp_routes_to_dns) diff --git a/src/network/networkd-nexthop.c b/src/network/networkd-nexthop.c index 07842ae6089..f98adf468e9 100644 --- a/src/network/networkd-nexthop.c +++ b/src/network/networkd-nexthop.c @@ -47,6 +47,7 @@ static int nexthop_new(NextHop **ret) { *nexthop = (NextHop) { .family = AF_UNSPEC, + .onlink = -1, }; *ret = TAKE_PTR(nexthop); @@ -360,6 +361,12 @@ static int nexthop_configure(const NextHop *nexthop, Link *link) { r = netlink_message_append_in_addr_union(req, NHA_GATEWAY, nexthop->family, &nexthop->gw); if (r < 0) return log_link_error_errno(link, r, "Could not append NHA_GATEWAY attribute: %m"); + + if (nexthop->onlink > 0) { + r = sd_rtnl_message_nexthop_set_flags(req, RTNH_F_ONLINK); + if (r < 0) + return log_link_error_errno(link, r, "Failed to set RTNH_F_ONLINK flag: %m"); + } } r = netlink_call_async(link->manager->rtnl, NULL, req, nexthop_handler, @@ -549,6 +556,16 @@ static int nexthop_section_verify(NextHop *nh) { /* When no Gateway= is specified, assume IPv4. */ nh->family = AF_INET; + if (nh->onlink < 0 && in_addr_is_set(nh->family, &nh->gw) && + ordered_hashmap_isempty(nh->network->addresses_by_section)) { + /* If no address is configured, in most cases the gateway cannot be reachable. + * TODO: we may need to improve the condition above. */ + log_warning("%s: Gateway= without static address configured. " + "Enabling OnLink= option.", + nh->section->filename); + nh->onlink = true; + } + return 0; } @@ -722,3 +739,48 @@ int config_parse_nexthop_family( TAKE_PTR(n); return 0; } + +int config_parse_nexthop_onlink( + 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) { + + _cleanup_(nexthop_free_or_set_invalidp) NextHop *n = NULL; + Network *network = userdata; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = nexthop_new_static(network, filename, section_line, &n); + if (r < 0) + return log_oom(); + + if (isempty(rvalue)) { + n->onlink = -1; + TAKE_PTR(n); + return 0; + } + + r = parse_boolean(rvalue); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Failed to parse %s=, ignoring assignment: %s", lvalue, rvalue); + return 0; + } + + n->onlink = r; + + TAKE_PTR(n); + return 0; +} diff --git a/src/network/networkd-nexthop.h b/src/network/networkd-nexthop.h index 06673d4369d..0356e997ecb 100644 --- a/src/network/networkd-nexthop.h +++ b/src/network/networkd-nexthop.h @@ -27,6 +27,7 @@ typedef struct NextHop { uint32_t id; int family; union in_addr_union gw; + int onlink; } NextHop; NextHop *nexthop_free(NextHop *nexthop); @@ -41,3 +42,4 @@ int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, CONFIG_PARSER_PROTOTYPE(config_parse_nexthop_id); CONFIG_PARSER_PROTOTYPE(config_parse_nexthop_gateway); CONFIG_PARSER_PROTOTYPE(config_parse_nexthop_family); +CONFIG_PARSER_PROTOTYPE(config_parse_nexthop_onlink); diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index ddfa4d4df7a..aa744d54700 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -2743,9 +2743,10 @@ static int route_section_verify(Route *route, Network *network) { if (route->family == AF_INET6 && route->priority == 0) route->priority = IP6_RT_PRIO_USER; - if (ordered_hashmap_isempty(network->addresses_by_section) && - in_addr_is_set(route->gw_family, &route->gw) && - route->gateway_onlink < 0) { + if (route->gateway_onlink < 0 && in_addr_is_set(route->gw_family, &route->gw) && + ordered_hashmap_isempty(network->addresses_by_section)) { + /* If no address is configured, in most cases the gateway cannot be reachable. + * TODO: we may need to improve the condition above. */ log_warning("%s: Gateway= without static address configured. " "Enabling GatewayOnLink= option.", network->filename); diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network index 90420f42b59..04a2a4c9c19 100644 --- a/test/fuzz/fuzz-network-parser/directives.network +++ b/test/fuzz/fuzz-network-parser/directives.network @@ -352,6 +352,7 @@ SendVendorOption= Id= Gateway= Family= +OnLink= [QDisc] Parent= Handle=