]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: make Name= in [Match] support alternative names of interfaces
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 15 Dec 2019 13:46:19 +0000 (22:46 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 16 Dec 2019 01:55:56 +0000 (10:55 +0900)
man/systemd.network.xml
src/libsystemd-network/network-internal.c
src/libsystemd-network/network-internal.h
src/network/networkd-link.c
src/network/networkd-link.h
src/network/networkd-network-gperf.gperf
src/network/networkd-network.c
src/network/networkd-network.h
src/network/test-network.c
src/udev/net/link-config.c

index 148ddac913bfffefb4e91e0d43e720a296ba0216..ba266f9aaa341e36324eed2f03d25e2c12f9a727 100644 (file)
         <varlistentry>
           <term><varname>Name=</varname></term>
           <listitem>
-            <para>A whitespace-separated list of shell-style globs
-            matching the device name, as exposed by the udev property
-            <literal>INTERFACE</literal>. If the list is prefixed
-            with a "!", the test is inverted.</para>
+            <para>A whitespace-separated list of shell-style globs matching the device name, as exposed
+            by the udev property <literal>INTERFACE</literal>, or device's alternative names. If the
+            list is prefixed with a "!", the test is inverted.</para>
           </listitem>
         </varlistentry>
         <varlistentry>
index e3704992093a00d01e9ea7f57f1d8bcda6540a33..7198fe4775c43bdc02638a409802460ab440018c 100644 (file)
@@ -103,6 +103,18 @@ static bool net_condition_test_strv(char * const *patterns, const char *string)
         return has_positive_rule ? match : true;
 }
 
