]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
basic: convert ifname_valid_full() to take flags and allow numeric interfaces
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 3 Sep 2020 12:59:21 +0000 (14:59 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Wed, 9 Sep 2020 22:46:44 +0000 (00:46 +0200)
src/basic/socket-util.c
src/basic/socket-util.h
src/network/networkd-network-gperf.gperf
src/test/test-socket-util.c
src/udev/net/link-config-gperf.gperf

index 4b3a4f206cdac249e4fe79b5e60694c2c8ea7a63..1f65015347fe42924075337d9f4b6c2297f95cb5 100644 (file)
@@ -686,17 +686,19 @@ static const char* const ip_tos_table[] = {
 
 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff);
 
-bool ifname_valid_full(const char *p, bool alternative) {
+bool ifname_valid_full(const char *p, IfnameValidFlags flags) {
         bool numeric = true;
 
         /* Checks whether a network interface name is valid. This is inspired by dev_valid_name() in the kernel sources
          * but slightly stricter, as we only allow non-control, non-space ASCII characters in the interface name. We
          * also don't permit names that only container numbers, to avoid confusion with numeric interface indexes. */
 
+        assert(!(flags & ~_IFNAME_VALID_ALL));
+
         if (isempty(p))
                 return false;
 
-        if (alternative) {
+        if (flags & IFNAME_VALID_ALTERNATIVE) {
                 if (strlen(p) >= ALTIFNAMSIZ)
                         return false;
         } else {
@@ -707,22 +709,27 @@ bool ifname_valid_full(const char *p, bool alternative) {
         if (dot_or_dot_dot(p))
                 return false;
 
-        while (*p) {
-                if ((unsigned char) *p >= 127U)
+        for (const char *t = p; *t; t++) {
+                if ((unsigned char) *t >= 127U)
                         return false;
 
-                if ((unsigned char) *p <= 32U)
+                if ((unsigned char) *t <= 32U)
                         return false;
 
-                if (IN_SET(*p, ':', '/'))
+                if (IN_SET(*t, ':', '/'))
                         return false;
 
-                numeric = numeric && (*p >= '0' && *p <= '9');
-                p++;
+                numeric = numeric && (*t >= '0' && *t <= '9');
         }
 
-        if (numeric)
-                return false;
+        if (numeric) {
+                if (!(flags & IFNAME_VALID_NUMERIC))
+                        return false;
+
+                /* Verify that the number is well-formatted and in range. */
+                if (parse_ifindex(p) < 0)
+                        return false;
+        }
 
         return true;
 }
index 6a320a976f434a59a6dbc35273b1e928466b235b..fee9055cecd105b2219e4b3bf6cb45e27180028b 100644 (file)
@@ -130,9 +130,14 @@ static inline int fd_inc_rcvbuf(int fd, size_t n) {
 int ip_tos_to_string_alloc(int i, char **s);
 int ip_tos_from_string(const char *s);
 
-bool ifname_valid_full(const char *p, bool alternative);
+typedef enum {
+      IFNAME_VALID_ALTERNATIVE = 1 << 0,
+      IFNAME_VALID_NUMERIC     = 1 << 1,
+      _IFNAME_VALID_ALL        = IFNAME_VALID_ALTERNATIVE | IFNAME_VALID_NUMERIC,
+} IfnameValidFlags;
+bool ifname_valid_full(const char *p, IfnameValidFlags flags);
 static inline bool ifname_valid(const char *p) {
-        return ifname_valid_full(p, false);
+        return ifname_valid_full(p, 0);
 }
 bool address_label_valid(const char *p);
 
index 3f1652b1904ffa622973dd91f29a97701d347880..d07714f5a1c85988bdb7484cdadb9842ae06ae6e 100644 (file)
@@ -39,7 +39,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,                               1,                             offsetof(Network, match_name)
+Match.Name,                                  config_parse_match_ifnames,                               IFNAME_VALID_ALTERNATIVE,      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 d0dda3795129dcb59979aa11cad2304bfc98bfe8..1bb186655dea2b295821ef01fd841f655ad34ecc 100644 (file)
@@ -26,13 +26,13 @@ assert_cc(SUN_PATH_LEN == 108);
 static void test_ifname_valid(void) {
         log_info("/* %s */", __func__);
 
-        assert(ifname_valid("foo"));
-        assert(ifname_valid("eth0"));
+        assert( ifname_valid("foo"));
+        assert( ifname_valid("eth0"));
 
         assert(!ifname_valid("0"));
         assert(!ifname_valid("99"));
-        assert(ifname_valid("a99"));
-        assert(ifname_valid("99a"));
+        assert( ifname_valid("a99"));
+        assert( ifname_valid("99a"));
 
         assert(!ifname_valid(NULL));
         assert(!ifname_valid(""));
@@ -44,9 +44,13 @@ static void test_ifname_valid(void) {
         assert(ifname_valid("foo.bar"));
         assert(!ifname_valid("x:y"));
 
-        assert(ifname_valid("xxxxxxxxxxxxxxx"));
-        assert(!ifname_valid("xxxxxxxxxxxxxxxx"));
-        assert(ifname_valid_full("xxxxxxxxxxxxxxxx", true));
+        assert( ifname_valid_full("xxxxxxxxxxxxxxx", 0));
+        assert(!ifname_valid_full("xxxxxxxxxxxxxxxx", 0));
+        assert( ifname_valid_full("xxxxxxxxxxxxxxxx", IFNAME_VALID_ALTERNATIVE));
+        assert( ifname_valid_full("xxxxxxxxxxxxxxxx", IFNAME_VALID_ALTERNATIVE));
+        assert(!ifname_valid_full("999", IFNAME_VALID_ALTERNATIVE));
+        assert( ifname_valid_full("999", IFNAME_VALID_ALTERNATIVE | IFNAME_VALID_NUMERIC));
+        assert(!ifname_valid_full("0", IFNAME_VALID_ALTERNATIVE | IFNAME_VALID_NUMERIC));
 }
 
 static void test_socket_print_unix_one(const char *in, size_t len_in, const char *expected) {
index 60a9d21c1d11ec1b58badaecf3296030a918a62b..20f5d7e5a45bbcb848d9b23f28c77c03692edb1b 100644 (file)
@@ -7,6 +7,7 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
 #include "ethtool-util.h"
 #include "link-config.h"
 #include "network-internal.h"
+#include "socket-util.h"
 %}
 struct ConfigPerfItem;
 %null_strings
@@ -36,7 +37,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.AlternativeName,            config_parse_ifnames,                  IFNAME_VALID_ALTERNATIVE,      offsetof(link_config, alternative_names)
 Link.AlternativeNamesPolicy,     config_parse_alternative_names_policy, 0,                             offsetof(link_config, alternative_names_policy)
 Link.Alias,                      config_parse_ifalias,                  0,                             offsetof(link_config, alias)
 Link.MTUBytes,                   config_parse_mtu,                      AF_UNSPEC,                     offsetof(link_config, mtu)