chiark / gitweb /
kmod: automatically load a few kernel modules we need for normal operation before...
[elogind.git] / src / sd-daemon.c
index 8a7c9e8dba34231dab76ef6f005d528ff101c3a2..eec4722709cb15f89eaca9ad8e2a8aa64ad75cec 100644 (file)
@@ -133,7 +133,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 +169,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 +229,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 +258,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));
@@ -254,15 +285,16 @@ int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t
                         /* Unnamed socket */
                         return l == sizeof(sa_family_t);
 
-                if (l < sizeof(sa_family_t) + length + 1)
-                        return 0;
-
                 if (path[0])
                         /* Normal path socket */
-                        return memcmp(path, sockaddr.un.sun_path, length+1) == 0;
+                        return
+                                (l >= sizeof(sa_family_t) + length + 1) &&
+                                memcmp(path, sockaddr.un.sun_path, length+1) == 0;
                 else
                         /* Abstract namespace socket */
-                        return memcmp(path, sockaddr.un.sun_path+1, length) == 0;
+                        return
+                                (l == sizeof(sa_family_t) + length) &&
+                                memcmp(path, sockaddr.un.sun_path, length) == 0;
         }
 
         return 1;