+static bool net_condition_test_ifname(char * const *patterns, const char *ifname, char * const *alternative_names) {
+        if (net_condition_test_strv(patterns, ifname))
+                return true;
+
+        char * const *p;
+        STRV_FOREACH(p, alternative_names)
+                if (net_condition_test_strv(patterns, *p))
+                        return true;
+
+        return false;
+}
+
 static int net_condition_test_property(char * const *match_property, sd_device *device) {
         char * const *p;
 
@@ -166,6 +178,7 @@ bool net_match_config(Set *match_mac,
                       sd_device *device,
                       const struct ether_addr *dev_mac,
                       const char *dev_name,
+                      char * const *alternative_names,
                       enum nl80211_iftype wifi_iftype,
                       const char *ssid,
                       const struct ether_addr *bssid) {
@@ -196,7 +209,7 @@ bool net_match_config(Set *match_mac,
         if (!net_condition_test_strv(match_types, dev_type))
                 return false;
 
-        if (!net_condition_test_strv(match_names, dev_name))
+        if (!net_condition_test_ifname(match_names, dev_name, alternative_names))
                 return false;
 
         if (!net_condition_test_property(match_property, device))
@@ -349,7 +362,7 @@ int config_parse_match_ifnames(
                         return 0;
                 }
 
-                if (!ifname_valid(word)) {
+                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;
index 7875f690ee8a5b40835bb8589dafe71537ccdf9d..a940b24a42414023ea59acb0eae86663bd30be58 100644 (file)
@@ -27,6 +27,7 @@ bool net_match_config(Set *match_mac,
                       sd_device *device,
                       const struct ether_addr *dev_mac,
                       const char *dev_name,
+                      char * const *alternative_names,
                       enum nl80211_iftype wifi_iftype,
                       const char *ssid,
                       const struct ether_addr *bssid);
index 9ebc58f0c995f5b12b5b6645b2aca6211c3371c0..dcdab6c83eb70855ced9c985a71493f1eb7530a3 100644 (file)
@@ -542,10 +542,10 @@ static int link_update_flags(Link *link, sd_netlink_message *m, bool force_updat
 
 static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
         _cleanup_(link_unrefp) Link *link = NULL;
-        uint16_t type;
         const char *ifname, *kind = NULL;
-        int r, ifindex;
         unsigned short iftype;
+        int r, ifindex;
+        uint16_t type;
 
         assert(manager);
         assert(message);
@@ -617,6 +617,10 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
         if (r < 0)
                 log_link_debug_errno(link, r, "MAC address not found for new device, continuing without");
 
+        r = sd_netlink_message_read_strv(message, IFLA_PROP_LIST, IFLA_ALT_IFNAME, &link->alternative_names);
+        if (r < 0 && r != -ENODATA)
+                return r;
+
         if (asprintf(&link->state_file, "/run/systemd/netif/links/%d", link->ifindex) < 0)
                 return -ENOMEM;
 
@@ -713,6 +717,7 @@ static Link *link_free(Link *link) {
         free(link->lldp_file);
 
         free(link->ifname);
+        strv_free(link->alternative_names);
         free(link->kind);
         free(link->ssid);
 
@@ -2934,14 +2939,28 @@ static int link_configure_duid(Link *link) {
         return 0;
 }
 
-int link_reconfigure(Link *link, bool force) {
+static int link_reconfigure_internal(Link *link, sd_netlink_message *m, bool force) {
         Network *network;
         int r;
 
         if (IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_LINGER))
                 return 0;
 
-        r = network_get(link->manager, link->sd_device, link->ifname,
+        if (m) {
+                _cleanup_strv_free_ char **s = NULL;
+
+                r = sd_netlink_message_get_errno(m);
+                if (r < 0)
+                        return r;
+
+                r = sd_netlink_message_read_strv(m, IFLA_PROP_LIST, IFLA_ALT_IFNAME, &s);
+                if (r < 0 && r != -ENODATA)
+                        return r;
+
+                strv_free_and_replace(link->alternative_names, s);
+        }
+
+        r = network_get(link->manager, link->sd_device, link->ifname, link->alternative_names,
                         &link->mac, link->wlan_iftype, link->ssid, &link->bssid, &network);
         if (r == -ENOENT) {
                 link_enter_unmanaged(link);
@@ -2959,10 +2978,8 @@ int link_reconfigure(Link *link, bool force) {
 
         /* Dropping old .network file */
         r = link_stop_clients(link, false);
-        if (r < 0) {
-                link_enter_failed(link);
+        if (r < 0)
                 return r;
-        }
 
         if (link_dhcp4_server_enabled(link))
                 (void) sd_dhcp_server_stop(link->dhcp_server);
@@ -3006,6 +3023,46 @@ int link_reconfigure(Link *link, bool force) {
         return 0;
 }
 
+static int link_reconfigure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+        int r;
+
+        r = link_reconfigure_internal(link, m, false);
+        if (r < 0)
+                link_enter_failed(link);
+
+        return 1;
+}
+
+static int link_force_reconfigure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+        int r;
+
+        r = link_reconfigure_internal(link, m, true);
+        if (r < 0)
+                link_enter_failed(link);
+
+        return 1;
+}
+
+int link_reconfigure(Link *link, bool force) {
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
+        int r;
+
+        r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_GETLINK,
+                                     link->ifindex);
+        if (r < 0)
+                return r;
+
+        r = netlink_call_async(link->manager->rtnl, NULL, req,
+                               force ? link_force_reconfigure_handler : link_reconfigure_handler,
+                               link_netlink_destroy_callback, link);
+        if (r < 0)
+                return r;
+
+        link_ref(link);
+
+        return 0;
+}
+
 static int link_initialized_and_synced(Link *link) {
         Network *network;
         int r;
@@ -3035,7 +3092,7 @@ static int link_initialized_and_synced(Link *link) {
                 if (r < 0)
                         return r;
 
-                r = network_get(link->manager, link->sd_device, link->ifname,
+                r = network_get(link->manager, link->sd_device, link->ifname, link->alternative_names,
                                 &link->mac, link->wlan_iftype, link->ssid, &link->bssid, &network);
                 if (r == -ENOENT) {
                         link_enter_unmanaged(link);
@@ -3080,8 +3137,23 @@ static int link_initialized_and_synced(Link *link) {
 }
 
 static int link_initialized_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+        _cleanup_strv_free_ char **s = NULL;
         int r;
 
+        r = sd_netlink_message_get_errno(m);
+        if (r < 0) {
+                link_enter_failed(link);
+                return 0;
+        }
+
+        r = sd_netlink_message_read_strv(m, IFLA_PROP_LIST, IFLA_ALT_IFNAME, &s);
+        if (r < 0 && r != -ENODATA) {
+                link_enter_failed(link);
+                return 0;
+        }
+
+        strv_free_and_replace(link->alternative_names, s);
+
         r = link_initialized_and_synced(link);
         if (r < 0)
                 link_enter_failed(link);
@@ -3414,9 +3486,11 @@ static int link_carrier_gained(Link *link) {
         if (r < 0)
                 return r;
         if (r > 0) {
-                r = link_reconfigure(link, false);
-                if (r < 0)
+                r = link_reconfigure_internal(link, NULL, false);
+                if (r < 0) {
+                        link_enter_failed(link);
                         return r;
+                }
         }
 
         if (IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) {
@@ -3520,6 +3594,7 @@ static int link_admin_state_up(Link *link) {
 }
 
 int link_update(Link *link, sd_netlink_message *m) {
+        _cleanup_strv_free_ char **s = NULL;
         struct ether_addr mac;
         const char *ifname;
         uint32_t mtu;
@@ -3551,6 +3626,10 @@ int link_update(Link *link, sd_netlink_message *m) {
                         return r;
         }
 
+        r = sd_netlink_message_read_strv(m, IFLA_PROP_LIST, IFLA_ALT_IFNAME, &s);
+        if (r >= 0)
+                strv_free_and_replace(link->alternative_names, s);
+
         r = sd_netlink_message_read_u32(m, IFLA_MTU, &mtu);
         if (r >= 0 && mtu > 0) {
                 link->mtu = mtu;
index 39ef475daf54464219f0e2877d5cef8bdc41ded8..172e48338371d036e138eb669d3b11624bc610e7 100644 (file)
@@ -48,6 +48,7 @@ typedef struct Link {
         int ifindex;
         int master_ifindex;
         char *ifname;
+        char **alternative_names;
         char *kind;
         unsigned short iftype;
         char *state_file;
index 9e0948fc2bf904e06a1517bfcee0ac4da9f5db51..af51730008806bb00be87aef345330826e8be51a 100644 (file)
@@ -34,7 +34,7 @@ Match.Type,                             config_parse_match_strv,
 Match.WLANInterfaceType,                config_parse_match_strv,                         0,                             offsetof(Network, match_wlan_iftype)
 Match.SSID,                             config_parse_match_strv,                         0,                             offsetof(Network, match_ssid)
 Match.BSSID,                            config_parse_hwaddrs,                            0,                             offsetof(Network, match_bssid)
-Match.Name,                             config_parse_match_ifnames,                      0,                             offsetof(Network, match_name)
+Match.Name,                             config_parse_match_ifnames,                      1,                             offsetof(Network, match_name)
 Match.Property,                         config_parse_match_property,                     0,                             offsetof(Network, match_property)
 Match.Host,                             config_parse_net_condition,                      CONDITION_HOST,                offsetof(Network, conditions)
 Match.Virtualization,                   config_parse_net_condition,                      CONDITION_VIRTUALIZATION,      offsetof(Network, conditions)
index 181afbb4cd15c694f897ce4d5bb7440ded7374cd..e2e29993546135a1cc3880aa2f7a08d12e995a74 100644 (file)
@@ -718,7 +718,7 @@ int network_get_by_name(Manager *manager, const char *name, Network **ret) {
 }
 
 int network_get(Manager *manager, sd_device *device,
-                const char *ifname, const struct ether_addr *address,
+                const char *ifname, char * const *alternative_names, const struct ether_addr *address,
                 enum nl80211_iftype wlan_iftype, const char *ssid, const struct ether_addr *bssid,
                 Network **ret) {
         Network *network;
@@ -731,7 +731,7 @@ int network_get(Manager *manager, sd_device *device,
                 if (net_match_config(network->match_mac, network->match_path, network->match_driver,
                                      network->match_type, network->match_name, network->match_property,
                                      network->match_wlan_iftype, network->match_ssid, network->match_bssid,
-                                     device, address, ifname, wlan_iftype, ssid, bssid)) {
+                                     device, address, ifname, alternative_names, wlan_iftype, ssid, bssid)) {
                         if (network->match_name && device) {
                                 const char *attr;
                                 uint8_t name_assign_type = NET_NAME_UNKNOWN;
index aa74bb4ae75a545b9ffefd49dd34c6e87f7df506..bd3c96d972e87f03c54d46f611b79b35ab69e25c 100644 (file)
@@ -297,8 +297,9 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
 int network_verify(Network *network);
 
 int network_get_by_name(Manager *manager, const char *name, Network **ret);
-int network_get(Manager *manager, sd_device *device, const char *ifname, const struct ether_addr *mac,
-                enum nl80211_iftype wlan_iftype, const char *ssid, const struct ether_addr *bssid, Network **ret);
+int network_get(Manager *manager, sd_device *device, const char *ifname, char * const *alternative_names,
+                const struct ether_addr *mac, enum nl80211_iftype wlan_iftype, const char *ssid,
+                const struct ether_addr *bssid, Network **ret);
 int network_apply(Network *network, Link *link);
 void network_apply_anonymize_if_set(Network *network);
 
index 873d996e4fc7dc4e26e354532a41067d8592257c..9c068606990e0b835c88723be09163dc53ab772d 100644 (file)
@@ -125,7 +125,7 @@ static void test_network_get(Manager *manager, sd_device *loopback) {
 
         /* let's assume that the test machine does not have a .network file
            that applies to the loopback device... */
-        assert_se(network_get(manager, loopback, "lo", &mac, 0, NULL, NULL, &network) == -ENOENT);
+        assert_se(network_get(manager, loopback, "lo", NULL, &mac, 0, NULL, NULL, &network) == -ENOENT);
         assert_se(!network);
 }
 
index 6879cfee071747d2eed4c4ffa766d86da01dac3a..8d89f1af10d6ac34eb350f8724e836f6b6879f50 100644 (file)
@@ -244,7 +244,7 @@ int link_config_get(link_config_ctx *ctx, sd_device *device, link_config **ret)
         LIST_FOREACH(links, link, ctx->links) {
                 if (net_match_config(link->match_mac, link->match_path, link->match_driver,
                                      link->match_type, link->match_name, link->match_property, NULL, NULL, NULL,
-                                     device, NULL, NULL, 0, NULL, NULL)) {
+                                     device, NULL, NULL, NULL, 0, NULL, NULL)) {
                         if (link->match_name && !strv_contains(link->match_name, "*")) {
                                 unsigned name_assign_type = NET_NAME_UNKNOWN;