diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c index 1c353e86b07..9fc89a5f6e7 100644 --- a/src/basic/socket-util.c +++ b/src/basic/socket-util.c @@ -793,7 +793,7 @@ bool ifname_valid_full(const char *p, IfnameValidFlags flags) { /* Let's refuse "all" and "default" as interface name, to avoid collisions with the special sysctl * directories /proc/sys/net/{ipv4,ipv6}/conf/{all,default} */ - if (STR_IN_SET(p, "all", "default")) + if (!FLAGS_SET(flags, IFNAME_VALID_SPECIAL) && STR_IN_SET(p, "all", "default")) return false; for (const char *t = p; *t; t++) { diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h index 7fd591f6e2e..0d76eace7da 100644 --- a/src/basic/socket-util.h +++ b/src/basic/socket-util.h @@ -135,9 +135,10 @@ int ip_tos_to_string_alloc(int i, char **s); int ip_tos_from_string(const char *s); typedef enum { - IFNAME_VALID_ALTERNATIVE = 1 << 0, - IFNAME_VALID_NUMERIC = 1 << 1, - _IFNAME_VALID_ALL = IFNAME_VALID_ALTERNATIVE | IFNAME_VALID_NUMERIC, + IFNAME_VALID_ALTERNATIVE = 1 << 0, /* Allow "altnames" too */ + IFNAME_VALID_NUMERIC = 1 << 1, /* Allow decimal formatted ifindexes too */ + IFNAME_VALID_SPECIAL = 1 << 2, /* Allow the special names "all" and "default" */ + _IFNAME_VALID_ALL = IFNAME_VALID_ALTERNATIVE | IFNAME_VALID_NUMERIC | IFNAME_VALID_SPECIAL, } IfnameValidFlags; bool ifname_valid_char(char a); bool ifname_valid_full(const char *p, IfnameValidFlags flags); diff --git a/src/basic/sysctl-util.c b/src/basic/sysctl-util.c index 60eec3dfec1..a19f3e26491 100644 --- a/src/basic/sysctl-util.c +++ b/src/basic/sysctl-util.c @@ -5,11 +5,13 @@ #include #include +#include "af-list.h" #include "fd-util.h" #include "fileio.h" #include "log.h" #include "macro.h" #include "path-util.h" +#include "socket-util.h" #include "string-util.h" #include "sysctl-util.h" @@ -77,17 +79,21 @@ int sysctl_writef(const char *property, const char *format, ...) { int sysctl_write_ip_property(int af, const char *ifname, const char *property, const char *value) { const char *p; - assert(IN_SET(af, AF_INET, AF_INET6)); assert(property); assert(value); - p = strjoina("/proc/sys/net/ipv", af == AF_INET ? "4" : "6", - ifname ? "/conf/" : "", strempty(ifname), - property[0] == '/' ? "" : "/", property); + if (!IN_SET(af, AF_INET, AF_INET6)) + return -EAFNOSUPPORT; - log_debug("Setting '%s' to '%s'", p, value); + if (ifname) { + if (!ifname_valid_full(ifname, IFNAME_VALID_SPECIAL)) + return -EINVAL; - return write_string_file(p, value, WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER); + p = strjoina("net/", af_to_ipv4_ipv6(af), "/conf/", ifname, "/", property); + } else + p = strjoina("net/", af_to_ipv4_ipv6(af), "/", property); + + return sysctl_write(p, value); } int sysctl_read(const char *property, char **ret) {