diff options
Diffstat (limited to 'src/libnm-systemd-shared/src/basic/socket-util.c')
| -rw-r--r-- | src/libnm-systemd-shared/src/basic/socket-util.c | 58 |
1 files changed, 33 insertions, 25 deletions
diff --git a/src/libnm-systemd-shared/src/basic/socket-util.c b/src/libnm-systemd-shared/src/basic/socket-util.c index da36c280..49a4df44 100644 --- a/src/libnm-systemd-shared/src/basic/socket-util.c +++ b/src/libnm-systemd-shared/src/basic/socket-util.c @@ -112,7 +112,7 @@ int socket_address_verify(const SocketAddress *a, bool strict) { /* If there's no embedded NUL byte, then the size needs to match the whole * structure or the structure with one extra NUL byte suffixed. (Yeah, Linux is awful, * and considers both equivalent: getsockname() even extends sockaddr_un beyond its - * size if the path is non NUL terminated.)*/ + * size if the path is non NUL terminated.) */ if (!IN_SET(a->size, sizeof(a->sockaddr.un.sun_path), sizeof(a->sockaddr.un.sun_path)+1)) return -EINVAL; } @@ -460,23 +460,23 @@ int sockaddr_pretty( if (r < 0) return -ENOMEM; } else { - char a[INET6_ADDRSTRLEN], ifname[IF_NAMESIZE + 1]; + char a[INET6_ADDRSTRLEN]; 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, + if (asprintf(&p, "[%s]:%u%s%s", a, be16toh(sa->in6.sin6_port), sa->in6.sin6_scope_id != 0 ? "%" : "", - sa->in6.sin6_scope_id != 0 ? ifname : ""); - if (r < 0) + FORMAT_IFNAME_FULL(sa->in6.sin6_scope_id, FORMAT_IFNAME_IFINDEX)) < 0) return -ENOMEM; } else { - p = sa->in6.sin6_scope_id != 0 ? strjoin(a, "%", ifname) : strdup(a); + if (sa->in6.sin6_scope_id != 0) + p = strjoin(a, "%", FORMAT_IFNAME_FULL(sa->in6.sin6_scope_id, FORMAT_IFNAME_IFINDEX)); + else + p = strdup(a); if (!p) return -ENOMEM; } @@ -754,6 +754,22 @@ static const char* const ip_tos_table[] = { DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff); #endif /* NM_IGNORED */ +bool ifname_valid_char(char a) { + if ((unsigned char) a >= 127U) + return false; + + if ((unsigned char) a <= 32U) + return false; + + if (IN_SET(a, + ':', /* colons are used by the legacy "alias" interface logic */ + '/', /* slashes cannot work, since we need to use network interfaces in sysfs paths, and in paths slashes are separators */ + '%')) /* %d is used in the kernel's weird foo%d format string naming feature which we really really don't want to ever run into by accident */ + return false; + + return true; +} + bool ifname_valid_full(const char *p, IfnameValidFlags flags) { bool numeric = true; @@ -783,20 +799,11 @@ 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++) { - if ((unsigned char) *t >= 127U) - return false; - - if ((unsigned char) *t <= 32U) - return false; - - if (IN_SET(*t, - ':', /* colons are used by the legacy "alias" interface logic */ - '/', /* slashes cannot work, since we need to use network interfaces in sysfs paths, and in paths slashes are separators */ - '%')) /* %d is used in the kernel's weird foo%d format string naming feature which we really really don't want to ever run into by accident */ + if (!ifname_valid_char(*t)) return false; numeric = numeric && (*t >= '0' && *t <= '9'); @@ -921,7 +928,7 @@ int getpeergroups(int fd, gid_t **ret) { ssize_t send_one_fd_iov_sa( int transport_fd, int fd, - struct iovec *iov, size_t iovlen, + const struct iovec *iov, size_t iovlen, const struct sockaddr *sa, socklen_t len, int flags) { @@ -929,7 +936,7 @@ ssize_t send_one_fd_iov_sa( struct msghdr mh = { .msg_name = (struct sockaddr*) sa, .msg_namelen = len, - .msg_iov = iov, + .msg_iov = (struct iovec *)iov, .msg_iovlen = iovlen, }; ssize_t k; @@ -1204,7 +1211,7 @@ int sockaddr_un_set_path(struct sockaddr_un *ret, const char *path) { /* 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 * addresses!), which the kernel doesn't. We do this to reduce chance of incompatibility with other apps that - * do not expect non-NUL terminated file system path*/ + * do not expect non-NUL terminated file system path. */ if (l+1 > sizeof(ret->sun_path)) return -EINVAL; @@ -1238,7 +1245,7 @@ int socket_bind_to_ifname(int fd, const char *ifname) { } int socket_bind_to_ifindex(int fd, int ifindex) { - char ifname[IF_NAMESIZE + 1]; + char ifname[IF_NAMESIZE]; int r; assert(fd >= 0); @@ -1256,8 +1263,9 @@ int socket_bind_to_ifindex(int fd, int ifindex) { return r; /* Fall back to SO_BINDTODEVICE on kernels < 5.0 which didn't have SO_BINDTOIFINDEX */ - if (!format_ifname(ifindex, ifname)) - return -errno; + r = format_ifname(ifindex, ifname); + if (r < 0) + return r; return socket_bind_to_ifname(fd, ifname); } |