Merge pull request #16947 from keszybz/socket-parsing-rework
Socket parsing rework
This commit is contained in:
+31
-22
@@ -68,7 +68,7 @@ int socket_address_verify(const SocketAddress *a, bool strict) {
|
||||
if (a->sockaddr.in.sin_port == 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (!IN_SET(a->type, SOCK_STREAM, SOCK_DGRAM))
|
||||
if (!IN_SET(a->type, 0, SOCK_STREAM, SOCK_DGRAM))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
@@ -80,7 +80,7 @@ int socket_address_verify(const SocketAddress *a, bool strict) {
|
||||
if (a->sockaddr.in6.sin6_port == 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (!IN_SET(a->type, SOCK_STREAM, SOCK_DGRAM))
|
||||
if (!IN_SET(a->type, 0, SOCK_STREAM, SOCK_DGRAM))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
@@ -114,7 +114,7 @@ int socket_address_verify(const SocketAddress *a, bool strict) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!IN_SET(a->type, SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET))
|
||||
if (!IN_SET(a->type, 0, SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
@@ -124,7 +124,7 @@ int socket_address_verify(const SocketAddress *a, bool strict) {
|
||||
if (a->size != sizeof(struct sockaddr_nl))
|
||||
return -EINVAL;
|
||||
|
||||
if (!IN_SET(a->type, SOCK_RAW, SOCK_DGRAM))
|
||||
if (!IN_SET(a->type, 0, SOCK_RAW, SOCK_DGRAM))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
@@ -133,7 +133,7 @@ int socket_address_verify(const SocketAddress *a, bool strict) {
|
||||
if (a->size != sizeof(struct sockaddr_vm))
|
||||
return -EINVAL;
|
||||
|
||||
if (!IN_SET(a->type, SOCK_STREAM, SOCK_DGRAM))
|
||||
if (!IN_SET(a->type, 0, SOCK_STREAM, SOCK_DGRAM))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
@@ -399,19 +399,23 @@ int sockaddr_pretty(
|
||||
if (r < 0)
|
||||
return -ENOMEM;
|
||||
} else {
|
||||
char a[INET6_ADDRSTRLEN];
|
||||
char a[INET6_ADDRSTRLEN], ifname[IF_NAMESIZE + 1];
|
||||
|
||||
inet_ntop(AF_INET6, &sa->in6.sin6_addr, a, sizeof(a));
|
||||
if (sa->in6.sin6_scope_id != 0)
|
||||
format_ifname_full(sa->in6.sin6_scope_id, ifname, FORMAT_IFNAME_IFINDEX);
|
||||
|
||||
if (include_port) {
|
||||
r = asprintf(&p,
|
||||
"[%s]:%u",
|
||||
"[%s]:%u%s%s",
|
||||
a,
|
||||
be16toh(sa->in6.sin6_port));
|
||||
be16toh(sa->in6.sin6_port),
|
||||
sa->in6.sin6_scope_id != 0 ? "%" : "",
|
||||
sa->in6.sin6_scope_id != 0 ? ifname : "");
|
||||
if (r < 0)
|
||||
return -ENOMEM;
|
||||
} else {
|
||||
p = strdup(a);
|
||||
p = sa->in6.sin6_scope_id != 0 ? strjoin(a, "%", ifname) : strdup(a);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
}
|
||||
@@ -686,17 +690,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 +713,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;
|
||||
}
|
||||
@@ -1107,12 +1118,10 @@ int sockaddr_un_set_path(struct sockaddr_un *ret, const char *path) {
|
||||
* reference paths in the abstract namespace that include NUL bytes in the name. */
|
||||
|
||||
l = strlen(path);
|
||||
if (l == 0)
|
||||
if (l < 2)
|
||||
return -EINVAL;
|
||||
if (!IN_SET(path[0], '/', '@'))
|
||||
return -EINVAL;
|
||||
if (path[1] == 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* Don't allow paths larger than the space in sockaddr_un. Note that we are a tiny bit more restrictive than
|
||||
* the kernel is: we insist on NUL termination (both for abstract namespace and regular file system socket
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user