]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/network/networkd-link.c
util: rename socket_protocol_{from,to}_name() to ip_protocol_{from,to}_name()
[thirdparty/systemd.git] / src / network / networkd-link.c
index b112b13eedd4d961fd243e98374ffa3e7f54aab3..db2dbef52c76fc77986a0eaec0b992180620ccc4 100644 (file)
@@ -270,7 +270,7 @@ static int link_enable_ipv6(Link *link) {
 
         p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/disable_ipv6");
 
-        r = write_string_file(p, one_zero(disabled), WRITE_STRING_FILE_VERIFY_ON_FAILURE);
+        r = write_string_file(p, one_zero(disabled), WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
         if (r < 0)
                 log_link_warning_errno(link, r, "Cannot %s IPv6 for interface %s: %m",
                                        enable_disable(!disabled), link->ifname);
@@ -449,16 +449,19 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
         if (r < 0)
                 return r;
 
-        link = new0(Link, 1);
+        link = new(Link, 1);
         if (!link)
                 return -ENOMEM;
 
-        link->n_ref = 1;
-        link->manager = manager;
-        link->state = LINK_STATE_PENDING;
-        link->rtnl_extended_attrs = true;
-        link->ifindex = ifindex;
-        link->iftype = iftype;
+        *link = (Link) {
+                .n_ref = 1,
+                .manager = manager,
+                .state = LINK_STATE_PENDING,
+                .rtnl_extended_attrs = true,
+                .ifindex = ifindex,
+                .iftype = iftype,
+        };
+
         link->ifname = strdup(ifname);
         if (!link->ifname)
                 return -ENOMEM;
@@ -503,6 +506,17 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
         return 0;
 }
 
+static void link_detach_from_manager(Link *link) {
+        if (!link || !link->manager)
+                return;
+
+        hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex));
+        set_remove(link->manager->links_requesting_uuid, link);
+        link_clean(link);
+
+        link->manager = NULL;
+}
+
 static Link *link_free(Link *link) {
         Address *address;
         Link *carrier;
@@ -552,11 +566,7 @@ static Link *link_free(Link *link) {
         sd_ndisc_unref(link->ndisc);
         sd_radv_unref(link->radv);
 
-        if (link->manager) {
-                hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex));
-                set_remove(link->manager->links_requesting_uuid, link);
-                link_clean(link);
-        }
+        link_detach_from_manager(link);
 
         free(link->ifname);
 
