net engine: fix potential buffer overrun in socket path
[fio.git] / engines / net.c
index 4ba4a5f80b82edea9e30566d7fc48e5b309a900a..3e26131be9a9913b853080b8ab85695aff60fb98 100644 (file)
@@ -94,18 +94,22 @@ static struct fio_option options[] = {
                            .oval = FIO_TYPE_TCP,
                            .help = "Transmission Control Protocol",
                          },
+#ifdef CONFIG_IPV6
                          { .ival = "tcpv6",
                            .oval = FIO_TYPE_TCP_V6,
                            .help = "Transmission Control Protocol V6",
                          },
+#endif
                          { .ival = "udp",
                            .oval = FIO_TYPE_UDP,
                            .help = "User Datagram Protocol",
                          },
+#ifdef CONFIG_IPV6
                          { .ival = "udpv6",
                            .oval = FIO_TYPE_UDP_V6,
                            .help = "User Datagram Protocol V6",
                          },
+#endif
                          { .ival = "unix",
                            .oval = FIO_TYPE_UNIX,
                            .help = "UNIX domain socket",
@@ -388,7 +392,7 @@ static int fio_netio_send(struct thread_data *td, struct io_u *io_u)
 
        do {
                if (is_udp(o)) {
-                       struct sockaddr *to;
+                       const struct sockaddr *to;
                        socklen_t len;
 
                        if (is_ipv6(o)) {
@@ -857,13 +861,17 @@ static int fio_fill_addr(struct thread_data *td, const char *host, int af,
                return 0;
 
        memset(&hints, 0, sizeof(hints));
-       hints.ai_family = AF_UNSPEC;
 
        if (is_tcp(o))
                hints.ai_socktype = SOCK_STREAM;
        else
                hints.ai_socktype = SOCK_DGRAM;
 
+       if (is_ipv6(o))
+               hints.ai_family = AF_INET6;
+       else
+               hints.ai_family = AF_INET;
+
        ret = getaddrinfo(host, NULL, &hints, res);
        if (ret) {
                int e = EINVAL;
@@ -905,10 +913,10 @@ static int fio_netio_setup_connect_inet(struct thread_data *td,
 
        if (is_ipv6(o)) {
                af = AF_INET6;
-               dst = &nd->addr6;
+               dst = &nd->addr6.sin6_addr;
        } else {
                af = AF_INET;
-               dst = &nd->addr;
+               dst = &nd->addr.sin_addr;
        }
 
        if (fio_fill_addr(td, host, af, dst, &res))
@@ -937,7 +945,8 @@ static int fio_netio_setup_connect_unix(struct thread_data *td,
        struct sockaddr_un *soun = &nd->addr_un;
 
        soun->sun_family = AF_UNIX;
-       strcpy(soun->sun_path, path);
+       memset(soun->sun_path, 0, sizeof(soun->sun_path));
+       strncpy(soun->sun_path, path, sizeof(soun->sun_path) - 1);
        return 0;
 }
 
@@ -968,7 +977,7 @@ static int fio_netio_setup_listen_unix(struct thread_data *td, const char *path)
 
        memset(addr, 0, sizeof(*addr));
        addr->sun_family = AF_UNIX;
-       strcpy(addr->sun_path, path);
+       strncpy(addr->sun_path, path, sizeof(addr->sun_path) - 1);
        unlink(path);
 
        len = sizeof(addr->sun_family) + strlen(path) + 1;
@@ -1035,12 +1044,17 @@ static int fio_netio_setup_listen_inet(struct thread_data *td, short port)
        }
 #endif
 
-       if (td->o.filename){
+       if (td->o.filename) {
                if (!is_udp(o) || !fio_netio_is_multicast(td->o.filename)) {
                        log_err("fio: hostname not valid for non-multicast inbound network IO\n");
                        close(fd);
                        return 1;
                }
+               if (is_ipv6(o)) {
+                       log_err("fio: IPv6 not supported for multicast network IO");
+                       close(fd);
+                       return 1;
+               }
 
                inet_aton(td->o.filename, &sin.sin_addr);
 
@@ -1054,6 +1068,7 @@ static int fio_netio_setup_listen_inet(struct thread_data *td, short port)
                } else {
                        mr.imr_interface.s_addr = htonl(INADDR_ANY);
                }
+
                if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char*)&mr, sizeof(mr)) < 0) {
                        td_verror(td, errno, "setsockopt IP_ADD_MEMBERSHIP");
                        close(fd);
@@ -1078,6 +1093,7 @@ static int fio_netio_setup_listen_inet(struct thread_data *td, short port)
        }
 
        if (bind(fd, saddr, len) < 0) {
+               close(fd);
                td_verror(td, errno, "bind");
                return 1;
        }
@@ -1180,8 +1196,9 @@ static int fio_netio_setup(struct thread_data *td)
        struct netio_data *nd;
 
        if (!td->files_index) {
-               add_file(td, td->o.filename ?: "net");
+               add_file(td, td->o.filename ?: "net", 0, 0);
                td->o.nr_files = td->o.nr_files ?: 1;
+               td->o.open_files++;
        }
 
        if (!td->io_ops->data) {