]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/basic/socket-util.c
tree-wide: use -EBADF for fd initialization
[thirdparty/systemd.git] / src / basic / socket-util.c
index 0dfe2a7dbca0e9c791835d59c04e7049a2412d88..54f5f1cc5bca053d88e910e7609e00abf70ec5f7 100644 (file)
@@ -490,9 +490,7 @@ int sockaddr_pretty(
                         if (r < 0)
                                 return -ENOMEM;
                 } else {
-                        char a[INET6_ADDRSTRLEN];
-
-                        inet_ntop(AF_INET6, &sa->in6.sin6_addr, a, sizeof(a));
+                        const char *a = IN6_ADDR_TO_STRING(&sa->in6.sin6_addr);
 
                         if (include_port) {
                                 if (asprintf(&p,
@@ -651,24 +649,24 @@ int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret)
 }
 
 static const char* const netlink_family_table[] = {
-        [NETLINK_ROUTE] = "route",
-        [NETLINK_FIREWALL] = "firewall",
-        [NETLINK_INET_DIAG] = "inet-diag",
-        [NETLINK_NFLOG] = "nflog",
-        [NETLINK_XFRM] = "xfrm",
-        [NETLINK_SELINUX] = "selinux",
-        [NETLINK_ISCSI] = "iscsi",
-        [NETLINK_AUDIT] = "audit",
-        [NETLINK_FIB_LOOKUP] = "fib-lookup",
-        [NETLINK_CONNECTOR] = "connector",
-        [NETLINK_NETFILTER] = "netfilter",
-        [NETLINK_IP6_FW] = "ip6-fw",
-        [NETLINK_DNRTMSG] = "dnrtmsg",
+        [NETLINK_ROUTE]          = "route",
+        [NETLINK_FIREWALL]       = "firewall",
+        [NETLINK_INET_DIAG]      = "inet-diag",
+        [NETLINK_NFLOG]          = "nflog",
+        [NETLINK_XFRM]           = "xfrm",
+        [NETLINK_SELINUX]        = "selinux",
+        [NETLINK_ISCSI]          = "iscsi",
+        [NETLINK_AUDIT]          = "audit",
+        [NETLINK_FIB_LOOKUP]     = "fib-lookup",
+        [NETLINK_CONNECTOR]      = "connector",
+        [NETLINK_NETFILTER]      = "netfilter",
+        [NETLINK_IP6_FW]         = "ip6-fw",
+        [NETLINK_DNRTMSG]        = "dnrtmsg",
         [NETLINK_KOBJECT_UEVENT] = "kobject-uevent",
-        [NETLINK_GENERIC] = "generic",
-        [NETLINK_SCSITRANSPORT] = "scsitransport",
-        [NETLINK_ECRYPTFS] = "ecryptfs",
-        [NETLINK_RDMA] = "rdma",
+        [NETLINK_GENERIC]        = "generic",
+        [NETLINK_SCSITRANSPORT]  = "scsitransport",
+        [NETLINK_ECRYPTFS]       = "ecryptfs",
+        [NETLINK_RDMA]           = "rdma",
 };
 
 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(netlink_family, int, INT_MAX);
@@ -775,10 +773,10 @@ int fd_set_rcvbuf(int fd, size_t n, bool increase) {
 }
 
 static const char* const ip_tos_table[] = {
-        [IPTOS_LOWDELAY] = "low-delay",
-        [IPTOS_THROUGHPUT] = "throughput",
+        [IPTOS_LOWDELAY]    = "low-delay",
+        [IPTOS_THROUGHPUT]  = "throughput",
         [IPTOS_RELIABILITY] = "reliability",
-        [IPTOS_LOWCOST] = "low-cost",
+        [IPTOS_LOWCOST]     = "low-cost",
 };
 
 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff);
@@ -835,7 +833,7 @@ bool ifname_valid_full(const char *p, IfnameValidFlags flags) {
                 if (!ifname_valid_char(*t))
                         return false;
 
-                numeric = numeric && (*t >= '0' && *t <= '9');
+                numeric = numeric && ascii_isdigit(*t);
         }
 
         /* It's fully numeric but didn't parse as valid ifindex above? if so, it must be too large or zero or
@@ -1051,7 +1049,7 @@ ssize_t receive_one_fd_iov(
         if (found)
                 *ret_fd = *(int*) CMSG_DATA(found);
         else
-                *ret_fd = -1;
+                *ret_fd = -EBADF;
 
         return k;
 }
@@ -1426,3 +1424,51 @@ int socket_get_mtu(int fd, int af, size_t *ret) {
         *ret = (size_t) mtu;
         return 0;
 }
+
+int connect_unix_path(int fd, int dir_fd, const char *path) {
+        _cleanup_close_ int inode_fd = -EBADF;
+        union sockaddr_union sa = {
+                .un.sun_family = AF_UNIX,
+        };
+        size_t path_len;
+        socklen_t salen;
+
+        assert(fd >= 0);
+        assert(dir_fd == AT_FDCWD || dir_fd >= 0);
+        assert(path);
+
+        /* Connects to the specified AF_UNIX socket in the file system. Works around the 108 byte size limit
+         * in sockaddr_un, by going via O_PATH if needed. This hence works for any kind of path. */
+
+        path_len = strlen(path);
+
+        /* Refuse zero length path early, to make sure AF_UNIX stack won't mistake this for an abstract
+         * namespace path, since first char is NUL */
+        if (path_len <= 0)
+                return -EINVAL;
+
+        if (dir_fd == AT_FDCWD && path_len < sizeof(sa.un.sun_path)) {
+                memcpy(sa.un.sun_path, path, path_len + 1);
+                salen = offsetof(struct sockaddr_un, sun_path) + path_len + 1;
+        } else {
+                const char *proc;
+                size_t proc_len;
+
+                /* If dir_fd is specified, then we need to go the indirect O_PATH route, because connectat()
+                 * does not exist. If the path is too long, we also need to take the indirect route, since we
+                 * can't fit this into a sockaddr_un directly. */
+
+                inode_fd = openat(dir_fd, path, O_PATH|O_CLOEXEC);
+                if (inode_fd < 0)
+                        return -errno;
+
+                proc = FORMAT_PROC_FD_PATH(inode_fd);
+                proc_len = strlen(proc);
+
+                assert(proc_len < sizeof(sa.un.sun_path));
+                memcpy(sa.un.sun_path, proc, proc_len + 1);
+                salen = offsetof(struct sockaddr_un, sun_path) + proc_len + 1;
+        }
+
+        return RET_NERRNO(connect(fd, &sa.sa, salen));
+}