]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/basic/socket-label.c
Merge pull request #11827 from keszybz/pkgconfig-variables
[thirdparty/systemd.git] / src / basic / socket-label.c
index 20be406371ca686b7fcfd9249f03bff09baa0cf0..4ed19cd937573168550a4bdb2f22b0372b99495f 100644 (file)
@@ -1,22 +1,4 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
-/***
-  This file is part of systemd.
-
-  Copyright 2010 Lennart Poettering
-
-  systemd is free software; you can redistribute it and/or modify it
-  under the terms of the GNU Lesser General Public License as published by
-  the Free Software Foundation; either version 2.1 of the License, or
-  (at your option) any later version.
-
-  systemd is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
 
 #include <errno.h>
 #include <netinet/in.h>
@@ -29,6 +11,7 @@
 
 #include "alloc-util.h"
 #include "fd-util.h"
+#include "fs-util.h"
 #include "log.h"
 #include "macro.h"
 #include "missing.h"
@@ -51,11 +34,12 @@ int socket_address_listen(
                 const char *label) {
 
         _cleanup_close_ int fd = -1;
-        int r, one;
+        const char *p;
+        int r;
 
         assert(a);
 
-        r = socket_address_verify(a);
+        r = socket_address_verify(a, true);
         if (r < 0)
                 return r;
 
@@ -78,10 +62,9 @@ int socket_address_listen(
                 return r;
 
         if (socket_address_family(a) == AF_INET6 && only != SOCKET_ADDRESS_DEFAULT) {
-                int flag = only == SOCKET_ADDRESS_IPV6_ONLY;
-
-                if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &flag, sizeof(flag)) < 0)
-                        return -errno;
+                r = setsockopt_int(fd, IPPROTO_IPV6, IPV6_V6ONLY, only == SOCKET_ADDRESS_IPV6_ONLY);
+                if (r < 0)
+                        return r;
         }
 
         if (IN_SET(socket_address_family(a), AF_INET, AF_INET6)) {
@@ -90,41 +73,45 @@ int socket_address_listen(
                                 return -errno;
 
                 if (reuse_port) {
-                        one = 1;
-                        if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)) < 0)
-                                log_warning_errno(errno, "SO_REUSEPORT failed: %m");
+                        r = setsockopt_int(fd, SOL_SOCKET, SO_REUSEPORT, true);
+                        if (r < 0)
+                                log_warning_errno(r, "SO_REUSEPORT failed: %m");
                 }
 
                 if (free_bind) {
-                        one = 1;
-                        if (setsockopt(fd, IPPROTO_IP, IP_FREEBIND, &one, sizeof(one)) < 0)
-                                log_warning_errno(errno, "IP_FREEBIND failed: %m");
+                        r = setsockopt_int(fd, IPPROTO_IP, IP_FREEBIND, true);
+                        if (r < 0)
+                                log_warning_errno(r, "IP_FREEBIND failed: %m");
                 }
 
                 if (transparent) {
-                        one = 1;
-                        if (setsockopt(fd, IPPROTO_IP, IP_TRANSPARENT, &one, sizeof(one)) < 0)
-                                log_warning_errno(errno, "IP_TRANSPARENT failed: %m");
+                        r = setsockopt_int(fd, IPPROTO_IP, IP_TRANSPARENT, true);
+                        if (r < 0)
+                                log_warning_errno(r, "IP_TRANSPARENT failed: %m");
                 }
         }
 
-        one = 1;
-        if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0)
-                return -errno;
+        r = setsockopt_int(fd, SOL_SOCKET, SO_REUSEADDR, true);
+        if (r < 0)
+                return r;
 
-        if (socket_address_family(a) == AF_UNIX && a->sockaddr.un.sun_path[0] != 0) {
+        p = socket_address_get_path(a);
+        if (p) {
                 /* Create parents */
-                (void) mkdir_parents_label(a->sockaddr.un.sun_path, directory_mode);
+                (void) mkdir_parents_label(p, directory_mode);
 
                 /* Enforce the right access mode for the socket */
                 RUN_WITH_UMASK(~socket_mode) {
                         r = mac_selinux_bind(fd, &a->sockaddr.sa, a->size);
                         if (r == -EADDRINUSE) {
                                 /* Unlink and try again */
-                                unlink(a->sockaddr.un.sun_path);
-                                if (bind(fd, &a->sockaddr.sa, a->size) < 0)
-                                        return -errno;
-                        } else if (r < 0)
+
+                                if (unlink(p) < 0)
+                                        return r; /* didn't work, return original error */
+
+                                r = mac_selinux_bind(fd, &a->sockaddr.sa, a->size);
+                        }
+                        if (r < 0)
                                 return r;
                 }
         } else {
@@ -136,6 +123,11 @@ int socket_address_listen(
                 if (listen(fd, backlog) < 0)
                         return -errno;
 
+        /* Let's trigger an inotify event on the socket node, so that anyone waiting for this socket to be connectable
+         * gets notified */
+        if (p)
+                (void) touch(p);
+
         r = fd;
         fd = -1;