]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
udev: support AlternativeName= setting in .link file
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 15 Dec 2019 14:21:18 +0000 (23:21 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 16 Dec 2019 01:52:22 +0000 (10:52 +0900)
man/systemd.link.xml
src/libsystemd/sd-netlink/netlink-util.c
src/libsystemd/sd-netlink/netlink-util.h
src/shared/conf-parser.c
src/shared/conf-parser.h
src/udev/net/link-config-gperf.gperf
src/udev/net/link-config.c
src/udev/net/link-config.h
test/fuzz/fuzz-link-parser/directives.link

index 63bb31d6e81a4a75971a5db250727d272ba207d3..0f9e988ba04b18d13f1303379b039c473889de5e 100644 (file)
           </para>
         </listitem>
       </varlistentry>
+      <varlistentry>
+        <term><varname>AlternativeName=</varname></term>
+        <listitem>
+          <para>The alternative interface name to use. This option can be specified multiple times.
+          If the empty string is assigned to this option, the list is reset, and all prior assignments
+          have no effect.</para>
+        </listitem>
+      </varlistentry>
       <varlistentry>
         <term><varname>MTUBytes=</varname></term>
         <listitem>
index 628ce507a058e0f955333d13f57c6a251e5faa0d..bd9412a63b7b94454f11d92f0578ed09ec3bc24b 100644 (file)
@@ -4,6 +4,7 @@
 
 #include "netlink-internal.h"
 #include "netlink-util.h"
+#include "strv.h"
 
 int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name) {
         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
@@ -83,6 +84,45 @@ int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias,
         return 0;
 }
 
+int rtnl_set_link_alternative_names(sd_netlink **rtnl, int ifindex, char * const *alternative_names) {
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
+        int r;
+
+        assert(rtnl);
+        assert(ifindex > 0);
+
+        if (strv_isempty(alternative_names))
+                return 0;
+
+        if (!*rtnl) {
+                r = sd_netlink_open(rtnl);
+                if (r < 0)
+                        return r;
+        }
+
+        r = sd_rtnl_message_new_link(*rtnl, &message, RTM_NEWLINKPROP, ifindex);
+        if (r < 0)
+                return r;
+
+        r = sd_netlink_message_open_container(message, IFLA_PROP_LIST);
+        if (r < 0)
+                return r;
+
+        r = sd_netlink_message_append_strv(message, IFLA_ALT_IFNAME, alternative_names);
+        if (r < 0)
+                return r;
+
+        r = sd_netlink_message_close_container(message);
+        if (r < 0)
+                return r;
+
+        r = sd_netlink_call(*rtnl, message, 0, NULL);
+        if (r < 0)
+                return r;
+
+        return 0;
+}
+
 int rtnl_message_new_synthetic_error(sd_netlink *rtnl, int error, uint32_t serial, sd_netlink_message **ret) {
         struct nlmsgerr *err;
         int r;
index 1b79fb7bced4e4c6d15e771fa8d3fc6586ab789a..42c8917219376f4ffea457ea84bf510dbfd2c2a1 100644 (file)
@@ -49,6 +49,7 @@ static inline bool rtnl_message_type_is_qdisc(uint16_t type) {
 
 int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name);
 int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias, const struct ether_addr *mac, uint32_t mtu);
+int rtnl_set_link_alternative_names(sd_netlink **rtnl, int ifindex, char * const *alternative_names);
 
 int rtnl_log_parse_error(int r);
 int rtnl_log_create_error(int r);
index 90b31148f3e66a9cc6ccbf27ed089599c53859dc..cb20279dda602ad45276dc223fdc1761b0d622c9 100644 (file)
@@ -985,6 +985,66 @@ int config_parse_ifname(
         return 0;
 }
 
