From: Zbigniew Jędrzejewski-Szmek Date: Thu, 3 Sep 2020 12:59:21 +0000 (+0200) Subject: basic: convert ifname_valid_full() to take flags and allow numeric interfaces X-Git-Tag: v247-rc1~261^2~10 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2313524aa0082b84ae96083cd616120f60a67faa;p=thirdparty%2Fsystemd.git basic: convert ifname_valid_full() to take flags and allow numeric interfaces --- diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c index 4b3a4f206cd..1f65015347f 100644 --- a/src/basic/socket-util.c +++ b/src/basic/socket-util.c @@ -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; } diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h index 6a320a976f4..fee9055cecd 100644 --- a/src/basic/socket-util.h +++ b/src/basic/socket-util.h @@ -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); diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 3f1652b1904..d07714f5a1c 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -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) diff --git a/src/test/test-socket-util.c b/src/test/test-socket-util.c index d0dda379512..1bb186655de 100644 --- a/src/test/test-socket-util.c +++ b/src/test/test-socket-util.c @@ -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) { diff --git a/src/udev/net/link-config-gperf.gperf b/src/udev/net/link-config-gperf.gperf index 60a9d21c1d1..20f5d7e5a45 100644 --- a/src/udev/net/link-config-gperf.gperf +++ b/src/udev/net/link-config-gperf.gperf @@ -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)