[PATCH] tests: add check for nlmsg_type decoding
Dmitry V. Levin
ldv at altlinux.org
Sun Jun 4 11:06:12 UTC 2017
On Sat, May 20, 2017 at 05:39:32PM +0800, JingPiao Chen wrote:
> * tests/netlink_protocol.c: Add check for nlmsg_type decoding.
> ---
> tests/netlink_protocol.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 95 insertions(+)
>
> diff --git a/tests/netlink_protocol.c b/tests/netlink_protocol.c
> index 121c83d..8461c52 100644
> --- a/tests/netlink_protocol.c
> +++ b/tests/netlink_protocol.c
> @@ -38,9 +38,15 @@
> # include <unistd.h>
> # include <sys/xattr.h>
> # include <netinet/in.h>
> +# include <linux/audit.h>
> +# include <linux/inet_diag.h>
> +# include <linux/netfilter/nfnetlink.h>
> # include <linux/netlink.h>
> +# include <linux/rtnetlink.h>
> +# include <linux/selinux_netlink.h>
> # include <linux/sock_diag.h>
> # include <linux/netlink_diag.h>
> +# include <linux/xfrm.h>
I'm not sure whether all these headers are available back to 2.6 kernels,
need to check this. The same question applies to the previous commit
"netlink: add type decoding" by Fabien Siron.
> # if !defined NETLINK_SOCK_DIAG && defined NETLINK_INET_DIAG
> # define NETLINK_SOCK_DIAG NETLINK_INET_DIAG
> @@ -350,6 +356,94 @@ test_nlmsg_done(const int fd)
> fd, nlh->nlmsg_len, nlh->nlmsg_len, total_len, sprintrc(rc));
> }
>
> +static int
> +create_socket(int proto, const char *name)
> +{
> + struct sockaddr_nl addr;
> + socklen_t len = sizeof(addr);
> + int fd;
> +
> + memset(&addr, 0, sizeof(addr));
> + addr.nl_family = AF_NETLINK;
> +
> + if ((fd = socket(AF_NETLINK, SOCK_RAW, proto)) == -1)
> + perror_msg_and_skip("socket AF_NETLINK");
This perror_msg_and_skip means that if at least one protocol family
is not supported by the kernel, the whole test will be skipped.
> +
> + printf("socket(AF_NETLINK, SOCK_RAW, %s) = %d\n", name, fd);
> + if (bind(fd, (struct sockaddr *) &addr, len))
> + perror_msg_and_skip("bind");
> + printf("bind(%d, {sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}"
> + ", %u) = 0\n", fd, len);
> +
> + return fd;
> +}
> +
> +static void
> +test_nlmsg_type(void)
> +{
> + long rc;
> + int fd;
> + struct nlmsghdr nlh = {
> + .nlmsg_len = sizeof(nlh),
> + .nlmsg_flags = NLM_F_REQUEST,
> + .nlmsg_seq = 0,
> + .nlmsg_pid = 0
> + };
You don't have to explicitly initialize with zeroes, see send_query().
> + fd = create_socket(NETLINK_AUDIT, "NETLINK_AUDIT");
> + nlh.nlmsg_type = AUDIT_GET;
> + rc = sendto(fd, &nlh, sizeof(nlh), MSG_DONTWAIT, NULL, 0);
> + printf("sendto(%d, {{len=%u, type=AUDIT_GET, flags=NLM_F_REQUEST"
> + ", seq=0, pid=0}}, %u, MSG_DONTWAIT, NULL, 0) = %s\n",
> + fd, nlh.nlmsg_len, (unsigned) sizeof(nlh), sprintrc(rc));
> + close(fd);
> +
> + fd = create_socket(NETLINK_NETFILTER, "NETLINK_NETFILTER");
> + nlh.nlmsg_type = (NFNL_SUBSYS_NONE << 8) | NFNL_MSG_BATCH_BEGIN;
> + rc = sendto(fd, &nlh, sizeof(nlh), MSG_DONTWAIT, NULL, 0);
> + printf("sendto(%d, {{len=%u, type={NFNL_SUBSYS_NONE, %d}"
> + ", flags=NLM_F_REQUEST, seq=0, pid=0}}"
> + ", %u, MSG_DONTWAIT, NULL, 0) = %s\n",
> + fd, nlh.nlmsg_len, NFNL_MSG_BATCH_BEGIN,
> + (unsigned) sizeof(nlh), sprintrc(rc));
> + close(fd);
> +
> + fd = create_socket(NETLINK_ROUTE, "NETLINK_ROUTE");
> + nlh.nlmsg_type = RTM_NEWLINK;
> + rc = sendto(fd, &nlh, sizeof(nlh), MSG_DONTWAIT, NULL, 0);
> + printf("sendto(%d, {{len=%u, type=RTM_NEWLINK, flags=NLM_F_REQUEST"
> + ", seq=0, pid=0}}, %u, MSG_DONTWAIT, NULL, 0) = %s\n",
> + fd, nlh.nlmsg_len, (unsigned) sizeof(nlh), sprintrc(rc));
> + close(fd);
> +
> + fd = create_socket(NETLINK_SELINUX, "NETLINK_SELINUX");
> + nlh.nlmsg_type = SELNL_MSG_SETENFORCE;
> + rc = sendto(fd, &nlh, sizeof(nlh), MSG_DONTWAIT, NULL, 0);
> + printf("sendto(%d, {{len=%u, type=SELNL_MSG_SETENFORCE"
> + ", flags=NLM_F_REQUEST, seq=0, pid=0}}"
> + ", %u, MSG_DONTWAIT, NULL, 0) = %s\n",
> + fd, nlh.nlmsg_len, (unsigned) sizeof(nlh), sprintrc(rc));
> + close(fd);
> +
> + fd = create_socket(NETLINK_SOCK_DIAG, "NETLINK_SOCK_DIAG");
> + nlh.nlmsg_type = SOCK_DIAG_BY_FAMILY;
> + rc = sendto(fd, &nlh, sizeof(nlh), MSG_DONTWAIT, NULL, 0);
> + printf("sendto(%d, {{len=%u, type=SOCK_DIAG_BY_FAMILY"
> + ", flags=NLM_F_REQUEST, seq=0, pid=0}}"
> + ", %u, MSG_DONTWAIT, NULL, 0) = %s\n",
> + fd, nlh.nlmsg_len, (unsigned) sizeof(nlh), sprintrc(rc));
> + close(fd);
> +
> + fd = create_socket(NETLINK_XFRM, "NETLINK_XFRM");
> + nlh.nlmsg_type = XFRM_MSG_NEWSA;
> + rc = sendto(fd, &nlh, sizeof(nlh), MSG_DONTWAIT, NULL, 0);
> + printf("sendto(%d, {{len=%u, type=XFRM_MSG_NEWSA"
> + ", flags=NLM_F_REQUEST, seq=0, pid=0}}"
> + ", %u, MSG_DONTWAIT, NULL, 0) = %s\n",
> + fd, nlh.nlmsg_len, (unsigned) sizeof(nlh), sprintrc(rc));
> + close(fd);
All these protocol family specific nlmsg_type tests are unrelated
so they can be placed in separate tests.
I've run this test in different environments and found a common problem:
when netlink_diag kernel module is not loaded (e.g. OBS setups seem to
have this property), socket(AF_NETLINK, SOCK_RAW, NETLINK_SOCK_DIAG) call
in strace succeeds but subsequent requests end with NLMSG_ERROR and error
set to ENOENT. This situation is also detected by
tests/netlink_netlink_diag which is used by tests/net-yy-netlink.test
to skip the test when kernel is not capable.
In other words, testing of nlmsg_type decoding should not be done inside
generic tests like netlink_protocol. A separate test is needed, with
netlink_netlink_diag precheck like in tests/net-yy-netlink.test; even
better alternative is a separate test for each netlink protocol, these
tests could be extended further when more protocol specific decoding
is added later.
--
ldv
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.strace.io/pipermail/strace-devel/attachments/20170604/7745a4b5/attachment.bin>
More information about the Strace-devel
mailing list