#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
+#include <sys/fcntl.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <errno.h>
#ifdef DISABLE_SYSTEMD
return 0;
#else
- int r;
+ int r, fd;
const char *e;
char *p = NULL;
unsigned long l;
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:
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)
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));
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))
}
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));