@@ -784,7 +794,8 @@ static int link_set_routing_policy_rule(Link *link) {
 
         LIST_FOREACH(rules, rule, link->network->rules) {
                 r = routing_policy_rule_get(link->manager, rule->family, &rule->from, rule->from_prefixlen, &rule->to,
-                                            rule->to_prefixlen, rule->tos, rule->fwmark, rule->table, rule->iif, rule->oif, &rrule);
+                                            rule->to_prefixlen, rule->tos, rule->fwmark, rule->table, rule->iif, rule->oif,
+                                            rule->protocol, &rule->sport, &rule->dport, &rrule);
                 if (r == 0) {
                         (void) routing_policy_rule_make_local(link->manager, rrule);
                         continue;
@@ -839,6 +850,11 @@ static int route_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata
 }
 
 static int link_enter_set_routes(Link *link) {
+        enum {
+                PHASE_NON_GATEWAY, /* First phase: Routes without a gateway */
+                PHASE_GATEWAY,     /* Second phase: Routes with a gateway */
+                _PHASE_MAX
+        } phase;
         Route *rt;
         int r;
 
@@ -850,16 +866,22 @@ static int link_enter_set_routes(Link *link) {
 
         link_set_state(link, LINK_STATE_SETTING_ROUTES);
 
-        LIST_FOREACH(routes, rt, link->network->static_routes) {
-                r = route_configure(rt, link, route_handler);
-                if (r < 0) {
-                        log_link_warning_errno(link, r, "Could not set routes: %m");
-                        link_enter_failed(link);
-                        return r;
-                }
+        /* 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) {
 
-                link->route_messages++;
-        }
+                        if (in_addr_is_null(rt->family, &rt->gw) != (phase == PHASE_NON_GATEWAY))
+                                continue;
+
+                        r = route_configure(rt, link, route_handler);
+                        if (r < 0) {
+                                log_link_warning_errno(link, r, "Could not set routes: %m");
+                                link_enter_failed(link);
+                                return r;
+                        }
+
+                        link->route_messages++;
+                }
 
         if (link->route_messages == 0) {
                 link->static_routes_configured = true;
@@ -1256,7 +1278,7 @@ static int link_set_proxy_arp(Link *link) {
 
         p = strjoina("/proc/sys/net/ipv4/conf/", link->ifname, "/proxy_arp");
 
-        r = write_string_file(p, one_zero(link->network->proxy_arp), WRITE_STRING_FILE_VERIFY_ON_FAILURE);
+        r = write_string_file(p, one_zero(link->network->proxy_arp), WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
         if (r < 0)
                 log_link_warning_errno(link, r, "Cannot configure proxy ARP for interface: %m");
 
@@ -2265,6 +2287,9 @@ void link_drop(Link *link) {
         log_link_debug(link, "Link removed");
 
         (void) unlink(link->state_file);
+
+        link_detach_from_manager(link);
+
         link_unref(link);
 
         return;
@@ -2463,7 +2488,7 @@ static int link_set_ipv4_forward(Link *link) {
          * primarily to keep IPv4 and IPv6 packet forwarding behaviour
          * somewhat in sync (see below). */
 
-        r = write_string_file("/proc/sys/net/ipv4/ip_forward", "1", WRITE_STRING_FILE_VERIFY_ON_FAILURE);
+        r = write_string_file("/proc/sys/net/ipv4/ip_forward", "1", WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
         if (r < 0)
                 log_link_warning_errno(link, r, "Cannot turn on IPv4 packet forwarding, ignoring: %m");
 
@@ -2485,7 +2510,7 @@ static int link_set_ipv6_forward(Link *link) {
          * same behaviour there and also propagate the setting from
          * one to all, to keep things simple (see above). */
 
-        r = write_string_file("/proc/sys/net/ipv6/conf/all/forwarding", "1", WRITE_STRING_FILE_VERIFY_ON_FAILURE);
+        r = write_string_file("/proc/sys/net/ipv6/conf/all/forwarding", "1", WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
         if (r < 0)
                 log_link_warning_errno(link, r, "Cannot configure IPv6 packet forwarding, ignoring: %m");
 
@@ -2505,7 +2530,7 @@ static int link_set_ipv6_privacy_extensions(Link *link) {
         p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/use_tempaddr");
         xsprintf(buf, "%u", (unsigned) link->network->ipv6_privacy_extensions);
 
-        r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE);
+        r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
         if (r < 0)
                 log_link_warning_errno(link, r, "Cannot configure IPv6 privacy extension for interface: %m");
 
@@ -2529,7 +2554,7 @@ static int link_set_ipv6_accept_ra(Link *link) {
         p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/accept_ra");
 
         /* We handle router advertisements ourselves, tell the kernel to GTFO */
-        r = write_string_file(p, "0", WRITE_STRING_FILE_VERIFY_ON_FAILURE);
+        r = write_string_file(p, "0", WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
         if (r < 0)
                 log_link_warning_errno(link, r, "Cannot disable kernel IPv6 accept_ra for interface: %m");
 
@@ -2557,7 +2582,7 @@ static int link_set_ipv6_dad_transmits(Link *link) {
         p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/dad_transmits");
         xsprintf(buf, "%i", link->network->ipv6_dad_transmits);
 
-        r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE);
+        r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
         if (r < 0)
                 log_link_warning_errno(link, r, "Cannot set IPv6 dad transmits for interface: %m");
 
@@ -2585,7 +2610,7 @@ static int link_set_ipv6_hop_limit(Link *link) {
         p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/hop_limit");
         xsprintf(buf, "%i", link->network->ipv6_hop_limit);
 
-        r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE);
+        r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
         if (r < 0)
                 log_link_warning_errno(link, r, "Cannot set IPv6 hop limit for interface: %m");
 
@@ -2611,7 +2636,7 @@ static int link_set_ipv6_mtu(Link *link) {
 
         xsprintf(buf, "%" PRIu32, link->network->ipv6_mtu);
 
-        r = write_string_file(p, buf, 0);
+        r = write_string_file(p, buf, WRITE_STRING_FILE_DISABLE_BUFFER);
         if (r < 0)
                 log_link_warning_errno(link, r, "Cannot set IPv6 MTU for interface: %m");
 
@@ -3197,13 +3222,12 @@ static int link_load(Link *link) {
 
         assert(link);
 
-        r = parse_env_file(NULL, link->state_file, NEWLINE,
+        r = parse_env_file(NULL, link->state_file,
                            "NETWORK_FILE", &network_file,
                            "ADDRESSES", &addresses,
                            "ROUTES", &routes,
                            "DHCP4_ADDRESS", &dhcp4_address,
-                           "IPV4LL_ADDRESS", &ipv4ll_address,
-                           NULL);
+                           "IPV4LL_ADDRESS", &ipv4ll_address);
         if (r < 0 && r != -ENOENT)
                 return log_link_error_errno(link, r, "Failed to read %s: %m", link->state_file);