From: Lennart Poettering Date: Tue, 2 Jun 2026 16:52:00 +0000 (+0200) Subject: sd-netlink: beef up sock-diag code a bit X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=daae289f1024f2203c38ff2074f2392305eab90d;p=thirdparty%2Fsystemd.git sd-netlink: beef up sock-diag code a bit Let's make it useful to enumerate AF_UNIX sockets. --- diff --git a/src/basic/basic-forward.h b/src/basic/basic-forward.h index 5f1bef4a3f2..f02801a77df 100644 --- a/src/basic/basic-forward.h +++ b/src/basic/basic-forward.h @@ -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. */ diff --git a/src/libsystemd/sd-netlink/netlink-sock-diag.c b/src/libsystemd/sd-netlink/netlink-sock-diag.c index 177be0c2bc8..c76cef4632f 100644 --- a/src/libsystemd/sd-netlink/netlink-sock-diag.c +++ b/src/libsystemd/sd-netlink/netlink-sock-diag.c @@ -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; +} diff --git a/src/libsystemd/sd-netlink/netlink-sock-diag.h b/src/libsystemd/sd-netlink/netlink-sock-diag.h index e12e55a2859..7253193f107 100644 --- a/src/libsystemd/sd-netlink/netlink-sock-diag.h +++ b/src/libsystemd/sd-netlink/netlink-sock-diag.h @@ -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); diff --git a/src/libsystemd/sd-netlink/netlink-types-sdnl.c b/src/libsystemd/sd-netlink/netlink-types-sdnl.c index 6b72efb86bc..6e08825513b 100644 --- a/src/libsystemd/sd-netlink/netlink-types-sdnl.c +++ b/src/libsystemd/sd-netlink/netlink-types-sdnl.c @@ -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);