]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: static routes via DHCP gateway
authorYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 7 Jan 2020 05:43:09 +0000 (14:43 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 7 Jan 2020 10:10:54 +0000 (19:10 +0900)
This makes Gateway= also take "DHCP". If "DHCP" is set, then the gateway
address provided by DHCP or IPv6 RA is used.

Closes #8213.

man/systemd.network.xml
src/network/networkd-dhcp4.c
src/network/networkd-link.c
src/network/networkd-ndisc.c
src/network/networkd-route.c
src/network/networkd-route.h

index 4cd25201737f2638c38c9cdb12017f6ae376422f..4299583fe7e1810a69c663afe0572394fda2e1c8 100644 (file)
         <varlistentry>
           <term><varname>Gateway=</varname></term>
           <listitem>
-            <para>As in the <literal>[Network]</literal> section.</para>
+            <para>Takes the gateway address or special value <literal>dhcp</literal>. If
+            <literal>dhcp</literal>, then the gateway address provided by DHCP (or in the IPv6 case,
+            provided by IPv6 RA) is used.</para>
           </listitem>
         </varlistentry>
          <varlistentry>
index 66d83e76bfae4ffd3c590999c01cc051d3b4445f..70377ad6bb5b0bd18b30397da46e161222f09cd7 100644 (file)
@@ -377,6 +377,23 @@ static int link_set_dhcp_routes(Link *link) {
                         return log_link_error_errno(link, r, "Could not set router: %m");
         }
 
+        Route *rt;
+        LIST_FOREACH(routes, rt, link->network->static_routes) {
+                if (!rt->gateway_from_dhcp)
+                        continue;
+
+                if (rt->family != AF_INET)
+                        continue;
+
+                rt->gw.in = router[0];
+
+                r = route_configure(rt, link, dhcp4_route_handler);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not set gateway: %m");
+                if (r > 0)
+                        link->dhcp4_messages++;
+        }
+
         return link_set_dns_routes(link, &address);
 }
 
@@ -480,6 +497,20 @@ static int dhcp_remove_router(Link *link, sd_dhcp_lease *lease, const struct in_
         if (remove_all || !set_contains(link->dhcp_routes, route))
                 (void) route_remove(route, link, NULL);
 
+        Route *rt;
+        LIST_FOREACH(routes, rt, link->network->static_routes) {
+                if (!rt->gateway_from_dhcp)
+                        continue;
+
+                if (rt->family != AF_INET)
+                        continue;
+
+                if (!remove_all && in4_addr_equal(router, &rt->gw.in))
+                        continue;
+
+                (void) route_remove(rt, link, NULL);
+        }
+
         return 0;
 }
 
index 23d0ee675b007ba9a4c9496bfb337e783c9293e9..f2027057c44f39782731d290cfee6c63e7588486 100644 (file)
@@ -1039,6 +1039,8 @@ int link_request_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++)
                 LIST_FOREACH(routes, rt, link->network->static_routes) {
+                        if (rt->gateway_from_dhcp)
+                                continue;
 
                         if ((in_addr_is_null(rt->family, &rt->gw) && ordered_set_isempty(rt->multipath_routes)) != (phase == PHASE_NON_GATEWAY))
                                 continue;
index d1db9e4931c17e9d84cd837f2c01bf432d312544..fb3d6f2a841ace03b792adfbf004c3042ae658f5 100644 (file)
@@ -169,6 +169,26 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
         if (r > 0)
                 link->ndisc_messages++;
 
+        Route *route_gw;
+        LIST_FOREACH(routes, route_gw, link->network->static_routes) {
+                if (!route_gw->gateway_from_dhcp)
+                        continue;
+
+                if (route_gw->family != AF_INET6)
+                        continue;
+
+                route_gw->gw = gateway;
+
+                r = route_configure(route_gw, link, ndisc_netlink_route_message_handler);
+                if (r < 0) {
+                        log_link_error_errno(link, r, "Could not set gateway: %m");
+                        link_enter_failed(link);
+                        return r;
+                }
+                if (r > 0)
+                        link->ndisc_messages++;
+        }
+
         return 0;
 }
 
index ecc8d219b7d1d59da62a3a31b19b94de35ddd23c..4e90fdef18535dd3e4cf66680493cf876669e88d 100644 (file)
@@ -998,10 +998,19 @@ int config_parse_gateway(
                 /* we are not in an Route section, so treat
                  * this as the special '0' section */
                 r = route_new_static(network, NULL, 0, &n);
-        } else
+                if (r < 0)
+                        return r;
+        } else {
                 r = route_new_static(network, filename, section_line, &n);
-        if (r < 0)
-                return r;
+                if (r < 0)
+                        return r;
+
+                if (streq(rvalue, "dhcp")) {
+                        n->gateway_from_dhcp = true;
+                        TAKE_PTR(n);
+                        return 0;
+                }
+        }
 
         if (n->family == AF_UNSPEC)
                 r = in_addr_from_string_auto(rvalue, &n->family, &n->gw);
index 91bba368ee21f73e14c5108a889f19667ef3dc64..067c65f2f78217eb387d953526525ee2b8785e35 100644 (file)
@@ -48,6 +48,7 @@ struct Route {
         unsigned char pref;
         unsigned flags;
         int gateway_onlink;
+        bool gateway_from_dhcp;
 
         union in_addr_union gw;
         union in_addr_union dst;