From 4addea850295d28afff630cb436000f0cb8988c0 Mon Sep 17 00:00:00 2001 From: "Bruce A. Mah" Date: Tue, 4 Feb 2014 15:05:39 -0800 Subject: [PATCH] Fix unfiled bug that could break TCP tests under some circumstances. The bug and solution are very similar to Issue 126 (fixed in d7e0c1445c0a). Basically a setsockopt(IPV6_V6ONLY) call had a bogus level argument, but we never checked the return value so we never noticed this. As with the prior issue, the fix is to unbreak the setsockopt() call, and add some error checking to detect future breakage. This bug was on a codepath that only got called if non-default values were set for the socket buffer size, the MSS, or the NODELAY parameter. It might have affected some FreeBSD tests, but really only got noticed when debugging some other code that was (probably) cut-and-pasted from this code. --- src/iperf_api.h | 1 + src/iperf_error.c | 4 ++++ src/iperf_tcp.c | 10 +++++++++- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/iperf_api.h b/src/iperf_api.h index bc68b96..7491551 100644 --- a/src/iperf_api.h +++ b/src/iperf_api.h @@ -283,6 +283,7 @@ enum { IEDAEMON = 133, // Unable to become a daemon process IESETCONGESTION = 134, // Unable to set TCP_CONGESTION IEPIDFILE = 135, // Unable to write PID file + IEV6ONLY = 136, // Unable to set/unset IPV6_V6ONLY (check perror) /* Stream errors */ IECREATESTREAM = 200, // Unable to create a new stream (check herror/perror) IEINITSTREAM = 201, // Unable to initialize stream (check herror/perror) diff --git a/src/iperf_error.c b/src/iperf_error.c index 645df48..cbd0565 100644 --- a/src/iperf_error.c +++ b/src/iperf_error.c @@ -299,6 +299,10 @@ iperf_strerror(int i_errno) snprintf(errstr, len, "unable to write PID file"); perr = 1; break; + case IEV6ONLY: + snprintf(errstr, len, "Unable to set/reset IPV6_V6ONLY"); + perr = 1; + break; } if (herr || perr) diff --git a/src/iperf_tcp.c b/src/iperf_tcp.c index 4c8fcb8..7d9ad02 100644 --- a/src/iperf_tcp.c +++ b/src/iperf_tcp.c @@ -208,7 +208,15 @@ iperf_tcp_listen(struct iperf_test *test) opt = 0; else if (test->settings->domain == AF_INET6) opt = 1; - setsockopt(s, SOL_SOCKET, IPV6_V6ONLY, (char *) &opt, sizeof(opt)); + if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, + (char *) &opt, sizeof(opt)) < 0) { + saved_errno = errno; + close(s); + freeaddrinfo(res); + errno = saved_errno; + i_errno = IEV6ONLY; + return -1; + } } if (bind(s, (struct sockaddr *) res->ai_addr, res->ai_addrlen) < 0) {