From: Dmitry V. Levin Date: Thu, 16 Nov 2017 00:12:46 +0000 (+0000) Subject: tests: check [gs]etsockopt SOL_NETLINK decoding X-Git-Tag: v4.21~313 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8d481bf4c21e61a827658a10e1120f1c59b92e89;p=strace tests: check [gs]etsockopt SOL_NETLINK decoding * tests/sockopt-sol_netlink.c: New file. * tests/gen_tests.in (sockopt-sol_netlink): New entry. * tests/pure_executables.list: Add sockopt-sol_netlink. * tests/.gitignore: Likewise. --- diff --git a/tests/.gitignore b/tests/.gitignore index dc929302..93c980fa 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -410,6 +410,7 @@ so_linger so_peercred sock_filter-v socketcall +sockopt-sol_netlink splice stack-fcall stat diff --git a/tests/gen_tests.in b/tests/gen_tests.in index 091bbe59..8dff19fd 100644 --- a/tests/gen_tests.in +++ b/tests/gen_tests.in @@ -352,6 +352,7 @@ so_linger -e trace=getsockopt,setsockopt so_peercred -e trace=getsockopt sock_filter-v -v -e trace=getsockopt,setsockopt socketcall -a20 +sockopt-sol_netlink -e trace=getsockopt,setsockopt splice stat -a32 -v -P stat.sample -P /dev/full stat64 -a32 -v -P stat.sample -P /dev/full diff --git a/tests/pure_executables.list b/tests/pure_executables.list index d98b17db..7ab52efe 100755 --- a/tests/pure_executables.list +++ b/tests/pure_executables.list @@ -341,6 +341,7 @@ so_linger so_peercred sock_filter-v socketcall +sockopt-sol_netlink splice stat stat64 diff --git a/tests/sockopt-sol_netlink.c b/tests/sockopt-sol_netlink.c new file mode 100644 index 00000000..b17f9333 --- /dev/null +++ b/tests/sockopt-sol_netlink.c @@ -0,0 +1,190 @@ +/* + * Check decoding of getsockopt and setsockopt for SOL_NETLINK level. + * + * Copyright (c) 2017 Dmitry V. Levin + * 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 "netlink.h" +#include + +#ifndef SOL_NETLINK +# define SOL_NETLINK 270 +#endif + +static int rc; +static const char *errstr; + +static int +get_sockopt(int fd, int name, void *val, socklen_t *len) +{ + rc = getsockopt(fd, SOL_NETLINK, name, val, len); + errstr = sprintrc(rc); + return rc; +} + +static int +set_sockopt(int fd, int name, void *val, socklen_t len) +{ + rc = setsockopt(fd, SOL_NETLINK, name, val, len); + errstr = sprintrc(rc); + return rc; +} + +int +main(void) +{ + static const struct { + int val; + const char *str; + } names[] = { +#ifdef NETLINK_ADD_MEMBERSHIP + { ARG_STR(NETLINK_ADD_MEMBERSHIP) }, +#endif +#ifdef NETLINK_DROP_MEMBERSHIP + { ARG_STR(NETLINK_DROP_MEMBERSHIP) }, +#endif +#ifdef NETLINK_PKTINFO + { ARG_STR(NETLINK_PKTINFO) }, +#endif +#ifdef NETLINK_BROADCAST_ERROR + { ARG_STR(NETLINK_BROADCAST_ERROR) }, +#endif +#ifdef NETLINK_NO_ENOBUFS + { ARG_STR(NETLINK_NO_ENOBUFS) }, +#endif +#ifdef NETLINK_RX_RING + { ARG_STR(NETLINK_RX_RING) }, +#endif +#ifdef NETLINK_TX_RING + { ARG_STR(NETLINK_TX_RING) }, +#endif +#ifdef NETLINK_LISTEN_ALL_NSID + { ARG_STR(NETLINK_LISTEN_ALL_NSID) }, +#endif +#ifdef NETLINK_CAP_ACK + { ARG_STR(NETLINK_CAP_ACK) }, +#endif +#ifdef NETLINK_EXT_ACK + { ARG_STR(NETLINK_EXT_ACK) }, +#endif + }; + + TAIL_ALLOC_OBJECT_CONST_PTR(int, val); + TAIL_ALLOC_OBJECT_CONST_PTR(socklen_t, len); + void *const efault = val + 1; + int fd = socket(AF_NETLINK, SOCK_RAW, 0); + if (fd < 0) + perror_msg_and_skip("socket AF_NETLINK SOCK_RAW"); + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(names); ++i) { + /* getsockopt */ + + /* classic */ + *len = sizeof(*val); + get_sockopt(fd, names[i].val, val, len); + printf("getsockopt(%d, SOL_NETLINK, %s, ", fd, names[i].str); + if (rc) + printf("%p", val); + else + printf("[%d]", *val); + printf(", [%d]) = %s\n", *len, errstr); + + /* optlen larger than necessary - shortened */ + *len = sizeof(*val) + 1; + get_sockopt(fd, names[i].val, val, len); + printf("getsockopt(%d, SOL_NETLINK, %s, ", fd, names[i].str); + if (rc) + printf("%p", val); + else + printf("[%d]", *val); + printf(", [%d", (int) sizeof(*val) + 1); + if ((int) sizeof(*val) + 1 != *len) + printf("->%d", *len); + printf("]) = %s\n", errstr); + + /* zero optlen - print returned optlen */ + *len = 0; + get_sockopt(fd, names[i].val, NULL, len); + printf("getsockopt(%d, SOL_NETLINK, %s, NULL, [0", + fd, names[i].str); + if (*len) + printf("->%d", *len); + printf("]) = %s\n", errstr); + + /* optlen shorter than necessary - print address */ + *len = sizeof(*val) - 1; + get_sockopt(fd, names[i].val, val, len); + printf("getsockopt(%d, SOL_NETLINK, %s, %p, [%d", + fd, names[i].str, val, (int) sizeof(*val) - 1); + if ((int) sizeof(*val) - 1 != *len) + printf("->%d", *len); + printf("]) = %s\n", errstr); + + /* optval EFAULT - print address */ + *len = sizeof(*val); + get_sockopt(fd, names[i].val, efault, len); + printf("getsockopt(%d, SOL_NETLINK, %s, %p, [%d]) = %s\n", + fd, names[i].str, efault, *len, errstr); + + /* optlen EFAULT - print address */ + get_sockopt(fd, names[i].val, val, len + 1); + printf("getsockopt(%d, SOL_NETLINK, %s, %p, %p) = %s\n", + fd, names[i].str, val, len + 1, errstr); + + /* setsockopt */ + + /* classic */ + *val = 0xdefaced; + set_sockopt(fd, names[i].val, val, sizeof(*val)); + printf("setsockopt(%d, SOL_NETLINK, %s, [%d], %d) = %s\n", + fd, names[i].str, *val, (int) sizeof(*val), errstr); + + /* optlen larger than necessary - shortened */ + set_sockopt(fd, names[i].val, val, sizeof(*val) + 1); + printf("setsockopt(%d, SOL_NETLINK, %s, [%d], %d) = %s\n", + fd, names[i].str, *val, (int) sizeof(*val) + 1, errstr); + + /* optlen < 0 - print address */ + set_sockopt(fd, names[i].val, val, -1U); + printf("setsockopt(%d, SOL_NETLINK, %s, %p, -1) = %s\n", + fd, names[i].str, val, errstr); + + /* optlen smaller than necessary - print address */ + set_sockopt(fd, names[i].val, val, sizeof(*val) - 1); + printf("setsockopt(%d, SOL_NETLINK, %s, %p, %d) = %s\n", + fd, names[i].str, val, (int) sizeof(*val) - 1, errstr); + + /* optval EFAULT - print address */ + set_sockopt(fd, names[i].val, efault, sizeof(*val)); + printf("setsockopt(%d, SOL_NETLINK, %s, %p, %d) = %s\n", + fd, names[i].str, efault, (int) sizeof(*val), errstr); + } + + puts("+++ exited with 0 +++"); + return 0; +}