sd-netlink: add minimal support for sock_diag netlink sockets
This is just enough of the type info to determine AF_UNIX queue lengths information.
This commit is contained in:
@@ -109,10 +109,12 @@ sd_netlink_sources = files(
|
||||
'sd-netlink/netlink-message-rtnl.c',
|
||||
'sd-netlink/netlink-message.c',
|
||||
'sd-netlink/netlink-slot.c',
|
||||
'sd-netlink/netlink-sock-diag.c',
|
||||
'sd-netlink/netlink-socket.c',
|
||||
'sd-netlink/netlink-types-genl.c',
|
||||
'sd-netlink/netlink-types-nfnl.c',
|
||||
'sd-netlink/netlink-types-rtnl.c',
|
||||
'sd-netlink/netlink-types-sdnl.c',
|
||||
'sd-netlink/netlink-types.c',
|
||||
'sd-netlink/netlink-util.c',
|
||||
'sd-netlink/sd-netlink.c',
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <linux/sock_diag.h>
|
||||
#include <linux/unix_diag.h>
|
||||
|
||||
#include "netlink-internal.h"
|
||||
#include "netlink-sock-diag.h"
|
||||
#include "netlink-util.h"
|
||||
|
||||
int sd_sock_diag_socket_open(sd_netlink **ret) {
|
||||
return netlink_open_family(ret, NETLINK_SOCK_DIAG);
|
||||
}
|
||||
|
||||
int sd_sock_diag_message_new_unix(
|
||||
sd_netlink *sdnl,
|
||||
sd_netlink_message **ret,
|
||||
ino_t inode,
|
||||
uint64_t cookie,
|
||||
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_ACK);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*(struct unix_diag_req*) NLMSG_DATA(m->hdr) = (struct unix_diag_req) {
|
||||
.sdiag_family = AF_UNIX,
|
||||
.udiag_ino = inode,
|
||||
.udiag_show = show,
|
||||
.udiag_cookie = {
|
||||
cookie & UINT32_MAX,
|
||||
(cookie >> 32) & UINT32_MAX,
|
||||
},
|
||||
};
|
||||
|
||||
*ret = TAKE_PTR(m);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "sd-netlink.h"
|
||||
|
||||
/* TODO: to be exported later */
|
||||
|
||||
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);
|
||||
@@ -0,0 +1,37 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <linux/sock_diag.h>
|
||||
#include <linux/unix_diag.h>
|
||||
|
||||
#include "missing_network.h"
|
||||
#include "netlink-types-internal.h"
|
||||
#include "netlink-types.h"
|
||||
|
||||
static const NLAPolicy unix_diag_req_policies[] = {
|
||||
};
|
||||
DEFINE_POLICY_SET(unix_diag_req);
|
||||
|
||||
static const NLAPolicy sdnl_req_policies[] = {
|
||||
[SOCK_DIAG_BY_FAMILY] = BUILD_POLICY_NESTED_WITH_SIZE(unix_diag_req, sizeof(struct unix_diag_req)),
|
||||
};
|
||||
|
||||
DEFINE_POLICY_SET(sdnl_req);
|
||||
|
||||
static const NLAPolicy unix_diag_msg_policies[] = {
|
||||
[UNIX_DIAG_RQLEN] = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct unix_diag_rqlen)),
|
||||
};
|
||||
DEFINE_POLICY_SET(unix_diag_msg);
|
||||
|
||||
static const NLAPolicy sdnl_msg_policies[] = {
|
||||
[SOCK_DIAG_BY_FAMILY] = BUILD_POLICY_NESTED_WITH_SIZE(unix_diag_msg, sizeof(struct unix_diag_msg)),
|
||||
};
|
||||
|
||||
DEFINE_POLICY_SET(sdnl_msg);
|
||||
|
||||
const NLAPolicy *sdnl_get_policy(uint16_t nlmsg_type, uint16_t flags) {
|
||||
/* for sock_diag we need to look at whether a message is a response or request to determine how to decode it. */
|
||||
if (flags & NLM_F_REQUEST)
|
||||
return policy_set_get_policy(&sdnl_req_policy_set, nlmsg_type);
|
||||
|
||||
return policy_set_get_policy(&sdnl_msg_policy_set, nlmsg_type);
|
||||
}
|
||||
@@ -71,6 +71,9 @@ int netlink_get_policy_set_and_header_size(
|
||||
break;
|
||||
case NETLINK_GENERIC:
|
||||
return genl_get_policy_set_and_header_size(nl, type, ret_policy_set, ret_header_size);
|
||||
case NETLINK_SOCK_DIAG:
|
||||
policy = sdnl_get_policy(type, flags);
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ typedef struct NLAPolicySetUnion NLAPolicySetUnion;
|
||||
|
||||
const NLAPolicy *rtnl_get_policy(uint16_t nlmsg_type);
|
||||
const NLAPolicy *nfnl_get_policy(uint16_t nlmsg_type);
|
||||
const NLAPolicy *sdnl_get_policy(uint16_t nlmsg_type, uint16_t nlmsg_flags);
|
||||
const NLAPolicySet *genl_get_policy_set_by_name(const char *name);
|
||||
int genl_get_policy_set_and_header_size(
|
||||
sd_netlink *nl,
|
||||
|
||||
@@ -5,18 +5,22 @@
|
||||
#include <linux/if_macsec.h>
|
||||
#include <linux/l2tp.h>
|
||||
#include <linux/nl80211.h>
|
||||
#include <linux/unix_diag.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/ether.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "sd-netlink.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "ether-addr-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "macro.h"
|
||||
#include "netlink-genl.h"
|
||||
#include "netlink-internal.h"
|
||||
#include "netlink-sock-diag.h"
|
||||
#include "netlink-util.h"
|
||||
#include "socket-util.h"
|
||||
#include "stdio-util.h"
|
||||
@@ -699,4 +703,28 @@ TEST(rtnl_set_link_name) {
|
||||
ASSERT_NULL(resolved = mfree(resolved));
|
||||
}
|
||||
|
||||
TEST(sock_diag_unix) {
|
||||
_cleanup_(sd_netlink_unrefp) sd_netlink *nl = NULL;
|
||||
|
||||
ASSERT_OK(sd_sock_diag_socket_open(&nl));
|
||||
|
||||
_cleanup_close_ int unix_fd = ASSERT_FD(socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0));
|
||||
ASSERT_OK(socket_autobind(unix_fd, /* ret_name= */ NULL));
|
||||
ASSERT_OK_ERRNO(listen(unix_fd, 123));
|
||||
|
||||
struct stat st;
|
||||
ASSERT_OK_ERRNO(fstat(unix_fd, &st));
|
||||
|
||||
uint64_t cookie;
|
||||
socklen_t cookie_len = sizeof(cookie);
|
||||
ASSERT_OK_ERRNO(getsockopt(unix_fd, SOL_SOCKET, SO_COOKIE, &cookie, &cookie_len));
|
||||
ASSERT_EQ(cookie_len, sizeof(cookie));
|
||||
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
|
||||
ASSERT_OK(sd_sock_diag_message_new_unix(nl, &message, st.st_ino, cookie, UDIAG_SHOW_RQLEN));
|
||||
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *reply = NULL;
|
||||
ASSERT_OK(sd_netlink_call(nl, message, /* usec= */ 0, &reply));
|
||||
}
|
||||
|
||||
DEFINE_TEST_MAIN(LOG_DEBUG);
|
||||
|
||||
Reference in New Issue
Block a user