From c2a24727c874ebd0721f4eb369443b1efb278fc8 Mon Sep 17 00:00:00 2001 From: Olivier Houchard Date: Tue, 8 Nov 2011 17:23:43 +0000 Subject: [PATCH] Add IPv6 support to netblast/netsend/netreceive PR: bin/161368 Submitted by: Olivier Cochard-Labbe --- tools/tools/netrate/netblast/netblast.c | 71 ++++++++++++------ tools/tools/netrate/netreceive/netreceive.c | 81 ++++++++++++++++----- tools/tools/netrate/netsend/netsend.c | 61 +++++++++++++--- 3 files changed, 161 insertions(+), 52 deletions(-) diff --git a/tools/tools/netrate/netblast/netblast.c b/tools/tools/netrate/netblast/netblast.c index f932fca08d72..bf1f3ae67604 100644 --- a/tools/tools/netrate/netblast/netblast.c +++ b/tools/tools/netrate/netblast/netblast.c @@ -32,13 +32,13 @@ #include #include - -#include +#include /* getaddrinfo */ #include #include #include #include +#include /* close */ static void usage(void) @@ -141,26 +141,25 @@ blast_loop(int s, long duration, u_char *packet, u_int packet_len) int main(int argc, char *argv[]) { - long payloadsize, port, duration; - struct sockaddr_in sin; + long payloadsize, duration; + struct addrinfo hints, *res, *res0; char *dummy, *packet; - int s; + int port, s, error; + const char *cause = NULL; if (argc != 5) usage(); - bzero(&sin, sizeof(sin)); - sin.sin_len = sizeof(sin); - sin.sin_family = AF_INET; - if (inet_aton(argv[1], &sin.sin_addr) == 0) { - perror(argv[1]); - return (-1); - } + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; port = strtoul(argv[2], &dummy, 10); - if (port < 1 || port > 65535 || *dummy != '\0') + if (port < 1 || port > 65535 || *dummy != '\0') { + fprintf(stderr, "Invalid port number: %s\n", argv[2]); usage(); - sin.sin_port = htons(port); + /*NOTREACHED*/ + } payloadsize = strtoul(argv[3], &dummy, 10); if (payloadsize < 0 || *dummy != '\0') @@ -168,29 +167,55 @@ main(int argc, char *argv[]) if (payloadsize > 32768) { fprintf(stderr, "payloadsize > 32768\n"); return (-1); + /*NOTREACHED*/ } duration = strtoul(argv[4], &dummy, 10); - if (duration < 0 || *dummy != '\0') + if (duration < 0 || *dummy != '\0') { + fprintf(stderr, "Invalid duration time: %s\n", argv[4]); usage(); + /*NOTREACHED*/ + } packet = malloc(payloadsize); if (packet == NULL) { perror("malloc"); return (-1); + /*NOTREACHED*/ } + bzero(packet, payloadsize); - - s = socket(PF_INET, SOCK_DGRAM, 0); - if (s == -1) { - perror("socket"); + error = getaddrinfo(argv[1],argv[2], &hints, &res0); + if (error) { + perror(gai_strerror(error)); return (-1); + /*NOTREACHED*/ + } + s = -1; + for (res = res0; res; res = res->ai_next) { + s = socket(res->ai_family, res->ai_socktype, 0); + if (s < 0) { + cause = "socket"; + continue; + } + + if (connect(s, res->ai_addr, res->ai_addrlen) < 0) { + cause = "connect"; + close(s); + s = -1; + continue; + } + + break; /* okay we got one */ + } + if (s < 0) { + perror(cause); + return (-1); + /*NOTREACHED*/ } - if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) { - perror("connect"); - return (-1); - } + freeaddrinfo(res0); return (blast_loop(s, duration, packet, payloadsize)); + } diff --git a/tools/tools/netrate/netreceive/netreceive.c b/tools/tools/netrate/netreceive/netreceive.c index 4a3a6f6c3ae8..b54ee7fcfbc0 100644 --- a/tools/tools/netrate/netreceive/netreceive.c +++ b/tools/tools/netrate/netreceive/netreceive.c @@ -29,14 +29,19 @@ #include #include #include +#include #include +#include /* getaddrinfo */ #include #include #include #include +#include /* close */ + +#define MAXSOCK 20 static void usage(void) @@ -49,23 +54,26 @@ usage(void) int main(int argc, char *argv[]) { - struct sockaddr_in sin; + struct addrinfo hints, *res, *res0; char *dummy, *packet; - long port; - int s, v; + int port; + int error, v, i; + const char *cause = NULL; + int s[MAXSOCK]; + struct pollfd fds[MAXSOCK]; + int nsock; if (argc != 2) usage(); - bzero(&sin, sizeof(sin)); - sin.sin_len = sizeof(sin); - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = htonl(INADDR_ANY); + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_flags = AI_PASSIVE; port = strtoul(argv[1], &dummy, 10); if (port < 1 || port > 65535 || *dummy != '\0') usage(); - sin.sin_port = htons(port); packet = malloc(65536); if (packet == NULL) { @@ -74,27 +82,60 @@ main(int argc, char *argv[]) } bzero(packet, 65536); - s = socket(PF_INET, SOCK_DGRAM, 0); - if (s == -1) { - perror("socket"); + error = getaddrinfo(NULL, argv[1], &hints, &res0); + if (error) { + perror(gai_strerror(error)); return (-1); + /*NOTREACHED*/ } - v = 128 * 1024; - if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &v, sizeof(v)) < 0) { - perror("SO_RCVBUF"); - return (-1); - } + nsock = 0; + for (res = res0; res && nsock < MAXSOCK; res = res->ai_next) { + s[nsock] = socket(res->ai_family, res->ai_socktype, + res->ai_protocol); + if (s[nsock] < 0) { + cause = "socket"; + continue; + } - if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) { - perror("bind"); + v = 128 * 1024; + if (setsockopt(s[nsock], SOL_SOCKET, SO_RCVBUF, &v, sizeof(v)) < 0) { + cause = "SO_RCVBUF"; + close(s[nsock]); + continue; + } + if (bind(s[nsock], res->ai_addr, res->ai_addrlen) < 0) { + cause = "bind"; + close(s[nsock]); + continue; + } + (void) listen(s[nsock], 5); + fds[nsock].fd = s[nsock]; + fds[nsock].events = POLLIN; + + nsock++; + } + if (nsock == 0) { + perror(cause); return (-1); + /*NOTREACHED*/ } printf("netreceive listening on UDP port %d\n", (u_short)port); while (1) { - if (recv(s, packet, 65536, 0) < 0) - perror("recv"); + if (poll(fds, nsock, -1) < 0) + perror("poll"); + for (i = 0; i > nsock; i++) { + if (fds[i].revents & POLLIN) { + if (recv(s[i], packet, 65536, 0) < 0) + perror("recv"); + } + if ((fds[i].revents &~ POLLIN) != 0) + perror("poll"); + } } + + /*NOTREACHED*/ + freeaddrinfo(res0); } diff --git a/tools/tools/netrate/netsend/netsend.c b/tools/tools/netrate/netsend/netsend.c index 49cd3436d379..f97594e96366 100644 --- a/tools/tools/netrate/netsend/netsend.c +++ b/tools/tools/netrate/netsend/netsend.c @@ -29,6 +29,7 @@ #include #include #include +#include /* if_nametoindex() */ #include #include @@ -40,13 +41,17 @@ #include #include +#include + /* program arguments */ struct _a { int s; + int ipv6; struct timespec interval; int port, port_max; long duration; struct sockaddr_in sin; + struct sockaddr_in6 sin6; int packet_len; void *packet; }; @@ -179,9 +184,16 @@ timing_loop(struct _a *a) ic = gettimeofday_cycles; cur_port = a->port; if (a->port == a->port_max) { - if (connect(a->s, (struct sockaddr *)&a->sin, sizeof(a->sin))) { - perror("connect"); - return (-1); + if (a->ipv6) { + if (connect(a->s, (struct sockaddr *)&a->sin6, sizeof(a->sin6))) { + perror("connect (ipv6)"); + return (-1); + } + } else { + if (connect(a->s, (struct sockaddr *)&a->sin, sizeof(a->sin))) { + perror("connect (ipv4)"); + return (-1); + } } } while (1) { @@ -215,8 +227,13 @@ timing_loop(struct _a *a) a->sin.sin_port = htons(cur_port++); if (cur_port > a->port_max) cur_port = a->port; + if (a->ipv6) { + ret = sendto(a->s, a->packet, a->packet_len, 0, + (struct sockaddr *)&a->sin6, sizeof(a->sin6)); + } else { ret = sendto(a->s, a->packet, a->packet_len, 0, (struct sockaddr *)&a->sin, sizeof(a->sin)); + } } if (ret < 0) send_errors++; @@ -254,25 +271,48 @@ main(int argc, char *argv[]) long rate, payloadsize, port; char *dummy; struct _a a; /* arguments */ + struct addrinfo hints, *res, *ressave; bzero(&a, sizeof(a)); if (argc != 6) usage(); - a.sin.sin_len = sizeof(a.sin); - a.sin.sin_family = AF_INET; - if (inet_aton(argv[1], &a.sin.sin_addr) == 0) { - perror(argv[1]); + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + + if (getaddrinfo(argv[1], NULL, &hints, &res) != 0) { + fprintf(stderr, "Couldn't resolv %s\n", argv[1]); return (-1); } + ressave = res; + while (res) { + if (res->ai_family == AF_INET) { + memcpy(&a.sin, res->ai_addr, res->ai_addrlen); + a.ipv6 = 0; + break; + } else if (res->ai_family == AF_INET6) { + memcpy(&a.sin6, res->ai_addr, res->ai_addrlen); + a.ipv6 = 1; + break; + } + res = res->ai_next; + } + if (!res) { + fprintf(stderr, "Couldn't resolv %s\n", argv[1]); + exit(1); + } + freeaddrinfo(ressave); port = strtoul(argv[2], &dummy, 10); if (port < 1 || port > 65535) usage(); if (*dummy != '\0' && *dummy != '-') usage(); - a.sin.sin_port = htons(port); + if (a.ipv6) + a.sin6.sin6_port = htons(port); + else + a.sin.sin_port = htons(port); a.port = a.port_max = port; if (*dummy == '-') { /* set high port */ port = strtoul(dummy + 1, &dummy, 10); @@ -328,7 +368,10 @@ main(int argc, char *argv[]) "seconds\n", payloadsize, (intmax_t)a.interval.tv_sec, a.interval.tv_nsec, a.duration); - a.s = socket(PF_INET, SOCK_DGRAM, 0); + if (a.ipv6) + a.s = socket(PF_INET6, SOCK_DGRAM, 0); + else + a.s = socket(PF_INET, SOCK_DGRAM, 0); if (a.s == -1) { perror("socket"); return (-1);