]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/network/networkd-util.c
Merge pull request #12392 from poettering/firstboot-salt
[thirdparty/systemd.git] / src / network / networkd-util.c
index df091393f6f616cc7584f99c715d60e655514582..d01de53f7be70a16407732818b9dd2161577b593 100644 (file)
@@ -1,24 +1,6 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
-  This file is part of systemd.
-
-  Copyright 2013 Tom Gundersen <teg@jklm.no>
-
-  systemd is free software; you can redistribute it and/or modify it
-  under the terms of the GNU Lesser General Public License as published by
-  the Free Software Foundation; either version 2.1 of the License, or
-  (at your option) any later version.
-
-  systemd is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
 
+#include "condition.h"
 #include "conf-parser.h"
 #include "networkd-util.h"
 #include "parse-util.h"
 #include "string-util.h"
 #include "util.h"
 
-const char *address_family_boolean_to_string(AddressFamilyBoolean b) {
-        if (b == ADDRESS_FAMILY_YES ||
-            b == ADDRESS_FAMILY_NO)
-                return yes_no(b == ADDRESS_FAMILY_YES);
-
-        if (b == ADDRESS_FAMILY_IPV4)
-                return "ipv4";
-        if (b == ADDRESS_FAMILY_IPV6)
-                return "ipv6";
-
-        return NULL;
-}
-
-AddressFamilyBoolean address_family_boolean_from_string(const char *s) {
-        int r;
-
-        /* Make this a true superset of a boolean */
-
-        r = parse_boolean(s);
-        if (r > 0)
-                return ADDRESS_FAMILY_YES;
-        if (r == 0)
-                return ADDRESS_FAMILY_NO;
-
-        if (streq(s, "ipv4"))
-                return ADDRESS_FAMILY_IPV4;
-        if (streq(s, "ipv6"))
-                return ADDRESS_FAMILY_IPV6;
+static const char * const address_family_boolean_table[_ADDRESS_FAMILY_BOOLEAN_MAX] = {
+        [ADDRESS_FAMILY_NO]            = "no",
+        [ADDRESS_FAMILY_YES]           = "yes",
+        [ADDRESS_FAMILY_IPV4]          = "ipv4",
+        [ADDRESS_FAMILY_IPV6]          = "ipv6",
+};
 
-        return _ADDRESS_FAMILY_BOOLEAN_INVALID;
-}
+static const char * const link_local_address_family_boolean_table[_ADDRESS_FAMILY_BOOLEAN_MAX] = {
+        [ADDRESS_FAMILY_NO]            = "no",
+        [ADDRESS_FAMILY_YES]           = "yes",
+        [ADDRESS_FAMILY_IPV4]          = "ipv4",
+        [ADDRESS_FAMILY_IPV6]          = "ipv6",
+        [ADDRESS_FAMILY_FALLBACK]      = "fallback",
+        [ADDRESS_FAMILY_FALLBACK_IPV4] = "ipv4-fallback",
+};
 
-DEFINE_CONFIG_PARSE_ENUM(config_parse_address_family_boolean, address_family_boolean, AddressFamilyBoolean, "Failed to parse option");
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(address_family_boolean, AddressFamilyBoolean, ADDRESS_FAMILY_YES);
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(link_local_address_family_boolean, AddressFamilyBoolean, ADDRESS_FAMILY_YES);
+DEFINE_CONFIG_PARSE_ENUM(config_parse_link_local_address_family_boolean, link_local_address_family_boolean,
+                         AddressFamilyBoolean, "Failed to parse option");
 
 int config_parse_address_family_boolean_with_kernel(
                 const char* unit,
@@ -79,10 +48,18 @@ int config_parse_address_family_boolean_with_kernel(
         assert(rvalue);
         assert(data);
 
+        /* This function is mostly obsolete now. It simply redirects
+         * "kernel" to "no". In older networkd versions we used to
+         * distinguish IPForward=off from IPForward=kernel, where the
+         * former would explicitly turn off forwarding while the
+         * latter would simply not touch the setting. But that logic
+         * is gone, hence silently accept the old setting, but turn it
+         * to "no". */
+
         s = address_family_boolean_from_string(rvalue);
         if (s < 0) {
                 if (streq(rvalue, "kernel"))
-                        s = _ADDRESS_FAMILY_BOOLEAN_INVALID;
+                        s = ADDRESS_FAMILY_NO;
                 else {
                         log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse IPForward= option, ignoring: %s", rvalue);
                         return 0;
@@ -94,53 +71,58 @@ int config_parse_address_family_boolean_with_kernel(
         return 0;
 }
 
-static const char* const resolve_support_table[_RESOLVE_SUPPORT_MAX] = {
-        [RESOLVE_SUPPORT_NO] = "no",
-        [RESOLVE_SUPPORT_YES] = "yes",
-        [RESOLVE_SUPPORT_RESOLVE] = "resolve",
-};
+/* Router lifetime can be set with netlink interface since kernel >= 4.5
+ * so for the supported kernel we don't need to expire routes in userspace */
+int kernel_route_expiration_supported(void) {
+        static int cached = -1;
+        int r;
 
-DEFINE_STRING_TABLE_LOOKUP(resolve_support, ResolveSupport);
+        if (cached < 0) {
+                Condition c = {
+                        .type = CONDITION_KERNEL_VERSION,
+                        .parameter = (char *) ">= 4.5"
+                };
+                r = condition_test(&c);
+                if (r < 0)
+                        return r;
 
-int config_parse_resolve(
-                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) {
+                cached = r;
+        }
+        return cached;
+}
 
-        ResolveSupport *resolve = data;
-        int k;
+static void network_config_hash_func(const NetworkConfigSection *c, struct siphash *state) {
+        siphash24_compress(c->filename, strlen(c->filename), state);
+        siphash24_compress(&c->line, sizeof(c->line), state);
+}
 
-        assert(filename);
-        assert(lvalue);
-        assert(rvalue);
-        assert(resolve);
-
-        /* Our enum shall be a superset of booleans, hence first try
-         * to parse as boolean, and then as enum */
-
-        k = parse_boolean(rvalue);
-        if (k > 0)
-                *resolve = RESOLVE_SUPPORT_YES;
-        else if (k == 0)
-                *resolve = RESOLVE_SUPPORT_NO;
-        else {
-                ResolveSupport s;
-
-                s = resolve_support_from_string(rvalue);
-                if (s < 0){
-                        log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse %s= option, ignoring: %s", lvalue, rvalue);
-                        return 0;
-                }
+static int network_config_compare_func(const NetworkConfigSection *x, const NetworkConfigSection *y) {
+        int r;
 
-                *resolve = s;
-        }
+        r = strcmp(x->filename, y->filename);
+        if (r != 0)
+                return r;
+
+        return CMP(x->line, y->line);
+}
+
+DEFINE_HASH_OPS(network_config_hash_ops, NetworkConfigSection, network_config_hash_func, network_config_compare_func);
+
+int network_config_section_new(const char *filename, unsigned line, NetworkConfigSection **s) {
+        NetworkConfigSection *cs;
+
+        cs = malloc0(offsetof(NetworkConfigSection, filename) + strlen(filename) + 1);
+        if (!cs)
+                return -ENOMEM;
+
+        strcpy(cs->filename, filename);
+        cs->line = line;
+
+        *s = TAKE_PTR(cs);
 
         return 0;
 }
+
+void network_config_section_free(NetworkConfigSection *cs) {
+        free(cs);
+}