]> granicus.if.org Git - strace/commitdiff
tests: check ioctl(SIOCGIFCONF) decoding
authorEugene Syromyatnikov <evgsyr@gmail.com>
Sat, 24 Dec 2016 16:18:51 +0000 (19:18 +0300)
committerDmitry V. Levin <ldv@altlinux.org>
Wed, 4 Jan 2017 11:48:11 +0000 (11:48 +0000)
* tests/ioctl_sock_gifconf.c: New file.
* tests/ioctl_sock_gifconf.test: New test.
* tests/.gitignore: Add ioctl_sock_gifconf.
* tests/Makefile.am (check_PROGRAMS): Likewise.
(DECODER_TESTS): Add ioctl_sock_gifconf.test.

tests/.gitignore
tests/Makefile.am
tests/ioctl_sock_gifconf.c [new file with mode: 0644]
tests/ioctl_sock_gifconf.test [new file with mode: 0755]

index 1ede2c41b0262525a9627a51fcd0daa324d605ae..a0a400a5d2230b1c5d2a7c3328b403784de5e886 100644 (file)
@@ -121,6 +121,7 @@ ioctl_evdev-v
 ioctl_mtd
 ioctl_rtc
 ioctl_rtc-v
+ioctl_sock_gifconf
 ioctl_uffdio
 ioctl_v4l2
 ioperm
index bd8f3d54abfc54ba265ffbe9997c7a1c9de5ac03..d9dd1c9892a0c07cf60df1b7e06123592fb9bfd3 100644 (file)
@@ -182,6 +182,7 @@ check_PROGRAMS = \
        ioctl_mtd \
        ioctl_rtc \
        ioctl_rtc-v \
+       ioctl_sock_gifconf \
        ioctl_uffdio \
        ioctl_v4l2 \
        ioperm \
@@ -577,6 +578,7 @@ DECODER_TESTS = \
        ioctl_mtd.test \
        ioctl_rtc.test \
        ioctl_rtc-v.test \
+       ioctl_sock_gifconf.test \
        ioctl_uffdio.test \
        ioctl_v4l2.test \
        ioperm.test \
