mirror of
https://github.com/systemd/systemd.git
synced 2025-01-31 05:47:30 +03:00
util-lib: add new ifname_valid() call that validates interface names
Make use of this in nspawn at a couple of places. A later commit should port more code over to this, including networkd.
This commit is contained in:
parent
5e7423ff25
commit
ef76dff225
@ -43,7 +43,9 @@
|
||||
#include "socket-util.h"
|
||||
#include "string-table.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "user-util.h"
|
||||
#include "utf8.h"
|
||||
#include "util.h"
|
||||
|
||||
int socket_address_parse(SocketAddress *a, const char *s) {
|
||||
@ -795,6 +797,42 @@ static const char* const ip_tos_table[] = {
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff);
|
||||
|
||||
bool ifname_valid(const char *p) {
|
||||
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. */
|
||||
|
||||
if (isempty(p))
|
||||
return false;
|
||||
|
||||
if (strlen(p) >= IFNAMSIZ)
|
||||
return false;
|
||||
|
||||
if (STR_IN_SET(p, ".", ".."))
|
||||
return false;
|
||||
|
||||
while (*p) {
|
||||
if ((unsigned char) *p >= 127U)
|
||||
return false;
|
||||
|
||||
if ((unsigned char) *p <= 32U)
|
||||
return false;
|
||||
|
||||
if (*p == ':' || *p == '/')
|
||||
return false;
|
||||
|
||||
numeric = numeric && (*p >= '0' && *p <= '9');
|
||||
p++;
|
||||
}
|
||||
|
||||
if (numeric)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int getpeercred(int fd, struct ucred *ucred) {
|
||||
socklen_t n = sizeof(struct ucred);
|
||||
struct ucred u;
|
||||
|
@ -123,6 +123,8 @@ 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(const char *p);
|
||||
|
||||
int getpeercred(int fd, struct ucred *ucred);
|
||||
int getpeersec(int fd, char **ret);
|
||||
|
||||
|
@ -29,6 +29,8 @@
|
||||
#include "netlink-util.h"
|
||||
#include "nspawn-network.h"
|
||||
#include "siphash24.h"
|
||||
#include "socket-util.h"
|
||||
#include "stat-util.h"
|
||||
#include "string-util.h"
|
||||
#include "udev-util.h"
|
||||
#include "util.h"
|
||||
@ -515,13 +517,13 @@ int veth_extra_parse(char ***l, const char *p) {
|
||||
r = extract_first_word(&p, &a, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0 || isempty(a))
|
||||
if (r == 0 || !ifname_valid(a))
|
||||
return -EINVAL;
|
||||
|
||||
r = extract_first_word(&p, &b, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0 || isempty(b)) {
|
||||
if (r == 0 || !ifname_valid(b)) {
|
||||
free(b);
|
||||
b = strdup(a);
|
||||
if (!b)
|
||||
|
@ -467,6 +467,12 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case ARG_NETWORK_BRIDGE:
|
||||
|
||||
if (!ifname_valid(optarg)) {
|
||||
log_error("Bridge interface name not valid: %s", optarg);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
r = free_and_strdup(&arg_network_bridge, optarg);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
@ -489,6 +495,12 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case ARG_NETWORK_INTERFACE:
|
||||
|
||||
if (!ifname_valid(optarg)) {
|
||||
log_error("Network interface name not valid: %s", optarg);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (strv_extend(&arg_network_interfaces, optarg) < 0)
|
||||
return log_oom();
|
||||
|
||||
@ -497,6 +509,12 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case ARG_NETWORK_MACVLAN:
|
||||
|
||||
if (!ifname_valid(optarg)) {
|
||||
log_error("MACVLAN network interface name not valid: %s", optarg);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (strv_extend(&arg_network_macvlan, optarg) < 0)
|
||||
return log_oom();
|
||||
|
||||
@ -505,6 +523,12 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case ARG_NETWORK_IPVLAN:
|
||||
|
||||
if (!ifname_valid(optarg)) {
|
||||
log_error("IPVLAN network interface name not valid: %s", optarg);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (strv_extend(&arg_network_ipvlan, optarg) < 0)
|
||||
return log_oom();
|
||||
|
||||
|
@ -27,6 +27,29 @@
|
||||
#include "string-util.h"
|
||||
#include "util.h"
|
||||
|
||||
static void test_ifname_valid(void) {
|
||||
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(NULL));
|
||||
assert(!ifname_valid(""));
|
||||
assert(!ifname_valid(" "));
|
||||
assert(!ifname_valid(" foo"));
|
||||
assert(!ifname_valid("bar\n"));
|
||||
assert(!ifname_valid("."));
|
||||
assert(!ifname_valid(".."));
|
||||
assert(ifname_valid("foo.bar"));
|
||||
assert(!ifname_valid("x:y"));
|
||||
|
||||
assert(ifname_valid("xxxxxxxxxxxxxxx"));
|
||||
assert(!ifname_valid("xxxxxxxxxxxxxxxx"));
|
||||
}
|
||||
|
||||
static void test_socket_address_parse(void) {
|
||||
SocketAddress a;
|
||||
|
||||
@ -362,6 +385,8 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
log_set_max_level(LOG_DEBUG);
|
||||
|
||||
test_ifname_valid();
|
||||
|
||||
test_socket_address_parse();
|
||||
test_socket_address_parse_netlink();
|
||||
test_socket_address_equal();
|
||||
|
Loading…
x
Reference in New Issue
Block a user