selftests: net: basic test for IPV6_2292*
authorJakub Kicinski <kuba@kernel.org>
Thu, 17 Feb 2022 01:21:20 +0000 (17:21 -0800)
committerDavid S. Miller <davem@davemloft.net>
Thu, 17 Feb 2022 14:22:09 +0000 (14:22 +0000)
Add a basic test to make sure ping sockets don't crash
with IPV6_2292* options.

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
tools/testing/selftests/net/cmsg_ipv6.sh
tools/testing/selftests/net/cmsg_sender.c

index e42c36e..2d89cb0 100755 (executable)
@@ -137,6 +137,15 @@ for ovr in setsock cmsg both diff; do
     done
 done
 
+# IPV6 exthdr
+for p in u i r; do
+    # Very basic "does it crash" test
+    for h in h d r; do
+       $NSEXE ./cmsg_sender -p $p -6 -H $h $TGT6 1234
+       check_result $? 0 "ExtHdr $prot $ovr - pass"
+    done
+done
+
 # Summary
 if [ $BAD -ne 0 ]; then
     echo "FAIL - $BAD/$TOTAL cases failed"
index 6136aa7..aed7845 100644 (file)
@@ -66,6 +66,7 @@ struct options {
                struct option_cmsg_u32 dontfrag;
                struct option_cmsg_u32 tclass;
                struct option_cmsg_u32 hlimit;
+               struct option_cmsg_u32 exthdr;
        } v6;
 } opt = {
        .size = 13,
@@ -99,6 +100,8 @@ static void __attribute__((noreturn)) cs_usage(const char *bin)
               "\t\t-C val  Set TCLASS via setsockopt\n"
               "\t\t-l val  Set HOPLIMIT via cmsg\n"
               "\t\t-L val  Set HOPLIMIT via setsockopt\n"
+              "\t\t-H type Add an IPv6 header option\n"
+              "\t\t        (h = HOP; d = DST; r = RTDST)"
               "");
        exit(ERN_HELP);
 }
@@ -107,7 +110,7 @@ static void cs_parse_args(int argc, char *argv[])
 {
        char o;
 
-       while ((o = getopt(argc, argv, "46sS:p:m:M:d:tf:F:c:C:l:L:")) != -1) {
+       while ((o = getopt(argc, argv, "46sS:p:m:M:d:tf:F:c:C:l:L:H:")) != -1) {
                switch (o) {
                case 's':
                        opt.silent_send = true;
@@ -169,6 +172,23 @@ static void cs_parse_args(int argc, char *argv[])
                case 'L':
                        opt.sockopt.hlimit = atoi(optarg);
                        break;
+               case 'H':
+                       opt.v6.exthdr.ena = true;
+                       switch (optarg[0]) {
+                       case 'h':
+                               opt.v6.exthdr.val = IPV6_HOPOPTS;
+                               break;
+                       case 'd':
+                               opt.v6.exthdr.val = IPV6_DSTOPTS;
+                               break;
+                       case 'r':
+                               opt.v6.exthdr.val = IPV6_RTHDRDSTOPTS;
+                               break;
+                       default:
+                               printf("Error: hdr type: %s\n", optarg);
+                               break;
+                       }
+                       break;
                }
        }
 
@@ -272,6 +292,17 @@ cs_write_cmsg(int fd, struct msghdr *msg, char *cbuf, size_t cbuf_sz)
                *(__u32 *)CMSG_DATA(cmsg) = SOF_TIMESTAMPING_TX_SCHED |
                                            SOF_TIMESTAMPING_TX_SOFTWARE;
        }
+       if (opt.v6.exthdr.ena) {
+               cmsg = (struct cmsghdr *)(cbuf + cmsg_len);
+               cmsg_len += CMSG_SPACE(8);
+               if (cbuf_sz < cmsg_len)
+                       error(ERN_CMSG_WR, EFAULT, "cmsg buffer too small");
+
+               cmsg->cmsg_level = SOL_IPV6;
+               cmsg->cmsg_type = opt.v6.exthdr.val;
+               cmsg->cmsg_len = CMSG_LEN(8);
+               *(__u64 *)CMSG_DATA(cmsg) = 0;
+       }
 
        if (cmsg_len)
                msg->msg_controllen = cmsg_len;