diff options
-rw-r--r-- | Makefile-man.am | 5 | ||||
-rw-r--r-- | man/sd_is_fifo.xml | 30 | ||||
-rw-r--r-- | src/libsystemd/libsystemd.sym | 1 | ||||
-rw-r--r-- | src/libsystemd/sd-daemon/sd-daemon.c | 58 | ||||
-rw-r--r-- | src/systemd/sd-daemon.h | 13 |
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 |