diff --git a/tests/ioctl_sock_gifconf.c b/tests/ioctl_sock_gifconf.c
new file mode 100644 (file)
index 0000000..ae0bea4
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * Check decoding of SIOCGIFCONF command of ioctl syscall.
+ *
+ * Copyright (c) 2016 Eugene Syromyatnikov <evgsyr@gmail.com>
+ * 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 <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+#define MAX_STRLEN 1
+
+static void
+print_ifc_len(int val)
+{
+       if (val % (int) sizeof(struct ifreq))
+               printf("%d", val);
+       else
+               printf("%d * sizeof(struct ifreq)",
+                      val / (int) sizeof(struct ifreq));
+}
+
+static void
+print_ifconf(struct ifconf *ifc, int in_len, char *in_buf, long rc)
+{
+       if (in_buf) {
+               printf("{ifc_len=");
+               print_ifc_len(in_len);
+
+               if (in_len != ifc->ifc_len) {
+                       printf(" => ");
+                       print_ifc_len(ifc->ifc_len);
+               }
+       } else {
+               printf("{ifc_len=");
+               print_ifc_len(ifc->ifc_len);
+       }
+
+       printf(", ifc_buf=");
+
+       if ((rc < 0) || !in_buf) {
+               if (in_buf)
+                       printf("%p", in_buf);
+               else
+                       printf("NULL");
+       } else {
+               int i;
+
+               printf("[");
+               for (i = 0; i < (ifc->ifc_len) &&
+                   i < (int) (MAX_STRLEN * sizeof(struct ifreq));
+                   i += sizeof(struct ifreq)) {
+                       struct ifreq *ifr = (struct ifreq *) (ifc->ifc_buf + i);
+                       struct sockaddr_in *const sa_in =
+                               (struct sockaddr_in *) &(ifr->ifr_addr);
+
+                       if (i)
+                               printf(", ");
+                       printf("{ifr_name=\"%s\", ifr_addr={sa_family=AF_INET, "
+                              "sin_port=htons(%u), sin_addr=inet_addr(\"%s\")}"
+                              "}", ifr->ifr_name, ntohs(sa_in->sin_port),
+                              inet_ntoa(sa_in->sin_addr));
+               }
+
+               if ((size_t) (ifc->ifc_len - i) >= sizeof(struct ifreq))
+                       printf(", ...");
+
+               printf("]");
+       }
+
+       printf("}");
+}
+
+static void
+gifconf_ioctl(int fd, struct ifconf *ifc, bool ifc_valid)
+{
+       const char * errstr;
+       int in_len;
+       char *in_buf;
+       long rc;
+
+       if (ifc_valid) {
+               in_len = ifc->ifc_len;
+               in_buf = ifc->ifc_buf;
+       }
+
+       rc = ioctl(fd, SIOCGIFCONF, ifc);
+       errstr = sprintrc(rc);
+
+       printf("ioctl(%d, SIOCGIFCONF, ", fd);
+       if (ifc_valid) {
+               print_ifconf(ifc, in_len, in_buf, rc);
+       } else {
+               if (ifc)
+                       printf("%p", ifc);
+               else
+                       printf("NULL");
+       }
+
+       printf(") = %s\n", errstr);
+}
+
+int
+main(int argc, char *argv[])
+{
+       struct ifreq *ifr = tail_alloc(2 * sizeof(*ifr));
+       struct ifconf *ifc = tail_alloc(sizeof(*ifc));
+
+       struct sockaddr_in addr;
+       int fd;
+
+       memset(&addr, 0, sizeof(addr));
+       addr.sin_family = AF_INET;
+       addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+       if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+               perror_msg_and_skip("socket AF_INET");
+
+       gifconf_ioctl(fd, NULL, false);
+       gifconf_ioctl(fd, ifc + 1, false);
+
+       ifc->ifc_len = 3141592653U;
+       ifc->ifc_buf = NULL;
+       gifconf_ioctl(fd, ifc, true);
+
+       ifc->ifc_len = 0;
+       ifc->ifc_buf = (char *) (ifr + 2);
+       gifconf_ioctl(fd, ifc, true);
+
+       ifc->ifc_len = 1;
+       ifc->ifc_buf = (char *) (ifr + 1);
+       gifconf_ioctl(fd, ifc, true);
+
+       ifc->ifc_len = 1 * sizeof(*ifr);
+       ifc->ifc_buf = (char *) (ifr + 1);
+       gifconf_ioctl(fd, ifc, true);
+
+       ifc->ifc_len = 2 * sizeof(*ifr);
+       ifc->ifc_buf = (char *) (ifr + 1);
+       gifconf_ioctl(fd, ifc, true);
+
+       ifc->ifc_len = 2 * sizeof(*ifr) + 2;
+       ifc->ifc_buf = (char *) ifr;
+       gifconf_ioctl(fd, ifc, true);
+
+       ifc->ifc_len = 3 * sizeof(*ifr) + 4;
+       ifc->ifc_buf = (char *) ifr;
+       gifconf_ioctl(fd, ifc, true);
+
+       puts("+++ exited with 0 +++");
+       return 0;
+}
diff --git a/tests/ioctl_sock_gifconf.test b/tests/ioctl_sock_gifconf.test
new file mode 100755 (executable)
index 0000000..2e2fc01
--- /dev/null
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+# Check decoding of SIOCGIFCONF ioctl.
+
+. "${srcdir=.}/init.sh"
+
+run_prog > /dev/null
+run_strace -a28 -s1 -eioctl $args > "$EXP"
+check_prog grep
+grep -v '^ioctl([012],' < "$LOG" > "$OUT"
+match_diff "$OUT" "$EXP"
+rm -f "$EXP" "$OUT"