diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2021-12-16 09:34:01 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-16 09:34:01 +0100 |
commit | 67cb0d4725af7593440c50125a63d01963d54d13 (patch) | |
tree | ad60ac2193e2fa67ec71ed93a9e6c2b1306a6f5e /src/network | |
parent | 58f62d7079a3d77b859a25d585dd492531bda0a1 (diff) | |
parent | 79463de5336ad8aafd7e66235e907cc584b7b649 (diff) | |
download | systemd-67cb0d4725af7593440c50125a63d01963d54d13.tar.gz |
Merge pull request #21766 from yuwata/network-generator-name-policy
network-generator: support setting NamePolicy=
Diffstat (limited to 'src/network')
-rw-r--r-- | src/network/generator/main.c | 9 | ||||
-rw-r--r-- | src/network/generator/network-generator.c | 141 | ||||
-rw-r--r-- | src/network/generator/network-generator.h | 14 | ||||
-rw-r--r-- | src/network/generator/test-network-generator.c | 20 |
4 files changed, 154 insertions, 30 deletions
diff --git a/src/network/generator/main.c b/src/network/generator/main.c index 624b0a0b5d..a36fe98c86 100644 --- a/src/network/generator/main.c +++ b/src/network/generator/main.c @@ -65,9 +65,10 @@ static int link_save(Link *link, const char *dest_dir) { assert(link); - r = asprintf(&filename, "90-%s.link", - link->ifname); - if (r < 0) + filename = strjoin(!isempty(link->ifname) ? "90" : + !hw_addr_is_null(&link->mac) ? "91" : "92", + "-", link->filename, ".link"); + if (!filename) return log_oom(); r = generator_open_unit_file(dest_dir, "kernel command line", filename, &f); @@ -104,7 +105,7 @@ static int context_save(Context *context) { r = k; } - HASHMAP_FOREACH(link, context->links_by_name) { + HASHMAP_FOREACH(link, context->links_by_filename) { k = link_save(link, p); if (k < 0 && r >= 0) r = k; diff --git a/src/network/generator/network-generator.c b/src/network/generator/network-generator.c index 4a4ac3ed39..c081ec673c 100644 --- a/src/network/generator/network-generator.c +++ b/src/network/generator/network-generator.c @@ -1,11 +1,11 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ -#include "ether-addr-util.h" #include "fd-util.h" #include "fileio.h" #include "hostname-util.h" #include "log.h" #include "macro.h" +#include "netif-naming-scheme.h" #include "network-generator.h" #include "parse-util.h" #include "proc-cmdline.h" @@ -26,6 +26,7 @@ # .link ifname=<interface>:<MAC> + net.ifname-policy=policy1[,policy2,...][,<MAC>] # This is an original rule, not supported by other tools. # .netdev vlan=<vlanname>:<phydevice> @@ -264,36 +265,59 @@ static Link *link_free(Link *link) { if (!link) return NULL; + free(link->filename); free(link->ifname); + strv_free(link->policies); + strv_free(link->alt_policies); return mfree(link); } DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_free); -static int link_new(Context *context, const char *name, struct ether_addr *mac, Link **ret) { +static int link_new( + Context *context, + const char *name, + const struct hw_addr_data *mac, + Link **ret) { + _cleanup_(link_freep) Link *link = NULL; - _cleanup_free_ char *ifname = NULL; + _cleanup_free_ char *ifname = NULL, *filename = NULL; int r; assert(context); + assert(mac); - if (!ifname_valid(name)) - return -EINVAL; + if (name) { + if (!ifname_valid(name)) + return -EINVAL; - ifname = strdup(name); - if (!ifname) - return -ENOMEM; + ifname = strdup(name); + if (!ifname) + return -ENOMEM; + + filename = strdup(name); + if (!filename) + return -ENOMEM; + } + + if (!filename) { + filename = strdup(hw_addr_is_null(mac) ? "default" : + HW_ADDR_TO_STR_FULL(mac, HW_ADDR_TO_STRING_NO_COLON)); + if (!filename) + return -ENOMEM; + } link = new(Link, 1); if (!link) return -ENOMEM; *link = (Link) { + .filename = TAKE_PTR(filename), .ifname = TAKE_PTR(ifname), .mac = *mac, }; - r = hashmap_ensure_put(&context->links_by_name, &string_hash_ops, link->ifname, link); + r = hashmap_ensure_put(&context->links_by_filename, &string_hash_ops, link->filename, link); if (r < 0) return r; @@ -304,8 +328,10 @@ static int link_new(Context *context, const char *name, struct ether_addr *mac, return 0; } -Link *link_get(Context *context, const char *ifname) { - return hashmap_get(context->links_by_name, ifname); +Link *link_get(Context *context, const char *filename) { + assert(context); + assert(filename); + return hashmap_get(context->links_by_filename, filename); } static int network_set_dhcp_type(Context *context, const char *ifname, const char *dhcp_type) { @@ -896,7 +922,7 @@ static int parse_cmdline_bond(Context *context, const char *key, const char *val } static int parse_cmdline_ifname(Context *context, const char *key, const char *value) { - struct ether_addr mac; + struct hw_addr_data mac; const char *name, *p; int r; @@ -911,13 +937,72 @@ static int parse_cmdline_ifname(Context *context, const char *key, const char *v name = strndupa_safe(value, p - value); - r = parse_ether_addr(p + 1, &mac); + r = parse_hw_addr(p + 1, &mac); if (r < 0) return r; return link_new(context, name, &mac, NULL); } +static int parse_cmdline_ifname_policy(Context *context, const char *key, const char *value) { + _cleanup_strv_free_ char **policies = NULL, **alt_policies = NULL; + struct hw_addr_data mac = HW_ADDR_NULL; + Link *link; + int r; + + /* net.ifname-policy=policy1[,policy2,...][,<MAC>] */ + + if (proc_cmdline_value_missing(key, value)) + return -EINVAL; + + for (const char *q = value; ; ) { + _cleanup_free_ char *word = NULL; + NamePolicy p; + + r = extract_first_word(&q, &word, ",", 0); + if (r == 0) + break; + if (r < 0) + return r; + + p = name_policy_from_string(word); + if (p < 0) { + r = parse_hw_addr(word, &mac); + if (r < 0) + return r; + + if (hw_addr_is_null(&mac)) + return -EINVAL; + + if (!isempty(q)) + return -EINVAL; + + break; + } + + if (alternative_names_policy_from_string(word) >= 0) { + r = strv_extend(&alt_policies, word); + if (r < 0) + return r; + } + + r = strv_consume(&policies, TAKE_PTR(word)); + if (r < 0) + return r; + } + + if (strv_isempty(policies)) + return -EINVAL; + + r = link_new(context, NULL, &mac, &link); + if (r < 0) + return r; + + link->policies = TAKE_PTR(policies); + link->alt_policies = TAKE_PTR(alt_policies); + return 0; +} + int parse_cmdline_item(const char *key, const char *value, void *data) { Context *context = data; @@ -940,6 +1025,8 @@ int parse_cmdline_item(const char *key, const char *value, void *data) { return parse_cmdline_bond(context, key, value); if (streq(key, "ifname")) return parse_cmdline_ifname(context, key, value); + if (streq(key, "net.ifname-policy")) + return parse_cmdline_ifname_policy(context, key, value); return 0; } @@ -991,7 +1078,7 @@ void context_clear(Context *context) { hashmap_free_with_destructor(context->networks_by_name, network_free); hashmap_free_with_destructor(context->netdevs_by_name, netdev_free); - hashmap_free_with_destructor(context->links_by_name, link_free); + hashmap_free_with_destructor(context->links_by_filename, link_free); } static int address_dump(Address *address, FILE *f) { @@ -1117,13 +1204,27 @@ void link_dump(Link *link, FILE *f) { fputs("[Match]\n", f); - if (!ether_addr_is_null(&link->mac)) - fprintf(f, "MACAddress=%s\n", ETHER_ADDR_TO_STR(&link->mac)); + if (!hw_addr_is_null(&link->mac)) + fprintf(f, "MACAddress=%s\n", HW_ADDR_TO_STR(&link->mac)); + else + fputs("OriginalName=*\n", f); - fprintf(f, - "\n[Link]\n" - "Name=%s\n", - link->ifname); + fputs("\n[Link]\n", f); + + if (!isempty(link->ifname)) + fprintf(f, "Name=%s\n", link->ifname); + + if (!strv_isempty(link->policies)) { + fputs("NamePolicy=", f); + fputstrv(f, link->policies, " ", NULL); + fputc('\n', f); + } + + if (!strv_isempty(link->alt_policies)) { + fputs("AlternativeNamesPolicy=", f); + fputstrv(f, link->alt_policies, " ", NULL); + fputc('\n', f); + } } int network_format(Network *network, char **ret) { diff --git a/src/network/generator/network-generator.h b/src/network/generator/network-generator.h index 25c8816bbe..dd0a58738b 100644 --- a/src/network/generator/network-generator.h +++ b/src/network/generator/network-generator.h @@ -1,9 +1,9 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once -#include <net/ethernet.h> #include <stdio.h> +#include "ether-addr-util.h" #include "hashmap.h" #include "in-addr-util.h" #include "list.h" @@ -81,15 +81,21 @@ struct NetDev { }; struct Link { + char *filename; + /* [Match] */ + struct hw_addr_data mac; + + /* [Link] */ char *ifname; - struct ether_addr mac; + char **policies; + char **alt_policies; }; typedef struct Context { Hashmap *networks_by_name; Hashmap *netdevs_by_name; - Hashmap *links_by_name; + Hashmap *links_by_filename; } Context; int parse_cmdline_item(const char *key, const char *value, void *data); @@ -104,6 +110,6 @@ NetDev *netdev_get(Context *context, const char *ifname); void netdev_dump(NetDev *netdev, FILE *f); int netdev_format(NetDev *netdev, char **ret); -Link *link_get(Context *context, const char *ifname); +Link *link_get(Context *context, const char *filename); void link_dump(Link *link, FILE *f); int link_format(Link *link, char **ret); diff --git a/src/network/generator/test-network-generator.c b/src/network/generator/test-network-generator.c index e658d89333..bcd4b1d9e4 100644 --- a/src/network/generator/test-network-generator.c +++ b/src/network/generator/test-network-generator.c @@ -49,14 +49,14 @@ static void test_netdev_one(const char *ifname, const char *key, const char *val assert_se(streq(output, expected)); } -static void test_link_one(const char *ifname, const char *key, const char *value, const char *expected) { +static void test_link_one(const char *filename, const char *key, const char *value, const char *expected) { _cleanup_(context_clear) Context context = {}; _cleanup_free_ char *output = NULL; Link *link; printf("# %s=%s\n", key, value); assert_se(parse_cmdline_item(key, value, &context) >= 0); - assert_se(link = link_get(&context, ifname)); + assert_se(link = link_get(&context, filename)); assert_se(link_format(link, &output) >= 0); puts(output); assert_se(streq(output, expected)); @@ -334,6 +334,22 @@ int main(int argc, char *argv[]) { "Name=hogehoge\n" ); + test_link_one("001122334455", "net.ifname-policy", "keep,kernel,database,onboard,slot,path,mac,00:11:22:33:44:55", + "[Match]\n" + "MACAddress=00:11:22:33:44:55\n" + "\n[Link]\n" + "NamePolicy=keep kernel database onboard slot path mac\n" + "AlternativeNamesPolicy=database onboard slot path mac\n" + ); + + test_link_one("default", "net.ifname-policy", "keep,kernel,database,onboard,slot,path,mac", + "[Match]\n" + "OriginalName=*\n" + "\n[Link]\n" + "NamePolicy=keep kernel database onboard slot path mac\n" + "AlternativeNamesPolicy=database onboard slot path mac\n" + ); + test_network_two("eth0", "ip", "192.168.0.10:192.168.0.2:192.168.0.1:255.255.255.0:hogehoge:eth0:on:10.10.10.10:10.10.10.11", "rd.route", "10.1.2.3/16:10.0.2.3", |