summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile-man.am5
-rw-r--r--man/sd_is_fifo.xml30
-rw-r--r--src/libsystemd/libsystemd.sym1
-rw-r--r--src/libsystemd/sd-daemon/sd-daemon.c58
-rw-r--r--src/systemd/sd-daemon.h13
5 files changed, 106 insertions, 1 deletions
diff --git a/Makefile-man.am b/Makefile-man.am
index 228e29fc4f..5e6eee5e32 100644
--- a/Makefile-man.am
+++ b/Makefile-man.am
@@ -403,6 +403,7 @@ MANPAGES_ALIAS += \
man/sd_is_mq.3 \
man/sd_is_socket.3 \
man/sd_is_socket_inet.3 \
+ man/sd_is_socket_sockaddr.3 \
man/sd_is_socket_unix.3 \
man/sd_is_special.3 \
man/sd_journal.3 \
@@ -757,6 +758,7 @@ man/sd_id128_t.3: man/sd-id128.3
man/sd_is_mq.3: man/sd_is_fifo.3
man/sd_is_socket.3: man/sd_is_fifo.3
man/sd_is_socket_inet.3: man/sd_is_fifo.3
+man/sd_is_socket_sockaddr.3: man/sd_is_fifo.3
man/sd_is_socket_unix.3: man/sd_is_fifo.3
man/sd_is_special.3: man/sd_is_fifo.3
man/sd_journal.3: man/sd_journal_open.3
@@ -1551,6 +1553,9 @@ man/sd_is_socket.html: man/sd_is_fifo.html
man/sd_is_socket_inet.html: man/sd_is_fifo.html
$(html-alias)
+man/sd_is_socket_sockaddr.html: man/sd_is_fifo.html
+ $(html-alias)
+
man/sd_is_socket_unix.html: man/sd_is_fifo.html
$(html-alias)
diff --git a/man/sd_is_fifo.xml b/man/sd_is_fifo.xml
index 991c7f8bd8..1192ca1681 100644
--- a/man/sd_is_fifo.xml
+++ b/man/sd_is_fifo.xml
@@ -48,6 +48,7 @@
<refname>sd_is_socket</refname>
<refname>sd_is_socket_inet</refname>
<refname>sd_is_socket_unix</refname>
+ <refname>sd_is_socket_sockaddr</refname>
<refname>sd_is_mq</refname>
<refname>sd_is_special</refname>
<refpurpose>Check the type of a file descriptor</refpurpose>
@@ -81,6 +82,15 @@
</funcprototype>
<funcprototype>
+ <funcdef>int <function>sd_is_socket_sockaddr</function></funcdef>
+ <paramdef>int <parameter>fd</parameter></paramdef>
+ <paramdef>int <parameter>type</parameter></paramdef>
+ <paramdef>const struct sockaddr *<parameter>addr</parameter></paramdef>
+ <paramdef>unsigned <parameter>addr_len</parameter></paramdef>
+ <paramdef>int <parameter>listening</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
<funcdef>int <function>sd_is_socket_unix</function></funcdef>
<paramdef>int <parameter>fd</parameter></paramdef>
<paramdef>int <parameter>type</parameter></paramdef>
@@ -139,6 +149,18 @@
<constant>AF_UNSPEC</constant>, <constant>AF_INET</constant>, or
<constant>AF_INET6</constant>.</para>
+ <para><function>sd_is_socket_sockaddr()</function> is similar to
+ <function>sd_is_socket_inet()</function>, but checks if the socket is bound to the
+ address specified by <parameter>addr</parameter>. The
+ <structfield>family</structfield> specified by <parameter>addr</parameter> must be
+ either <constant>AF_INET</constant> or <constant>AF_INET6</constant> and
+ <parameter>addr_len</parameter> must be large enough for that family. If
+ <parameter>addr</parameter> specifies a non-zero port, it is also checked if the
+ socket is bound to this port. In addition, for IPv6, if <parameter>addr</parameter>
+ specifies non-zero <structfield>sin6_flowinfo</structfield> or
+ <structfield>sin6_scope_id</structfield>, it is checked if the socket has the same
+ values.</para>
+
<para><function>sd_is_socket_unix()</function> is similar to
<function>sd_is_socket()</function> but optionally checks the
<constant>AF_UNIX</constant> path the socket is bound to, unless
@@ -193,7 +215,13 @@
<citerefentry><refentrytitle>sd-daemon</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_listen_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>ip</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>ipv6</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>unix</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>fifo</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>mq_overview</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>socket</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
</para>
</refsect1>
diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym
index 46c4dac7d7..c1135ffa22 100644
--- a/src/libsystemd/libsystemd.sym
+++ b/src/libsystemd/libsystemd.sym
@@ -515,4 +515,5 @@ global:
LIBSYSTEMD_233 {
global:
sd_id128_get_machine_app_specific;
+ sd_is_socket_sockaddr;
} LIBSYSTEMD_232;
diff --git a/src/libsystemd/sd-daemon/sd-daemon.c b/src/libsystemd/sd-daemon/sd-daemon.c
index b20a7ebb4c..a9a32dd5a2 100644
--- a/src/libsystemd/sd-daemon/sd-daemon.c
+++ b/src/libsystemd/sd-daemon/sd-daemon.c
@@ -322,6 +322,64 @@ _public_ int sd_is_socket_inet(int fd, int family, int type, int listening, uint
return 1;
}
+_public_ int sd_is_socket_sockaddr(int fd, int type, const struct sockaddr* addr, unsigned addr_len, int listening) {
+ union sockaddr_union sockaddr = {};
+ socklen_t l = sizeof(sockaddr);
+ int r;
+
+ assert_return(fd >= 0, -EBADF);
+ assert_return(addr, -EINVAL);
+ assert_return(addr_len >= sizeof(sa_family_t), -ENOBUFS);
+ assert_return(IN_SET(addr->sa_family, AF_INET, AF_INET6), -EPFNOSUPPORT);
+
+ r = sd_is_socket_internal(fd, type, listening);
+ if (r <= 0)
+ return r;
+
+ if (getsockname(fd, &sockaddr.sa, &l) < 0)
+ return -errno;
+
+ if (l < sizeof(sa_family_t))
+ return -EINVAL;
+
+ if (sockaddr.sa.sa_family != addr->sa_family)
+ return 0;
+
+ if (sockaddr.sa.sa_family == AF_INET) {
+ const struct sockaddr_in *in = (const struct sockaddr_in *) addr;
+
+ if (l < sizeof(struct sockaddr_in) || addr_len < sizeof(struct sockaddr_in))
+ return -EINVAL;
+
+ if (in->sin_port != 0 &&
+ sockaddr.in.sin_port != in->sin_port)
+ return false;
+
+ return sockaddr.in.sin_addr.s_addr == in->sin_addr.s_addr;
+
+ } else {
+ const struct sockaddr_in6 *in = (const struct sockaddr_in6 *) addr;
+
+ if (l < sizeof(struct sockaddr_in6) || addr_len < sizeof(struct sockaddr_in6))
+ return -EINVAL;
+
+ if (in->sin6_port != 0 &&
+ sockaddr.in6.sin6_port != in->sin6_port)
+ return false;
+
+ if (in->sin6_flowinfo != 0 &&
+ sockaddr.in6.sin6_flowinfo != in->sin6_flowinfo)
+ return false;
+
+ if (in->sin6_scope_id != 0 &&
+ sockaddr.in6.sin6_scope_id != in->sin6_scope_id)
+ return false;
+
+ return memcmp(sockaddr.in6.sin6_addr.s6_addr, in->sin6_addr.s6_addr,
+ sizeof(in->sin6_addr.s6_addr)) == 0;
+ }
+}
+
_public_ int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) {
union sockaddr_union sockaddr = {};
socklen_t l = sizeof(sockaddr);
diff --git a/src/systemd/sd-daemon.h b/src/systemd/sd-daemon.h
index 740b176903..8c096f610f 100644
--- a/src/systemd/sd-daemon.h
+++ b/src/systemd/sd-daemon.h
@@ -22,6 +22,7 @@
#include <inttypes.h>
#include <sys/types.h>
+#include <sys/socket.h>
#include "_sd-common.h"
@@ -131,6 +132,18 @@ int sd_is_socket(int fd, int family, int type, int listening);
int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port);
/*
+ Helper call for identifying a passed file descriptor. Returns 1 if the
+ file descriptor is an Internet socket of the specified type
+ (SOCK_DGRAM, SOCK_STREAM, ...), and if the address of the socket is
+ the same as the address specified by addr. The listening flag is used
+ the same way as in sd_is_socket(). Returns a negative errno style
+ error code on failure.
+
+ See sd_is_socket_sockaddr(3) for more information.
+*/
+int sd_is_socket_sockaddr(int fd, int type, const struct sockaddr* addr, unsigned addr_len, int listening);
+
+/*
Helper call for identifying a passed file descriptor. Returns 1 if
the file descriptor is an AF_UNIX socket of the specified type
(SOCK_DGRAM, SOCK_STREAM, ...) and path, 0 otherwise. If type is 0