summary refs log tree commit diff
path: root/src/systemd/src/basic/socket-util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/systemd/src/basic/socket-util.c')
-rw-r--r--src/systemd/src/basic/socket-util.c163
1 files changed, 66 insertions, 97 deletions
diff --git a/src/systemd/src/basic/socket-util.c b/src/systemd/src/basic/socket-util.c
index 8ae68b6f..798ab16e 100644
--- a/src/systemd/src/basic/socket-util.c
+++ b/src/systemd/src/basic/socket-util.c
@@ -1,4 +1,3 @@
-/* SPDX-License-Identifier: LGPL-2.1+ */
 /***
   This file is part of systemd.
 
@@ -43,7 +42,6 @@
 #include "missing.h"
 #include "parse-util.h"
 #include "path-util.h"
-#include "process-util.h"
 #include "socket-util.h"
 #include "string-table.h"
 #include "string-util.h"
@@ -54,24 +52,14 @@
 
 #if 0 /* NM_IGNORED */
 #if ENABLE_IDN
-#  define IDN_FLAGS NI_IDN
+#  define IDN_FLAGS (NI_IDN|NI_IDN_USE_STD3_ASCII_RULES)
 #else
 #  define IDN_FLAGS 0
 #endif
 
-static const char* const socket_address_type_table[] = {
-        [SOCK_STREAM] = "Stream",
-        [SOCK_DGRAM] = "Datagram",
-        [SOCK_RAW] = "Raw",
-        [SOCK_RDM] = "ReliableDatagram",
-        [SOCK_SEQPACKET] = "SequentialPacket",
-        [SOCK_DCCP] = "DatagramCongestionControl",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(socket_address_type, int);
-
 int socket_address_parse(SocketAddress *a, const char *s) {
         char *e, *n;
+        unsigned u;
         int r;
 
         assert(a);
@@ -81,8 +69,6 @@ int socket_address_parse(SocketAddress *a, const char *s) {
         a->type = SOCK_STREAM;
 
         if (*s == '[') {
-                uint16_t port;
-
                 /* IPv6 in [x:.....:z]:p notation */
 
                 e = strchr(s+1, ']');
@@ -100,12 +86,15 @@ int socket_address_parse(SocketAddress *a, const char *s) {
                         return -EINVAL;
 
                 e++;
-                r = parse_ip_port(e, &port);
+                r = safe_atou(e, &u);
                 if (r < 0)
                         return r;
 
+                if (u <= 0 || u > 0xFFFF)
+                        return -EINVAL;
+
                 a->sockaddr.in6.sin6_family = AF_INET6;
-                a->sockaddr.in6.sin6_port = htobe16(port);
+                a->sockaddr.in6.sin6_port = htobe16((uint16_t)u);
                 a->size = sizeof(struct sockaddr_in6);
 
         } else if (*s == '/') {
@@ -135,14 +124,13 @@ int socket_address_parse(SocketAddress *a, const char *s) {
 
         } else if (startswith(s, "vsock:")) {
                 /* AF_VSOCK socket in vsock:cid:port notation */
-                const char *cid_start = s + STRLEN("vsock:");
-                unsigned port;
+                const char *cid_start = s + strlen("vsock:");
 
                 e = strchr(cid_start, ':');
                 if (!e)
                         return -EINVAL;
 
-                r = safe_atou(e+1, &port);
+                r = safe_atou(e+1, &u);
                 if (r < 0)
                         return r;
 
@@ -155,18 +143,19 @@ int socket_address_parse(SocketAddress *a, const char *s) {
                         a->sockaddr.vm.svm_cid = VMADDR_CID_ANY;
 
                 a->sockaddr.vm.svm_family = AF_VSOCK;
-                a->sockaddr.vm.svm_port = port;
+                a->sockaddr.vm.svm_port = u;
                 a->size = sizeof(struct sockaddr_vm);
 
         } else {
-                uint16_t port;
-
                 e = strchr(s, ':');
                 if (e) {
-                        r = parse_ip_port(e + 1, &port);
+                        r = safe_atou(e+1, &u);
                         if (r < 0)
                                 return r;
 
+                        if (u <= 0 || u > 0xFFFF)
+                                return -EINVAL;
+
                         n = strndupa(s, e-s);
 
                         /* IPv4 in w.x.y.z:p notation? */
@@ -177,7 +166,7 @@ int socket_address_parse(SocketAddress *a, const char *s) {
                         if (r > 0) {
                                 /* Gotcha, it's a traditional IPv4 address */
                                 a->sockaddr.in.sin_family = AF_INET;
-                                a->sockaddr.in.sin_port = htobe16(port);
+                                a->sockaddr.in.sin_port = htobe16((uint16_t)u);
                                 a->size = sizeof(struct sockaddr_in);
                         } else {
                                 unsigned idx;
@@ -191,7 +180,7 @@ int socket_address_parse(SocketAddress *a, const char *s) {
                                         return -EINVAL;
 
                                 a->sockaddr.in6.sin6_family = AF_INET6;
-                                a->sockaddr.in6.sin6_port = htobe16(port);
+                                a->sockaddr.in6.sin6_port = htobe16((uint16_t)u);
                                 a->sockaddr.in6.sin6_scope_id = idx;
                                 a->sockaddr.in6.sin6_addr = in6addr_any;
                                 a->size = sizeof(struct sockaddr_in6);
@@ -199,18 +188,21 @@ int socket_address_parse(SocketAddress *a, const char *s) {
                 } else {
 
                         /* Just a port */
-                        r = parse_ip_port(s, &port);
+                        r = safe_atou(s, &u);
                         if (r < 0)
                                 return r;
 
+                        if (u <= 0 || u > 0xFFFF)
+                                return -EINVAL;
+
                         if (socket_ipv6_is_supported()) {
                                 a->sockaddr.in6.sin6_family = AF_INET6;
-                                a->sockaddr.in6.sin6_port = htobe16(port);
+                                a->sockaddr.in6.sin6_port = htobe16((uint16_t)u);
                                 a->sockaddr.in6.sin6_addr = in6addr_any;
                                 a->size = sizeof(struct sockaddr_in6);
                         } else {
                                 a->sockaddr.in.sin_family = AF_INET;
-                                a->sockaddr.in.sin_port = htobe16(port);
+                                a->sockaddr.in.sin_port = htobe16((uint16_t)u);
                                 a->sockaddr.in.sin_addr.s_addr = INADDR_ANY;
                                 a->size = sizeof(struct sockaddr_in);
                         }
@@ -538,25 +530,22 @@ bool socket_address_matches_fd(const SocketAddress *a, int fd) {
         return socket_address_equal(a, &b);
 }
 
-int sockaddr_port(const struct sockaddr *_sa, unsigned *ret_port) {
+int sockaddr_port(const struct sockaddr *_sa, unsigned *port) {
         union sockaddr_union *sa = (union sockaddr_union*) _sa;
 
-        /* Note, this returns the port as 'unsigned' rather than 'uint16_t', as AF_VSOCK knows larger ports */
-
         assert(sa);
 
         switch (sa->sa.sa_family) {
-
         case AF_INET:
-                *ret_port = be16toh(sa->in.sin_port);
+                *port = be16toh(sa->in.sin_port);
                 return 0;
 
         case AF_INET6:
-                *ret_port = be16toh(sa->in6.sin6_port);
+                *port = be16toh(sa->in6.sin6_port);
                 return 0;
 
         case AF_VSOCK:
-                *ret_port = sa->vm.svm_port;
+                *port = sa->vm.svm_port;
                 return 0;
 
         default:
@@ -761,6 +750,19 @@ int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret)
         return 0;
 }
 
+int getnameinfo_pretty(int fd, char **ret) {
+        union sockaddr_union sa;
+        socklen_t salen = sizeof(sa);
+
+        assert(fd >= 0);
+        assert(ret);
+
+        if (getsockname(fd, &sa.sa, &salen) < 0)
+                return -errno;
+
+        return socknameinfo_pretty(&sa, salen, ret);
+}
+
 int socket_address_unlink(SocketAddress *a) {
         assert(a);
 
@@ -807,18 +809,6 @@ static const char* const socket_address_bind_ipv6_only_table[_SOCKET_ADDRESS_BIN
 
 DEFINE_STRING_TABLE_LOOKUP(socket_address_bind_ipv6_only, SocketAddressBindIPv6Only);
 
-SocketAddressBindIPv6Only parse_socket_address_bind_ipv6_only_or_bool(const char *n) {
-        int r;
-
-        r = parse_boolean(n);
-        if (r > 0)
-                return SOCKET_ADDRESS_IPV6_ONLY;
-        if (r == 0)
-                return SOCKET_ADDRESS_BOTH;
-
-        return socket_address_bind_ipv6_only_from_string(n);
-}
-
 bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b) {
         assert(a);
         assert(b);
@@ -953,77 +943,56 @@ int getpeercred(int fd, struct ucred *ucred) {
         if (n != sizeof(struct ucred))
                 return -EIO;
 
-        /* Check if the data is actually useful and not suppressed due to namespacing issues */
-        if (!pid_is_valid(u.pid))
+        /* Check if the data is actually useful and not suppressed due
+         * to namespacing issues */
+        if (u.pid <= 0)
+                return -ENODATA;
+        if (u.uid == UID_INVALID)
+                return -ENODATA;
+        if (u.gid == GID_INVALID)
                 return -ENODATA;
-
-        /* Note that we don't check UID/GID here, as namespace translation works differently there: instead of
-         * receiving in "invalid" user/group we get the overflow UID/GID. */
 
         *ucred = u;
         return 0;
 }
 
 int getpeersec(int fd, char **ret) {
-        _cleanup_free_ char *s = NULL;
         socklen_t n = 64;
+        char *s;
+        int r;
 
         assert(fd >= 0);
         assert(ret);
 
-        for (;;) {
-                s = new0(char, n+1);
-                if (!s)
-                        return -ENOMEM;
+        s = new0(char, n);
+        if (!s)
+                return -ENOMEM;
 
-                if (getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n) >= 0)
-                        break;
+        r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
+        if (r < 0) {
+                free(s);
 
                 if (errno != ERANGE)
                         return -errno;
 
-                s = mfree(s);
-        }
-
-        if (isempty(s))
-                return -EOPNOTSUPP;
-
-        *ret = TAKE_PTR(s);
-
-        return 0;
-}
-
-int getpeergroups(int fd, gid_t **ret) {
-        socklen_t n = sizeof(gid_t) * 64;
-        _cleanup_free_ gid_t *d = NULL;
-
-        assert(fd >= 0);
-        assert(ret);
-
-        for (;;) {
-                d = malloc(n);
-                if (!d)
+                s = new0(char, n);
+                if (!s)
                         return -ENOMEM;
 
-                if (getsockopt(fd, SOL_SOCKET, SO_PEERGROUPS, d, &n) >= 0)
-                        break;
-
-                if (errno != ERANGE)
+                r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
+                if (r < 0) {
+                        free(s);
                         return -errno;
-
-                d = mfree(d);
+                }
         }
 
-        assert_se(n % sizeof(gid_t) == 0);
-        n /= sizeof(gid_t);
-
-        if ((socklen_t) (int) n != n)
-                return -E2BIG;
-
-        *ret = d;
-        d = NULL;
+        if (isempty(s)) {
+                free(s);
+                return -EOPNOTSUPP;
+        }
 
-        return (int) n;
+        *ret = s;
+        return 0;
 }
 
 int send_one_fd_sa(