selftests/net: fix bugs in address and port initialization
authorSowmini Varadhan <sowmini.varadhan@oracle.com>
Mon, 25 Dec 2017 22:43:04 +0000 (14:43 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 12 Apr 2018 10:32:13 +0000 (12:32 +0200)
[ Upstream commit d36f45e5b46723cf2d4147173e18c52d4143176d ]

Address/port initialization should work correctly regardless
of the order in which command line arguments are supplied,
E.g, cfg_port should be used to connect to the remote host
even if it is processed after -D, src/dst address initialization
should not require that [-4|-6] be specified before
the -S or -D args, receiver should be able to bind to *.<cfg_port>

Achieve this by making sure that the address/port structures
are initialized after all command line options are parsed.

Store cfg_port in host-byte order, and use htons()
to set up the sin_port/sin6_port before bind/connect,
so that the network system calls get the correct values
in network-byte order.

Signed-off-by: Sowmini Varadhan <sowmini.varadhan@oracle.com>
Acked-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
tools/testing/selftests/net/msg_zerocopy.c

index 3ab6ec4039059cf127345652bccf6c34d5c4d273..e11fe84de0fd92f9123b9bb75c0745123ad43546 100644 (file)
@@ -259,22 +259,28 @@ static int setup_ip6h(struct ipv6hdr *ip6h, uint16_t payload_len)
        return sizeof(*ip6h);
 }
 
-static void setup_sockaddr(int domain, const char *str_addr, void *sockaddr)
+
+static void setup_sockaddr(int domain, const char *str_addr,
+                          struct sockaddr_storage *sockaddr)
 {
        struct sockaddr_in6 *addr6 = (void *) sockaddr;
        struct sockaddr_in *addr4 = (void *) sockaddr;
 
        switch (domain) {
        case PF_INET:
+               memset(addr4, 0, sizeof(*addr4));
                addr4->sin_family = AF_INET;
                addr4->sin_port = htons(cfg_port);
-               if (inet_pton(AF_INET, str_addr, &(addr4->sin_addr)) != 1)
+               if (str_addr &&
+                   inet_pton(AF_INET, str_addr, &(addr4->sin_addr)) != 1)
                        error(1, 0, "ipv4 parse error: %s", str_addr);
                break;
        case PF_INET6:
+               memset(addr6, 0, sizeof(*addr6));
                addr6->sin6_family = AF_INET6;
                addr6->sin6_port = htons(cfg_port);
-               if (inet_pton(AF_INET6, str_addr, &(addr6->sin6_addr)) != 1)
+               if (str_addr &&
+                   inet_pton(AF_INET6, str_addr, &(addr6->sin6_addr)) != 1)
                        error(1, 0, "ipv6 parse error: %s", str_addr);
                break;
        default:
@@ -603,6 +609,7 @@ static void parse_opts(int argc, char **argv)
                                    sizeof(struct tcphdr) -
                                    40 /* max tcp options */;
        int c;
+       char *daddr = NULL, *saddr = NULL;
 
        cfg_payload_len = max_payload_len;
 
@@ -627,7 +634,7 @@ static void parse_opts(int argc, char **argv)
                        cfg_cpu = strtol(optarg, NULL, 0);
                        break;
                case 'D':
-                       setup_sockaddr(cfg_family, optarg, &cfg_dst_addr);
+                       daddr = optarg;
                        break;
                case 'i':
                        cfg_ifindex = if_nametoindex(optarg);
@@ -638,7 +645,7 @@ static void parse_opts(int argc, char **argv)
                        cfg_cork_mixed = true;
                        break;
                case 'p':
-                       cfg_port = htons(strtoul(optarg, NULL, 0));
+                       cfg_port = strtoul(optarg, NULL, 0);
                        break;
                case 'r':
                        cfg_rx = true;
@@ -647,7 +654,7 @@ static void parse_opts(int argc, char **argv)
                        cfg_payload_len = strtoul(optarg, NULL, 0);
                        break;
                case 'S':
-                       setup_sockaddr(cfg_family, optarg, &cfg_src_addr);
+                       saddr = optarg;
                        break;
                case 't':
                        cfg_runtime_ms = 200 + strtoul(optarg, NULL, 10) * 1000;
@@ -660,6 +667,8 @@ static void parse_opts(int argc, char **argv)
                        break;
                }
        }
+       setup_sockaddr(cfg_family, daddr, &cfg_dst_addr);
+       setup_sockaddr(cfg_family, saddr, &cfg_src_addr);
 
        if (cfg_payload_len > max_payload_len)
                error(1, 0, "-s: payload exceeds max (%d)", max_payload_len);