From: Fabien Siron Date: Sat, 21 May 2016 07:49:00 +0000 (+0000) Subject: tests: add check for netlink protocol decoding with -yy option X-Git-Tag: v4.12~113 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=28e955d747661fd0f437e70f41e477c9161467df;p=strace tests: add check for netlink protocol decoding with -yy option * tests/netlink_netlink_diag.c: New file. * tests/net-yy-netlink.c: New file. * tests/net-yy-netlink.test: New test. * tests/.gitignore: Add net-yy-netlink and netlink_netlink_diag * tests/Makefile.am (check_PROGRAMS): Likewise. (TESTS): Add net-yy-netlink.test. --- diff --git a/tests/.gitignore b/tests/.gitignore index 26c18ec9..826aadbb 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -133,8 +133,10 @@ net-accept-connect net-icmp_filter net-y-unix net-yy-inet +net-yy-netlink net-yy-unix netlink_inet_diag +netlink_netlink_diag netlink_unix_diag newfstatat nsyscalls diff --git a/tests/Makefile.am b/tests/Makefile.am index 64c1879a..4aaf7c4b 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -186,8 +186,10 @@ check_PROGRAMS = \ net-icmp_filter \ net-y-unix \ net-yy-inet \ + net-yy-netlink \ net-yy-unix \ netlink_inet_diag \ + netlink_netlink_diag \ netlink_unix_diag \ newfstatat \ nsyscalls \ @@ -471,6 +473,7 @@ DECODER_TESTS = \ net-icmp_filter.test \ net-y-unix.test \ net-yy-inet.test \ + net-yy-netlink.test \ net-yy-unix.test \ net.test \ newfstatat.test \ diff --git a/tests/net-yy-netlink.c b/tests/net-yy-netlink.c new file mode 100644 index 00000000..60770381 --- /dev/null +++ b/tests/net-yy-netlink.c @@ -0,0 +1,83 @@ +/* + * This file is part of net-yy-netlink strace test. + * + * Copyright (c) 2013-2016 Dmitry V. Levin + * Copyright (c) 2016 Fabien Siron + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "tests.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if !defined NETLINK_SOCK_DIAG && defined NETLINK_INET_DIAG +# define NETLINK_SOCK_DIAG NETLINK_INET_DIAG +#endif + +int +main(void) +{ + unsigned magic = 1234; + struct sockaddr_nl addr = { + .nl_family = AF_NETLINK, + .nl_pid = 1234 + }; + struct sockaddr *const sa = tail_memdup(&addr, sizeof(addr)); + socklen_t * const len = tail_alloc(sizeof(socklen_t)); + *len = sizeof(addr); + + const int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_SOCK_DIAG); + if (fd < 0) + perror_msg_and_skip("socket"); + const unsigned long inode = inode_of_sockfd(fd); + printf("socket(AF_NETLINK, SOCK_RAW, NETLINK_SOCK_DIAG) = " + "%d\n", fd, inode); + + if (bind(fd, sa, *len)) + perror_msg_and_skip("bind"); + printf("bind(%d, {sa_family=AF_NETLINK, pid=%u, " + "groups=00000000}, %u) = 0\n", fd, inode, magic, + (unsigned) *len); + + assert(recvmsg(fd, NULL, MSG_DONTWAIT) == -1); + printf("recvmsg(%d, NULL, MSG_DONTWAIT)" + " = -1 %s (%m)\n", fd, magic, errno2name()); + + assert(close(fd) == 0); + printf("close(%d) = 0\n", fd, magic); + + puts("+++ exited with 0 +++"); + return 0; +} diff --git a/tests/net-yy-netlink.test b/tests/net-yy-netlink.test new file mode 100755 index 00000000..a8ae8d2a --- /dev/null +++ b/tests/net-yy-netlink.test @@ -0,0 +1,50 @@ +#!/bin/sh +# +# Check decoding of protocol:portid pairs associated with socket +# descriptors +# +# Copyright (c) 2014 Masatake YAMATO +# Copyright (c) 2014-2016 Dmitry V. Levin +# Copyright (c) 2016 Fabien Siron +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +. "${srcdir=.}/init.sh" + +# strace -yy is implemented using /proc/self/fd +[ -d /proc/self/fd/ ] || + framework_skip_ '/proc/self/fd/ is not available' + +check_prog sed +run_prog ./netlink_netlink_diag + +addr="$NAME-local-stream" +run_prog "./$NAME" $addr > /dev/null + +run_strace -a22 -yy -eclose,network $args > "$EXP" +# Filter out close() calls made by ld.so and libc. +sed -n '/socket/,$p' < "$LOG" > "$OUT" + +match_diff "$OUT" "$EXP" +rm -f "$EXP" "$OUT" diff --git a/tests/netlink_netlink_diag.c b/tests/netlink_netlink_diag.c new file mode 100644 index 00000000..0afdb5d7 --- /dev/null +++ b/tests/netlink_netlink_diag.c @@ -0,0 +1,143 @@ +/* + * This file is part of net-yy-netlink strace test. + * + * Copyright (c) 2014-2016 Dmitry V. Levin + * Copyright (c) 2016 Fabien Siron + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "tests.h" +#include +#include +#include +#include +#include +#include +#include + +#if !defined NETLINK_SOCK_DIAG && defined NETLINK_INET_DIAG +# define NETLINK_SOCK_DIAG NETLINK_INET_DIAG +#endif + +static void +send_query(const int fd) +{ + struct sockaddr_nl nladdr = { + .nl_family = AF_NETLINK + }; + struct { + struct nlmsghdr nlh; + struct netlink_diag_req ndr; + } req = { + .nlh = { + .nlmsg_len = sizeof(req), + .nlmsg_type = SOCK_DIAG_BY_FAMILY, + .nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST + }, + .ndr = { + .sdiag_family = AF_NETLINK, + .sdiag_protocol = NDIAG_PROTO_ALL, + .ndiag_show = NDIAG_SHOW_MEMINFO + } + }; + struct iovec iov = { + .iov_base = &req, + .iov_len = sizeof(req) + }; + struct msghdr msg = { + .msg_name = (void *) &nladdr, + .msg_namelen = sizeof(nladdr), + .msg_iov = &iov, + .msg_iovlen = 1 + }; + + if (sendmsg(fd, &msg, 0) <= 0) + perror_msg_and_skip("sendmsg"); +} + +static void +check_responses(const int fd) +{ + static long buf[8192 / sizeof(long)]; + struct sockaddr_nl nladdr = { + .nl_family = AF_NETLINK + }; + struct iovec iov = { + .iov_base = buf, + .iov_len = sizeof(buf) + }; + struct msghdr msg = { + .msg_name = (void *) &nladdr, + .msg_namelen = sizeof(nladdr), + .msg_iov = &iov, + .msg_iovlen = 1 + }; + + ssize_t ret = recvmsg(fd, &msg, 0); + if (ret <= 0) + perror_msg_and_skip("recvmsg"); + + struct nlmsghdr *h = (struct nlmsghdr *) buf; + if (!NLMSG_OK(h, ret)) + error_msg_and_skip("!NLMSG_OK"); + if (h->nlmsg_type == NLMSG_ERROR) { + const struct nlmsgerr *err = NLMSG_DATA(h); + if (h->nlmsg_len < NLMSG_LENGTH(sizeof(*err))) + error_msg_and_skip("NLMSG_ERROR"); + errno = -err->error; + perror_msg_and_skip("NLMSG_ERROR"); + } + if (h->nlmsg_type != SOCK_DIAG_BY_FAMILY) + error_msg_and_skip("unexpected nlmsg_type %u", + (unsigned) h->nlmsg_type); + + const struct netlink_diag_msg *diag = NLMSG_DATA(h); + if (h->nlmsg_len < NLMSG_LENGTH(sizeof(*diag))) + error_msg_and_skip("short response"); +} + +int main(void) +{ + struct sockaddr_nl addr; + socklen_t len = sizeof(addr); + + memset(&addr, 0, sizeof(addr)); + addr.nl_family = AF_NETLINK; + + close(0); + close(1); + + if (socket(AF_NETLINK, SOCK_RAW, NETLINK_SOCK_DIAG)) + perror_msg_and_skip("socket AF_NETLINK"); + if (bind(0, (struct sockaddr *) &addr, len)) + perror_msg_and_skip("bind"); + + if (socket(AF_NETLINK, SOCK_RAW, NETLINK_SOCK_DIAG) != 1) + perror_msg_and_skip("socket AF_NETLINK"); + + send_query(1); + check_responses(1); + return 0; +}