sd-netlink: beef up sock-diag code a bit

Let's make it useful to enumerate AF_UNIX sockets.
This commit is contained in:
Lennart Poettering
2026-06-23 23:10:01 +02:00
parent ce72c94acc
commit daae289f10
4 changed files with 53 additions and 0 deletions
+1
View 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. */
@@ -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;
}
@@ -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);
@@ -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);