+int config_parse_ifnames(
+                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_strv_free_ char **names = NULL;
+        char ***s = data;
+        const char *p;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        if (isempty(rvalue)) {
+                *s = strv_free(*s);
+                return 0;
+        }
+
+        p = rvalue;
+        for (;;) {
+                _cleanup_free_ char *word = NULL;
+
+                r = extract_first_word(&p, &word, NULL, 0);
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "Failed to extract interface name, ignoring assignment: %s",
+                                   rvalue);
+                        return 0;
+                }
+                if (r == 0)
+                        break;
+
+                if (!ifname_valid_full(word, ltype)) {
+                        log_syntax(unit, LOG_ERR, filename, line, 0,
+                                   "Interface name is not valid or too long, ignoring assignment: %s",
+                                   word);
+                        continue;
+                }
+
+                r = strv_consume(&names, TAKE_PTR(word));
+                if (r < 0)
+                        return log_oom();
+        }
+
+        r = strv_extend_strv(s, names, true);
+        if (r < 0)
+                return log_oom();
+
+        return 0;
+}
+
 int config_parse_ip_port(
                 const char *unit,
                 const char *filename,
index 9ec77778670d5f62383037db28de0aa2d9790660..287620ad71431a7854e3fa81c5c61f974bb981b6 100644 (file)
@@ -137,6 +137,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_signal);
 CONFIG_PARSER_PROTOTYPE(config_parse_personality);
 CONFIG_PARSER_PROTOTYPE(config_parse_permille);
 CONFIG_PARSER_PROTOTYPE(config_parse_ifname);
+CONFIG_PARSER_PROTOTYPE(config_parse_ifnames);
 CONFIG_PARSER_PROTOTYPE(config_parse_ip_port);
 CONFIG_PARSER_PROTOTYPE(config_parse_mtu);
 CONFIG_PARSER_PROTOTYPE(config_parse_rlimit);
index c6ff796efceb36d93cd0ec37c1931bd9ba7b6274..e0212bbc1826e0551db0fe201ab75280605219cb 100644 (file)
@@ -35,6 +35,7 @@ Link.MACAddressPolicy,           config_parse_mac_address_policy, 0,
 Link.MACAddress,                 config_parse_hwaddr,             0,                             offsetof(link_config, mac)
 Link.NamePolicy,                 config_parse_name_policy,        0,                             offsetof(link_config, name_policy)
 Link.Name,                       config_parse_ifname,             0,                             offsetof(link_config, name)
+Link.AlternativeName,            config_parse_ifnames,            1,                             offsetof(link_config, alternative_names)
 Link.Alias,                      config_parse_ifalias,            0,                             offsetof(link_config, alias)
 Link.MTUBytes,                   config_parse_mtu,                AF_UNSPEC,                     offsetof(link_config, mtu)
 Link.BitsPerSecond,              config_parse_si_size,            0,                             offsetof(link_config, speed)
index 7b07e2f38fa819ddefbf90cabaa804c1be276d5a..6879cfee071747d2eed4c4ffa766d86da01dac3a 100644 (file)
@@ -58,6 +58,7 @@ static void link_config_free(link_config *link) {
         free(link->mac);
         free(link->name_policy);
         free(link->name);
+        strv_free(link->alternative_names);
         free(link->alias);
 
         free(link);
@@ -458,6 +459,10 @@ int link_config_apply(link_config_ctx *ctx, link_config *config,
         if (r < 0)
                 return log_warning_errno(r, "Could not set Alias=, MACAddress= or MTU= on %s: %m", old_name);
 
+        r = rtnl_set_link_alternative_names(&ctx->rtnl, ifindex, config->alternative_names);
+        if (r < 0)
+                return log_warning_errno(r, "Could not set AlternativeName= on %s: %m", old_name);
+
         *name = new_name;
 
         return 0;
index 52a02b9b0907336fb30c1e8c20f84e8fe0bfb3ba..b5073548ab96c1cd1d67426d7533ca1b2ff6b204 100644 (file)
@@ -48,6 +48,7 @@ struct link_config {
         MACAddressPolicy mac_address_policy;
         NamePolicy *name_policy;
         char *name;
+        char **alternative_names;
         char *alias;
         uint32_t mtu;
         size_t speed;
index e7d0737acea0b2c85e658644379ce7977bc380cd..5c26129b7099f0821ace0048d0ce47f51f89c9eb 100644 (file)
@@ -16,6 +16,7 @@ MACAddressPolicy=
 MACAddress=
 NamePolicy=
 Name=
+AlternativeName=
 Alias=
 MTUBytes=
 BitsPerSecond=