]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-netlink: beef up sock-diag code a bit
authorLennart Poettering <lennart@amutable.com>
Tue, 2 Jun 2026 16:52:00 +0000 (18:52 +0200)
committerLennart Poettering <lennart@amutable.com>
Tue, 23 Jun 2026 21:10:01 +0000 (23:10 +0200)
Let's make it useful to enumerate AF_UNIX sockets.

src/basic/basic-forward.h
src/libsystemd/sd-netlink/netlink-sock-diag.c
src/libsystemd/sd-netlink/netlink-sock-diag.h
src/libsystemd/sd-netlink/netlink-types-sdnl.c

index 5f1bef4a3f204cac629e5b52590d8aeb67dfb225..f02801a77df2face3ee99d4897b2620014f2d06a 100644 (file)
@@ -56,6 +56,7 @@ struct statx;
 struct termios;
 struct tm;
 struct ucred;
+struct unix_diag_msg;
 
 /* To forward declare FILE and DIR, we have to declare the internal struct names for them. Since these are
  * used for C++ symbol name mangling, they're effectively part of the ABI and won't actually change. */
index 177be0c2bc84688468fd84946b15bf936a66a855..c76cef4632f615150e6b29b366ae718e770e88bc 100644 (file)
@@ -40,3 +40,51 @@ int sd_sock_diag_message_new_unix(
         *ret = TAKE_PTR(m);
         return 0;
 }
+
+int sd_sock_diag_message_new_unix_dump(
+                sd_netlink *sdnl,
+                sd_netlink_message **ret,
+                uint32_t states,
+                uint32_t show) {
+
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
+        int r;
+
+        assert_return(sdnl, -EINVAL);
+        assert_return(ret, -EINVAL);
+
+        r = message_new(sdnl, &m, SOCK_DIAG_BY_FAMILY, NLM_F_REQUEST | NLM_F_DUMP);
+        if (r < 0)
+                return r;
+
+        /* Unlike sd_sock_diag_message_new_unix() this requests a dump of all AF_UNIX sockets matching the
+         * specified state mask, rather than looking up a single socket by inode/cookie. The kernel's dump
+         * handler ignores udiag_ino/udiag_cookie, hence we leave them zeroed. */
+
+        *(struct unix_diag_req*) NLMSG_DATA(m->hdr) = (struct unix_diag_req) {
+                .sdiag_family = AF_UNIX,
+                .udiag_states = states,
+                .udiag_show = show,
+        };
+
+        *ret = TAKE_PTR(m);
+        return 0;
+}
+
+int sd_sock_diag_message_get_unix(sd_netlink_message *m, struct unix_diag_msg *ret) {
+        assert_return(m, -EINVAL);
+        assert_return(m->hdr, -EINVAL);
+        assert_return(ret, -EINVAL);
+
+        if (m->hdr->nlmsg_type != SOCK_DIAG_BY_FAMILY)
+                return -EINVAL;
+
+        if (NLMSG_PAYLOAD(m->hdr, 0) < sizeof(struct unix_diag_msg))
+                return -EBADMSG;
+
+        /* Reads out the fixed-size unix_diag_msg header that precedes the attributes in a reply. There's no
+         * sd-netlink attribute for this leading family header, hence we read it directly. */
+
+        *ret = *(struct unix_diag_msg*) NLMSG_DATA(m->hdr);
+        return 0;
+}
index e12e55a285935426b4cabc5c87c08cdbcc113764..7253193f107d83a883c74f8a2d7c841168998cdc 100644 (file)
@@ -7,3 +7,5 @@
 
 int sd_sock_diag_socket_open(sd_netlink **ret);
 int sd_sock_diag_message_new_unix(sd_netlink *sdnl, sd_netlink_message **ret, ino_t inode, uint64_t cookie, uint32_t show);
+int sd_sock_diag_message_new_unix_dump(sd_netlink *sdnl, sd_netlink_message **ret, uint32_t states, uint32_t show);
+int sd_sock_diag_message_get_unix(sd_netlink_message *m, struct unix_diag_msg *ret);
index 6b72efb86bc08e97f207c174c246ab1d5cb8f393..6e08825513b5b719676b3c5f4111a2a60798306e 100644 (file)
@@ -18,6 +18,8 @@ static const NLAPolicy sdnl_req_policies[] = {
 DEFINE_POLICY_SET(sdnl_req);
 
 static const NLAPolicy unix_diag_msg_policies[] = {
+        [UNIX_DIAG_NAME]  = BUILD_POLICY(STRING), /* Note: not NUL-terminated on the wire, read via sd_netlink_message_read_data() */
+        [UNIX_DIAG_VFS]   = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct unix_diag_vfs)),
         [UNIX_DIAG_RQLEN] = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct unix_diag_rqlen)),
 };
 DEFINE_POLICY_SET(unix_diag_msg);