]> granicus.if.org Git - strace/commitdiff
tests: check [gs]etsockopt SOL_NETLINK decoding
authorDmitry V. Levin <ldv@altlinux.org>
Thu, 16 Nov 2017 00:12:46 +0000 (00:12 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Thu, 16 Nov 2017 00:12:46 +0000 (00:12 +0000)
* 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.

tests/.gitignore
tests/gen_tests.in
tests/pure_executables.list
tests/sockopt-sol_netlink.c [new file with mode: 0644]

index dc9293029f00f31a24cdf6a4aec2dbbd5b88bc88..93c980fa90d5d25b7b78d7d323d9db7a4e541bb1 100644 (file)
@@ -410,6 +410,7 @@ so_linger
 so_peercred
 sock_filter-v
 socketcall
+sockopt-sol_netlink
 splice
 stack-fcall
 stat
index 091bbe594b84aa80c5a9765c0d9c5341c17ee8ff..8dff19fdf88e251f9d8a4c601f6d0de7e9e22b8b 100644 (file)
@@ -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
index d98b17db1fc693909938b7183fcfe35b8826c047..7ab52efe00bf79b618fbbc046b2df78053fb2677 100755 (executable)
@@ -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 (file)
index 0000000..b17f933
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * Check decoding of getsockopt and setsockopt for SOL_NETLINK level.
+ *
+ * Copyright (c) 2017 Dmitry V. Levin <ldv@altlinux.org>
+ * 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 <stdio.h>
+
+#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;
+}