X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fsd-daemon.c;h=29bd20468001a012417ba7e3e686512b4454c803;hp=62936ec5b4e66c0f98b906851a56838c5eb5d200;hb=695d1ef183a2200cf5f32998f9bd7eb0d8b56ac2;hpb=cd250a39da8d5b9c0d220a07e765064638708fe9 diff --git a/src/sd-daemon.c b/src/sd-daemon.c index 62936ec5b..29bd20468 100644 --- a/src/sd-daemon.c +++ b/src/sd-daemon.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -41,7 +42,7 @@ int sd_listen_fds(int unset_environment) { #ifdef DISABLE_SYSTEMD return 0; #else - int r; + int r, fd; const char *e; char *p = NULL; unsigned long l; @@ -88,6 +89,23 @@ int sd_listen_fds(int unset_environment) { goto finish; } + for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + (int) l; fd ++) { + int flags; + + if ((flags = fcntl(fd, F_GETFD)) < 0) { + r = -errno; + goto finish; + } + + if (flags & FD_CLOEXEC) + continue; + + if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) { + r = -errno; + goto finish; + } + } + r = (int) l; finish: @@ -133,7 +151,7 @@ int sd_is_fifo(int fd, const char *path) { return 1; } -int sd_is_socket(int fd, int type, int listening) { +static int sd_is_socket_internal(int fd, int type, int listening) { struct stat st_fd; if (fd < 0 || type < 0) @@ -169,25 +187,58 @@ int sd_is_socket(int fd, int type, int listening) { if (l != sizeof(accepting)) return -EINVAL; - if (!accepting == !listening) + if (!accepting != !listening) return 0; } return 1; } -int sd_is_socket_inet(int fd, int type, int listening, uint16_t port) { - union { - struct sockaddr sa; - struct sockaddr_in in4; - struct sockaddr_in6 in6; - struct sockaddr_un un; - struct sockaddr_storage storage; - } sockaddr; +union sockaddr_union { + struct sockaddr sa; + struct sockaddr_in in4; + struct sockaddr_in6 in6; + struct sockaddr_un un; + struct sockaddr_storage storage; +}; + +int sd_is_socket(int fd, int family, int type, int listening) { + int r; + + if (family < 0) + return -EINVAL; + + if ((r = sd_is_socket_internal(fd, type, listening)) <= 0) + return r; + + if (family > 0) { + union sockaddr_union sockaddr; + socklen_t l; + + memset(&sockaddr, 0, sizeof(sockaddr)); + l = sizeof(sockaddr); + + if (getsockname(fd, &sockaddr.sa, &l) < 0) + return -errno; + + if (l < sizeof(sa_family_t)) + return -EINVAL; + + return sockaddr.sa.sa_family == family; + } + + return 1; +} + +int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port) { + union sockaddr_union sockaddr; socklen_t l; int r; - if ((r = sd_is_socket(fd, type, listening)) <= 0) + if (family != 0 && family != AF_INET && family != AF_INET6) + return -EINVAL; + + if ((r = sd_is_socket_internal(fd, type, listening)) <= 0) return r; memset(&sockaddr, 0, sizeof(sockaddr)); @@ -196,13 +247,17 @@ int sd_is_socket_inet(int fd, int type, int listening, uint16_t port) { if (getsockname(fd, &sockaddr.sa, &l) < 0) return -errno; - if (l < sizeof(struct sockaddr)) + if (l < sizeof(sa_family_t)) return -EINVAL; if (sockaddr.sa.sa_family != AF_INET && sockaddr.sa.sa_family != AF_INET6) return 0; + if (family > 0) + if (sockaddr.sa.sa_family != family) + return 0; + if (port > 0) { if (sockaddr.sa.sa_family == AF_INET) { if (l < sizeof(struct sockaddr_in)) @@ -221,17 +276,11 @@ int sd_is_socket_inet(int fd, int type, int listening, uint16_t port) { } int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) { - union { - struct sockaddr sa; - struct sockaddr_in in4; - struct sockaddr_in6 in6; - struct sockaddr_un un; - struct sockaddr_storage storage; - } sockaddr; + union sockaddr_union sockaddr; socklen_t l; int r; - if ((r = sd_is_socket(fd, type, listening)) <= 0) + if ((r = sd_is_socket_internal(fd, type, listening)) <= 0) return r; memset(&sockaddr, 0, sizeof(sockaddr));