]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/network/networkd-route.c
network: make address/route_configure optionally return created Address/Route object
[thirdparty/systemd.git] / src / network / networkd-route.c
index 4e90fdef18535dd3e4cf66680493cf876669e88d..d8739b767928c3c656f0038d7438297272bd09f8 100644 (file)
 #include "networkd-route.h"
 #include "parse-util.h"
 #include "set.h"
+#include "socket-netlink.h"
 #include "string-table.h"
 #include "string-util.h"
+#include "strv.h"
 #include "strxcpyx.h"
 #include "sysctl-util.h"
-#include "util.h"
+#include "vrf.h"
 
 #define ROUTES_DEFAULT_MAX_PER_FAMILY 4096U
 
@@ -330,11 +332,7 @@ static int route_add_internal(Link *link, Set **routes, Route *in, Route **ret)
         route->initrwnd = in->initrwnd;
         route->lifetime = in->lifetime;
 
-        r = set_ensure_allocated(routes, &route_hash_ops);
-        if (r < 0)
-                return r;
-
-        r = set_put(*routes, route);
+        r = set_ensure_put(routes, &route_hash_ops, route);
         if (r < 0)
                 return r;
         if (r == 0)
@@ -367,11 +365,7 @@ int route_add(Link *link, Route *in, Route **ret) {
                         return r;
         } else if (r == 0) {
                 /* Take over a foreign route */
-                r = set_ensure_allocated(&link->routes, &route_hash_ops);
-                if (r < 0)
-                        return r;
-
-                r = set_put(link->routes, route);
+                r = set_ensure_put(&link->routes, &route_hash_ops, route);
                 if (r < 0)
                         return r;
 
@@ -511,7 +505,7 @@ int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata) {
 
         r = route_remove(route, route->link, NULL);
         if (r < 0)
-                log_warning_errno(r, "Could not remove route: %m");
+                log_link_warning_errno(route->link, r, "Could not remove route: %m");
         else
                 route_free(route);
 
@@ -603,7 +597,8 @@ static int append_nexthops(Route *route, sd_netlink_message *req) {
 int route_configure(
                 Route *route,
                 Link *link,
-                link_netlink_message_handler_t callback) {
+                link_netlink_message_handler_t callback,
+                Route **ret) {
 
         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
         _cleanup_(sd_event_source_unrefp) sd_event_source *expire = NULL;
@@ -809,6 +804,9 @@ int route_configure(
         sd_event_source_unref(route->expire);
         route->expire = TAKE_PTR(expire);
 
+        if (ret)
+                *ret = route;
+
         return 1;
 }
 
@@ -998,14 +996,24 @@ 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);
-                if (r < 0)
-                        return r;
+                if (r == -ENOMEM)
+                        return log_oom();
+                if (r < 0) {
+                        log_syntax(unit, LOG_WARNING, filename, line, r,
+                                   "Failed to allocate route, ignoring assignment: %m");
+                        return 0;
+                }
         } else {
                 r = route_new_static(network, filename, section_line, &n);
-                if (r < 0)
-                        return r;
+                if (r == -ENOMEM)
+                        return log_oom();
+                if (r < 0) {
+                        log_syntax(unit, LOG_WARNING, filename, line, r,
+                                   "Failed to allocate route, ignoring assignment: %m");
+                        return 0;
+                }
 
-                if (streq(rvalue, "dhcp")) {
+                if (streq(rvalue, "_dhcp")) {
                         n->gateway_from_dhcp = true;
                         TAKE_PTR(n);
                         return 0;
@@ -1017,7 +1025,7 @@ int config_parse_gateway(
         else
                 r = in_addr_from_string(n->family, rvalue, &n->gw);
         if (r < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, r,
+                log_syntax(unit, LOG_WARNING, filename, line, r,
                            "Invalid %s='%s', ignoring assignment: %m", lvalue, rvalue);
                 return 0;
         }
@@ -1049,15 +1057,20 @@ int config_parse_preferred_src(
         assert(data);
 
         r = route_new_static(network, filename, section_line, &n);
-        if (r < 0)
-                return r;
+        if (r == -ENOMEM)
+                return log_oom();
+        if (r < 0) {
+                log_syntax(unit, LOG_WARNING, filename, line, r,
+                           "Failed to allocate route, ignoring assignment: %m");
+                return 0;
+        }
 
         if (n->family == AF_UNSPEC)
                 r = in_addr_from_string_auto(rvalue, &n->family, &n->prefsrc);
         else
                 r = in_addr_from_string(n->family, rvalue, &n->prefsrc);
         if (r < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+                log_syntax(unit, LOG_WARNING, filename, line, EINVAL,
                            "Invalid %s='%s', ignoring assignment: %m", lvalue, rvalue);
                 return 0;
         }
@@ -1091,8 +1104,13 @@ int config_parse_destination(
         assert(data);
 
         r = route_new_static(network, filename, section_line, &n);
-        if (r < 0)
-                return r;
+        if (r == -ENOMEM)
+                return log_oom();
+        if (r < 0) {
+                log_syntax(unit, LOG_WARNING, filename, line, r,
+                           "Failed to allocate route, ignoring assignment: %m");
+                return 0;
+        }
 
         if (streq(lvalue, "Destination")) {
                 buffer = &n->dst;
@@ -1108,7 +1126,7 @@ int config_parse_destination(
         else
                 r = in_addr_prefix_from_string(rvalue, n->family, buffer, prefixlen);
         if (r < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+                log_syntax(unit, LOG_WARNING, filename, line, EINVAL,
                            "Invalid %s='%s', ignoring assignment: %m", lvalue, rvalue);
                 return 0;
         }
@@ -1140,12 +1158,17 @@ int config_parse_route_priority(
         assert(data);
 
         r = route_new_static(network, filename, section_line, &n);
-        if (r < 0)
-                return r;
+        if (r == -ENOMEM)
+                return log_oom();
+        if (r < 0) {
+                log_syntax(unit, LOG_WARNING, filename, line, r,
+                           "Failed to allocate route, ignoring assignment: %m");
+                return 0;
+        }
 
         r = safe_atou32(rvalue, &n->priority);
         if (r < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, r,
+                log_syntax(unit, LOG_WARNING, filename, line, r,
                            "Could not parse route priority \"%s\", ignoring assignment: %m", rvalue);
                 return 0;
         }
@@ -1177,12 +1200,17 @@ int config_parse_route_scope(
         assert(data);
 
         r = route_new_static(network, filename, section_line, &n);
-        if (r < 0)
-                return r;
+        if (r == -ENOMEM)
+                return log_oom();
+        if (r < 0) {
+                log_syntax(unit, LOG_WARNING, filename, line, r,
+                           "Failed to allocate route, ignoring assignment: %m");
+                return 0;
+        }
 
         r = route_scope_from_string(rvalue);
         if (r < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, 0, "Unknown route scope: %s", rvalue);
+                log_syntax(unit, LOG_WARNING, filename, line, 0, "Unknown route scope: %s", rvalue);
                 return 0;
         }
 
@@ -1215,8 +1243,13 @@ int config_parse_route_table(
         assert(data);
 
         r = route_new_static(network, filename, section_line, &n);
-        if (r < 0)
-                return r;
+        if (r == -ENOMEM)
+                return log_oom();
+        if (r < 0) {
+                log_syntax(unit, LOG_WARNING, filename, line, r,
+                           "Failed to allocate route, ignoring assignment: %m");
+                return 0;
+        }
 
         r = route_table_from_string(rvalue);
         if (r >= 0)
@@ -1224,7 +1257,7 @@ int config_parse_route_table(
         else {
                 r = safe_atou32(rvalue, &n->table);
                 if (r < 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, r,
+                        log_syntax(unit, LOG_WARNING, filename, line, r,
                                    "Could not parse route table number \"%s\", ignoring assignment: %m", rvalue);
                         return 0;
                 }
@@ -1235,7 +1268,7 @@ int config_parse_route_table(
         return 0;
 }
 
-int config_parse_gateway_onlink(
+int config_parse_route_boolean(
                 const char *unit,
                 const char *filename,
                 unsigned line,
@@ -1258,17 +1291,31 @@ int config_parse_gateway_onlink(
         assert(data);
 
         r = route_new_static(network, filename, section_line, &n);
-        if (r < 0)
-                return r;
+        if (r == -ENOMEM)
+                return log_oom();
+        if (r < 0) {
+                log_syntax(unit, LOG_WARNING, filename, line, r,
+                           "Failed to allocate route, ignoring assignment: %m");
+                return 0;
+        }
 
         r = parse_boolean(rvalue);
         if (r < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, r,
+                log_syntax(unit, LOG_WARNING, filename, line, r,
                            "Could not parse %s=\"%s\", ignoring assignment: %m", lvalue, rvalue);
                 return 0;
         }
 
-        n->gateway_onlink = r;
+        if (STR_IN_SET(lvalue, "GatewayOnLink", "GatewayOnlink"))
+                n->gateway_onlink = r;
+        else if (streq(lvalue, "QuickAck"))
+                n->quickack = r;
+        else if (streq(lvalue, "FastOpenNoCookie"))
+                n->fast_open_no_cookie = r;
+        else if (streq(lvalue, "TTLPropagate"))
+                n->ttl_propagate = r;
+        else
+                assert_not_reached("Invalid lvalue");
 
         TAKE_PTR(n);
         return 0;
@@ -1291,8 +1338,13 @@ int config_parse_ipv6_route_preference(
         int r;
 
         r = route_new_static(network, filename, section_line, &n);
-        if (r < 0)
-                return r;
+        if (r == -ENOMEM)
+                return log_oom();
+        if (r < 0) {
+                log_syntax(unit, LOG_WARNING, filename, line, r,
+                           "Failed to allocate route, ignoring assignment: %m");
+                return 0;
+        }
 
         if (streq(rvalue, "low"))
                 n->pref = ICMPV6_ROUTER_PREF_LOW;
@@ -1301,7 +1353,7 @@ int config_parse_ipv6_route_preference(
         else if (streq(rvalue, "high"))
                 n->pref = ICMPV6_ROUTER_PREF_HIGH;
         else {
-                log_syntax(unit, LOG_ERR, filename, line, 0, "Unknown route preference: %s", rvalue);
+                log_syntax(unit, LOG_WARNING, filename, line, 0, "Unknown route preference: %s", rvalue);
                 return 0;
         }
 
@@ -1326,8 +1378,13 @@ int config_parse_route_protocol(
         int r;
 
         r = route_new_static(network, filename, section_line, &n);
-        if (r < 0)
-                return r;
+        if (r == -ENOMEM)
+                return log_oom();
+        if (r < 0) {
+                log_syntax(unit, LOG_WARNING, filename, line, r,
+                           "Failed to allocate route, ignoring assignment: %m");
+                return 0;
+        }
 
         r = route_protocol_from_string(rvalue);
         if (r >= 0)
@@ -1335,7 +1392,7 @@ int config_parse_route_protocol(
         else {
                 r = safe_atou8(rvalue , &n->protocol);
                 if (r < 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, r,
+                        log_syntax(unit, LOG_WARNING, filename, line, r,
                                    "Could not parse route protocol \"%s\", ignoring assignment: %m", rvalue);
                         return 0;
                 }
@@ -1362,12 +1419,17 @@ int config_parse_route_type(
         int t, r;
 
         r = route_new_static(network, filename, section_line, &n);
-        if (r < 0)
-                return r;
+        if (r == -ENOMEM)
+                return log_oom();
+        if (r < 0) {
+                log_syntax(unit, LOG_WARNING, filename, line, r,
+                           "Failed to allocate route, ignoring assignment: %m");
+                return 0;
+        }
 
         t = route_type_from_string(rvalue);
         if (t < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, 0,
+                log_syntax(unit, LOG_WARNING, filename, line, 0,
                            "Could not parse route type \"%s\", ignoring assignment: %m", rvalue);
                 return 0;
         }
@@ -1402,17 +1464,22 @@ int config_parse_tcp_window(
         assert(data);
 
         r = route_new_static(network, filename, section_line, &n);
-        if (r < 0)
-                return r;
+        if (r == -ENOMEM)
+                return log_oom();
+        if (r < 0) {
+                log_syntax(unit, LOG_WARNING, filename, line, r,
+                           "Failed to allocate route, ignoring assignment: %m");
+                return 0;
+        }
 
         r = parse_size(rvalue, 1024, &k);
         if (r < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, r,
+                log_syntax(unit, LOG_WARNING, filename, line, r,
                            "Could not parse TCP %s \"%s\", ignoring assignment: %m", lvalue, rvalue);
                 return 0;
         }
         if (k > UINT32_MAX) {
-                log_syntax(unit, LOG_ERR, filename, line, 0,
+                log_syntax(unit, LOG_WARNING, filename, line, 0,
                            "Specified TCP %s \"%s\" is too large, ignoring assignment: %m", lvalue, rvalue);
                 return 0;
         }
@@ -1428,82 +1495,6 @@ int config_parse_tcp_window(
         return 0;
 }
 
-int config_parse_quickack(
-                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_(route_free_or_set_invalidp) Route *n = NULL;
-        Network *network = userdata;
-        int k, r;
-
-        assert(filename);
-        assert(section);
-        assert(lvalue);
-        assert(rvalue);
-        assert(data);
-
-        r = route_new_static(network, filename, section_line, &n);
-        if (r < 0)
-                return r;
-
-        k = parse_boolean(rvalue);
-        if (k < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, k,
-                           "Failed to parse TCP quickack, ignoring: %s", rvalue);
-                return 0;
-        }
-
-        n->quickack = !!k;
-        TAKE_PTR(n);
-        return 0;
-}
-
-int config_parse_fast_open_no_cookie(
-                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_(route_free_or_set_invalidp) Route *n = NULL;
-        Network *network = userdata;
-        int k, r;
-
-        assert(filename);
-        assert(section);
-        assert(lvalue);
-        assert(rvalue);
-        assert(data);
-
-        r = route_new_static(network, filename, section_line, &n);
-        if (r < 0)
-                return r;
-
-        k = parse_boolean(rvalue);
-        if (k < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, k,
-                           "Failed to parse TCP fastopen no cookie, ignoring: %s", rvalue);
-                return 0;
-        }
-
-        n->fast_open_no_cookie = k;
-        TAKE_PTR(n);
-        return 0;
-}
-
 int config_parse_route_mtu(
                 const char *unit,
                 const char *filename,
@@ -1527,8 +1518,13 @@ int config_parse_route_mtu(
         assert(data);
 
         r = route_new_static(network, filename, section_line, &n);
-        if (r < 0)
-                return r;
+        if (r == -ENOMEM)
+                return log_oom();
+        if (r < 0) {
+                log_syntax(unit, LOG_WARNING, filename, line, r,
+                           "Failed to allocate route, ignoring assignment: %m");
+                return 0;
+        }
 
         r = config_parse_mtu(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &n->mtu, userdata);
         if (r < 0)
@@ -1538,45 +1534,6 @@ int config_parse_route_mtu(
         return 0;
 }
 
-int config_parse_route_ttl_propagate(
-                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;
-        _cleanup_(route_free_or_set_invalidp) Route *n = NULL;
-        int r, k;
-
-        assert(filename);
-        assert(section);
-        assert(lvalue);
-        assert(rvalue);
-        assert(data);
-
-        r = route_new_static(network, filename, section_line, &n);
-        if (r < 0)
-                return r;
-
-        k = parse_boolean(rvalue);
-        if (k < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, k,
-                           "Failed to parse TTLPropagate= value, ignoring: %s", rvalue);
-                return 0;
-        }
-
-        n->ttl_propagate = k;
-
-        TAKE_PTR(n);
-        return 0;
-}
-
 int config_parse_multipath_route(
                 const char *unit,
                 const char *filename,
@@ -1604,8 +1561,13 @@ int config_parse_multipath_route(
         assert(data);
 
         r = route_new_static(network, filename, section_line, &n);
-        if (r < 0)
-                return r;
+        if (r == -ENOMEM)
+                return log_oom();
+        if (r < 0) {
+                log_syntax(unit, LOG_WARNING, filename, line, r,
+                           "Failed to allocate route, ignoring assignment: %m");
+                return 0;
+        }
 
         if (isempty(rvalue)) {
                 n->multipath_routes = ordered_set_free_free(n->multipath_routes);
@@ -1621,7 +1583,7 @@ int config_parse_multipath_route(
         if (r == -ENOMEM)
                 return log_oom();
         if (r <= 0) {
-                log_syntax(unit, LOG_ERR, filename, line, r,
+                log_syntax(unit, LOG_WARNING, filename, line, r,
                            "Invalid multipath route option, ignoring assignment: %s", rvalue);
                 return 0;
         }
@@ -1638,7 +1600,7 @@ int config_parse_multipath_route(
 
         r = in_addr_from_string_auto(ip, &family, &a);
         if (r < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, r,
+                log_syntax(unit, LOG_WARNING, filename, line, r,
                            "Invalid multipath route gateway '%s', ignoring assignment: %m", rvalue);
                 return 0;
         }
@@ -1646,23 +1608,24 @@ int config_parse_multipath_route(
         m->gateway.family = family;
 
         if (dev) {
-                r = parse_ifindex_or_ifname(dev, &m->ifindex);
+                r = resolve_interface(NULL, dev);
                 if (r < 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, r,
+                        log_syntax(unit, LOG_WARNING, filename, line, r,
                                    "Invalid interface name or index, ignoring assignment: %s", dev);
                         return 0;
                 }
+                m->ifindex = r;
         }
 
         if (!isempty(p)) {
                 r = safe_atou32(p, &m->weight);
                 if (r < 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, r,
+                        log_syntax(unit, LOG_WARNING, filename, line, r,
                                    "Invalid multipath route weight, ignoring assignment: %s", p);
                         return 0;
                 }
                 if (m->weight == 0 || m->weight > 256) {
-                        log_syntax(unit, LOG_ERR, filename, line, 0,
+                        log_syntax(unit, LOG_WARNING, filename, line, 0,
                                    "Invalid multipath route weight, ignoring assignment: %s", p);
                         return 0;
                 }
@@ -1674,7 +1637,7 @@ int config_parse_multipath_route(
 
         r = ordered_set_put(n->multipath_routes, m);
         if (r < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, r,
+                log_syntax(unit, LOG_WARNING, filename, line, r,
                            "Failed to store multipath route, ignoring assignment: %m");
                 return 0;
         }
@@ -1698,6 +1661,11 @@ int route_section_verify(Route *route, Network *network) {
                                          route->section->filename, route->section->line);
         }
 
+        if (!route->table_set && network->vrf) {
+                route->table = VRF(network->vrf)->table;
+                route->table_set = true;
+        }
+
         if (!route->table_set && IN_SET(route->type, RTN_LOCAL, RTN_BROADCAST, RTN_ANYCAST, RTN_NAT))
                 route->table = RT_TABLE_LOCAL;