Compare commits

..

No commits in common. "c9-beta" and "c8" have entirely different histories.
c9-beta ... c8

8 changed files with 905 additions and 49 deletions

2
.gitignore vendored
View File

@ -1 +1 @@
SOURCES/3.9.tar.gz
SOURCES/iperf-3.5.tar.gz

View File

@ -1 +1 @@
52c9e7668d7cd371e5dabf187aab3123d0550145 SOURCES/3.9.tar.gz
b255fe0905159bcfe2578e4774ab3091f69f898f SOURCES/iperf-3.5.tar.gz

View File

@ -0,0 +1,18 @@
diff --git a/src/iperf3.1 b/src/iperf3.1
index 05483a9..35a0873 100644
--- a/src/iperf3.1
+++ b/src/iperf3.1
@@ -329,6 +329,13 @@ If the client is run with \fB--json\fR, the server output is included
in a JSON object; otherwise it is appended at the bottom of the
human-readable output.
.TP
+.BR --udp-counters-64bit
+Use 64-bit counters in UDP test packets.
+The use of this option can help prevent counter overflows during long
+or high-bitrate UDP tests. Both client and server need to be running
+at least version 3.1 for this option to work. It may become the
+default behavior at some point in the future.
+.TP
.BR --username " \fIusername\fR"
username to use for authentication to the iperf server (if built with
OpenSSL support).

View File

@ -0,0 +1,69 @@
diff --git a/src/iperf_sctp.c b/src/iperf_sctp.c
index a0869a3..13f5cdf 100644
--- a/src/iperf_sctp.c
+++ b/src/iperf_sctp.c
@@ -130,12 +130,14 @@ iperf_sctp_accept(struct iperf_test * test)
if (Nread(s, cookie, COOKIE_SIZE, Psctp) < 0) {
i_errno = IERECVCOOKIE;
+ close(s);
return -1;
}
- if (strcmp(test->cookie, cookie) != 0) {
+ if (strncmp(test->cookie, cookie, COOKIE_SIZE) != 0) {
if (Nwrite(s, (char*) &rbuf, sizeof(rbuf), Psctp) < 0) {
i_errno = IESENDMESSAGE;
+ close(s);
return -1;
}
close(s);
@@ -209,9 +211,11 @@ iperf_sctp_listen(struct iperf_test *test)
/* servers must call sctp_bindx() _instead_ of bind() */
if (!TAILQ_EMPTY(&test->xbind_addrs)) {
- freeaddrinfo(res);
- if (iperf_sctp_bindx(test, s, IPERF_SCTP_SERVER))
+ if (iperf_sctp_bindx(test, s, IPERF_SCTP_SERVER)) {
+ close(s);
+ freeaddrinfo(res);
return -1;
+ }
} else
if (bind(s, (struct sockaddr *) res->ai_addr, res->ai_addrlen) < 0) {
saved_errno = errno;
@@ -422,8 +426,11 @@ iperf_sctp_connect(struct iperf_test *test)
/* clients must call bind() followed by sctp_bindx() before connect() */
if (!TAILQ_EMPTY(&test->xbind_addrs)) {
- if (iperf_sctp_bindx(test, s, IPERF_SCTP_CLIENT))
+ if (iperf_sctp_bindx(test, s, IPERF_SCTP_CLIENT)) {
+ freeaddrinfo(server_res);
+ close(s);
return -1;
+ }
}
/* TODO support sctp_connectx() to avoid heartbeating. */
@@ -435,12 +442,12 @@ iperf_sctp_connect(struct iperf_test *test)
i_errno = IESTREAMCONNECT;
return -1;
}
- freeaddrinfo(server_res);
/* Send cookie for verification */
if (Nwrite(s, test->cookie, COOKIE_SIZE, Psctp) < 0) {
saved_errno = errno;
close(s);
+ freeaddrinfo(server_res);
errno = saved_errno;
i_errno = IESENDCOOKIE;
return -1;
@@ -464,6 +471,7 @@ iperf_sctp_connect(struct iperf_test *test)
return -1;
}
+ freeaddrinfo(server_res);
return s;
#else
i_errno = IENOSCTP;

View File

@ -0,0 +1,45 @@
From 41f5129d402bcd14ec4d2cde875203ab51076352 Mon Sep 17 00:00:00 2001
From: "Bruce A. Mah" <bmah@es.net>
Date: Fri, 7 Jul 2023 11:03:43 -0700
Subject: [PATCH] Fix memory allocation hazard (#1542).
Reported by: @someusername123 on GitHub
---
src/iperf_api.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/src/iperf_api.c b/src/iperf_api.c
index f2d416214..a95e02418 100644
--- a/src/iperf_api.c
+++ b/src/iperf_api.c
@@ -2670,6 +2670,7 @@ static cJSON *
JSON_read(int fd)
{
uint32_t hsize, nsize;
+ size_t strsize;
char *str;
cJSON *json = NULL;
int rc;
@@ -2682,7 +2683,9 @@ JSON_read(int fd)
if (Nread(fd, (char*) &nsize, sizeof(nsize), Ptcp) >= 0) {
hsize = ntohl(nsize);
/* Allocate a buffer to hold the JSON */
- str = (char *) calloc(sizeof(char), hsize+1); /* +1 for trailing null */
+ strsize = hsize + 1; /* +1 for trailing NULL */
+ if (strsize) {
+ str = (char *) calloc(sizeof(char), strsize);
if (str != NULL) {
rc = Nread(fd, str, hsize, Ptcp);
if (rc >= 0) {
@@ -2701,6 +2704,10 @@ JSON_read(int fd)
}
}
free(str);
+ }
+ else {
+ printf("WARNING: Data length overflow\n");
+ }
}
return json;
}

View File

@ -0,0 +1,497 @@
From 5e3704dd850a5df2fb2b3eafd117963d017d07b4 Mon Sep 17 00:00:00 2001
From: "Bruce A. Mah" <bmah@es.net>
Date: Tue, 1 Aug 2023 14:02:54 -0700
Subject: [PATCH] Implement fixes to make the control connection more robust.
These include various timeouts in Nread() to guarantee that it will
eventually exit, a 10-second timeout for each attempt to read data
from the network and an approximately 30-second overall timeout per
Nread() call.
Also the iperf3 server now checks the length of the received session
cookie, and errors out if this happens to be incorrect.
Reported by Jorge Sancho Larraz - Canonical.
---
src/iperf_server_api.c | 7 ++++-
src/net.c | 62 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 68 insertions(+), 1 deletion(-)
diff --git a/src/iperf_server_api.c b/src/iperf_server_api.c
index 5fa1dd7..c528d5f 100644
--- a/src/iperf_server_api.c
+++ b/src/iperf_server_api.c
@@ -118,7 +118,12 @@ iperf_accept(struct iperf_test *test)
if (test->ctrl_sck == -1) {
/* Server free, accept new client */
test->ctrl_sck = s;
- if (Nread(test->ctrl_sck, test->cookie, COOKIE_SIZE, Ptcp) < 0) {
+ if (Nread(test->ctrl_sck, test->cookie, COOKIE_SIZE, Ptcp) != COOKIE_SIZE) {
+ /*
+ * Note this error covers both the case of a system error
+ * or the inability to read the correct amount of data
+ * (i.e. timed out).
+ */
i_errno = IERECVCOOKIE;
return -1;
}
diff --git a/src/iperf_time.c b/src/iperf_time.c
new file mode 100644
index 0000000..a435dd3
--- /dev/null
+++ b/src/iperf_time.c
@@ -0,0 +1,156 @@
+/*
+ * iperf, Copyright (c) 2014-2018, The Regents of the University of
+ * California, through Lawrence Berkeley National Laboratory (subject
+ * to receipt of any required approvals from the U.S. Dept. of
+ * Energy). All rights reserved.
+ *
+ * If you have questions about your rights to use or distribute this
+ * software, please contact Berkeley Lab's Technology Transfer
+ * Department at TTD@lbl.gov.
+ *
+ * NOTICE. This software is owned by the U.S. Department of Energy.
+ * As such, the U.S. Government has been granted for itself and others
+ * acting on its behalf a paid-up, nonexclusive, irrevocable,
+ * worldwide license in the Software to reproduce, prepare derivative
+ * works, and perform publicly and display publicly. Beginning five
+ * (5) years after the date permission to assert copyright is obtained
+ * from the U.S. Department of Energy, and subject to any subsequent
+ * five (5) year renewals, the U.S. Government is granted for itself
+ * and others acting on its behalf a paid-up, nonexclusive,
+ * irrevocable, worldwide license in the Software to reproduce,
+ * prepare derivative works, distribute copies to the public, perform
+ * publicly and display publicly, and to permit others to do so.
+ *
+ * This code is distributed under a BSD style license, see the LICENSE
+ * file for complete information.
+ */
+
+
+#include <stddef.h>
+
+#include "iperf_config.h"
+#include "iperf_time.h"
+
+#ifdef HAVE_CLOCK_GETTIME
+
+#include <time.h>
+
+int
+iperf_time_now(struct iperf_time *time1)
+{
+ struct timespec ts;
+ int result;
+ result = clock_gettime(CLOCK_MONOTONIC, &ts);
+ if (result == 0) {
+ time1->secs = (uint32_t) ts.tv_sec;
+ time1->usecs = (uint32_t) ts.tv_nsec / 1000;
+ }
+ return result;
+}
+
+#else
+
+#include <sys/time.h>
+
+int
+iperf_time_now(struct iperf_time *time1)
+{
+ struct timeval tv;
+ int result;
+ result = gettimeofday(&tv, NULL);
+ time1->secs = tv.tv_sec;
+ time1->usecs = tv.tv_usec;
+ return result;
+}
+
+#endif
+
+/* iperf_time_add_usecs
+ *
+ * Add a number of microseconds to a iperf_time.
+ */
+void
+iperf_time_add_usecs(struct iperf_time *time1, uint64_t usecs)
+{
+ time1->secs += usecs / 1000000L;
+ time1->usecs += usecs % 1000000L;
+ if ( time1->usecs >= 1000000L ) {
+ time1->secs += time1->usecs / 1000000L;
+ time1->usecs %= 1000000L;
+ }
+}
+
+uint64_t
+iperf_time_in_usecs(struct iperf_time *time)
+{
+ return time->secs * 1000000LL + time->usecs;
+}
+
+double
+iperf_time_in_secs(struct iperf_time *time)
+{
+ return time->secs + time->usecs / 1000000.0;
+}
+
+/* iperf_time_compare
+ *
+ * Compare two timestamps
+ *
+ * Returns -1 if time1 is earlier, 1 if time1 is later,
+ * or 0 if the timestamps are equal.
+ */
+int
+iperf_time_compare(struct iperf_time *time1, struct iperf_time *time2)
+{
+ if (time1->secs < time2->secs)
+ return -1;
+ if (time1->secs > time2->secs)
+ return 1;
+ if (time1->usecs < time2->usecs)
+ return -1;
+ if (time1->usecs > time2->usecs)
+ return 1;
+ return 0;
+}
+
+/* iperf_time_diff
+ *
+ * Calculates the time from time2 to time1, assuming time1 is later than time2.
+ * The diff will always be positive, so the return value should be checked
+ * to determine if time1 was earlier than time2.
+ *
+ * Returns 1 if the time1 is less than or equal to time2, otherwise 0.
+ */
+int
+iperf_time_diff(struct iperf_time *time1, struct iperf_time *time2, struct iperf_time *diff)
+{
+ int past = 0;
+ int cmp = 0;
+
+ cmp = iperf_time_compare(time1, time2);
+ if (cmp == 0) {
+ diff->secs = 0;
+ diff->usecs = 0;
+ past = 1;
+ }
+ else if (cmp == 1) {
+ diff->secs = time1->secs - time2->secs;
+ diff->usecs = time1->usecs;
+ if (diff->usecs < time2->usecs) {
+ diff->secs -= 1;
+ diff->usecs += 1000000;
+ }
+ diff->usecs = diff->usecs - time2->usecs;
+ } else {
+ diff->secs = time2->secs - time1->secs;
+ diff->usecs = time2->usecs;
+ if (diff->usecs < time1->usecs) {
+ diff->secs -= 1;
+ diff->usecs += 1000000;
+ }
+ diff->usecs = diff->usecs - time1->usecs;
+ past = 1;
+ }
+
+ return past;
+}
diff --git a/src/iperf_time.h b/src/iperf_time.h
new file mode 100644
index 0000000..588ee26
--- /dev/null
+++ b/src/iperf_time.h
@@ -0,0 +1,49 @@
+/*
+ * iperf, Copyright (c) 2014-2018, The Regents of the University of
+ * California, through Lawrence Berkeley National Laboratory (subject
+ * to receipt of any required approvals from the U.S. Dept. of
+ * Energy). All rights reserved.
+ *
+ * If you have questions about your rights to use or distribute this
+ * software, please contact Berkeley Lab's Technology Transfer
+ * Department at TTD@lbl.gov.
+ *
+ * NOTICE. This software is owned by the U.S. Department of Energy.
+ * As such, the U.S. Government has been granted for itself and others
+ * acting on its behalf a paid-up, nonexclusive, irrevocable,
+ * worldwide license in the Software to reproduce, prepare derivative
+ * works, and perform publicly and display publicly. Beginning five
+ * (5) years after the date permission to assert copyright is obtained
+ * from the U.S. Department of Energy, and subject to any subsequent
+ * five (5) year renewals, the U.S. Government is granted for itself
+ * and others acting on its behalf a paid-up, nonexclusive,
+ * irrevocable, worldwide license in the Software to reproduce,
+ * prepare derivative works, distribute copies to the public, perform
+ * publicly and display publicly, and to permit others to do so.
+ *
+ * This code is distributed under a BSD style license, see the LICENSE
+ * file for complete information.
+ */
+#ifndef __IPERF_TIME_H
+#define __IPERF_TIME_H
+
+#include <stdint.h>
+
+struct iperf_time {
+ uint32_t secs;
+ uint32_t usecs;
+};
+
+int iperf_time_now(struct iperf_time *time1);
+
+void iperf_time_add_usecs(struct iperf_time *time1, uint64_t usecs);
+
+int iperf_time_compare(struct iperf_time *time1, struct iperf_time *time2);
+
+int iperf_time_diff(struct iperf_time *time1, struct iperf_time *time2, struct iperf_time *diff);
+
+uint64_t iperf_time_in_usecs(struct iperf_time *time);
+
+double iperf_time_in_secs(struct iperf_time *time);
+
+#endif
diff --git a/src/iperf.h b/src/iperf.h
index f55994f..f137b07 100755
--- a/src/iperf.h
+++ b/src/iperf.h
@@ -61,6 +61,7 @@
#include "timer.h"
#include "queue.h"
#include "cjson.h"
+#include "iperf_time.h"
typedef uint64_t iperf_size_t;
diff --git a/src/net.c b/src/net.c
index fd525ee..8804a39 100644
--- a/src/net.c
+++ b/src/net.c
@@ -60,10 +60,14 @@
#include <poll.h>
#endif /* HAVE_POLL_H */
+#include "iperf.h"
#include "iperf_util.h"
#include "net.h"
#include "timer.h"
+static int nread_read_timeout = 10;
+static int nread_overall_timeout = 30;
+
/*
* timeout_connect adapted from netcat, via OpenBSD and FreeBSD
* Copyright (c) 2001 Eric Jackson <ericj@monkey.org>
@@ -313,6 +317,32 @@ Nread(int fd, char *buf, size_t count, int prot)
{
register ssize_t r;
register size_t nleft = count;
+ struct iperf_time ftimeout = { 0, 0 };
+
+ fd_set rfdset;
+ struct timeval timeout = { nread_read_timeout, 0 };
+
+ /*
+ * fd might not be ready for reading on entry. Check for this
+ * (with timeout) first.
+ *
+ * This check could go inside the while() loop below, except we're
+ * currently considering whether it might make sense to support a
+ * codepath that bypassese this check, for situations where we
+ * already know that fd has data on it (for example if we'd gotten
+ * to here as the result of a select() call.
+ */
+ {
+ FD_ZERO(&rfdset);
+ FD_SET(fd, &rfdset);
+ r = select(fd + 1, &rfdset, NULL, NULL, &timeout);
+ if (r < 0) {
+ return NET_HARDERROR;
+ }
+ if (r == 0) {
+ return 0;
+ }
+ }
while (nleft > 0) {
r = read(fd, buf, nleft);
@@ -326,6 +356,39 @@ Nread(int fd, char *buf, size_t count, int prot)
nleft -= r;
buf += r;
+
+ /*
+ * We need some more bytes but don't want to wait around
+ * forever for them. In the case of partial results, we need
+ * to be able to read some bytes every nread_timeout seconds.
+ */
+ if (nleft > 0) {
+ struct iperf_time now;
+
+ /*
+ * Also, we have an approximate upper limit for the total time
+ * that a Nread call is supposed to take. We trade off accuracy
+ * of this timeout for a hopefully lower performance impact.
+ */
+ iperf_time_now(&now);
+ if (ftimeout.secs == 0) {
+ ftimeout = now;
+ iperf_time_add_usecs(&ftimeout, nread_overall_timeout * 1000000L);
+ }
+ if (iperf_time_compare(&ftimeout, &now) < 0) {
+ break;
+ }
+
+ FD_ZERO(&rfdset);
+ FD_SET(fd, &rfdset);
+ r = select(fd + 1, &rfdset, NULL, NULL, &timeout);
+ if (r < 0) {
+ return NET_HARDERROR;
+ }
+ if (r == 0) {
+ break;
+ }
+ }
}
return count - nleft;
}
diff --git a/src/Makefile.am b/src/Makefile.am
index 9184e84..1c24b62 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -21,6 +21,8 @@ libiperf_la_SOURCES = \
iperf_server_api.c \
iperf_tcp.c \
iperf_tcp.h \
+ iperf_time.c \
+ iperf_time.h \
iperf_udp.c \
iperf_udp.h \
iperf_sctp.c \
diff --git a/src/Makefile.in b/src/Makefile.in
index 714f601..6e75194 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -142,7 +142,8 @@ libiperf_la_LIBADD =
am_libiperf_la_OBJECTS = cjson.lo iperf_api.lo iperf_error.lo \
iperf_auth.lo iperf_client_api.lo iperf_locale.lo \
iperf_server_api.lo iperf_tcp.lo iperf_udp.lo iperf_sctp.lo \
- iperf_util.lo dscp.lo net.lo tcp_info.lo timer.lo units.lo
+ iperf_util.lo iperf_time.lo dscp.lo net.lo tcp_info.lo \
+ timer.lo units.lo
libiperf_la_OBJECTS = $(am_libiperf_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@@ -165,6 +166,7 @@ am__objects_1 = iperf3_profile-cjson.$(OBJEXT) \
iperf3_profile-iperf_udp.$(OBJEXT) \
iperf3_profile-iperf_sctp.$(OBJEXT) \
iperf3_profile-iperf_util.$(OBJEXT) \
+ iperf3_profile-iperf_time.$(OBJEXT) \
iperf3_profile-dscp.$(OBJEXT) iperf3_profile-net.$(OBJEXT) \
iperf3_profile-tcp_info.$(OBJEXT) \
iperf3_profile-timer.$(OBJEXT) iperf3_profile-units.$(OBJEXT)
@@ -220,6 +222,7 @@ am__depfiles_remade = ./$(DEPDIR)/cjson.Plo ./$(DEPDIR)/dscp.Plo \
./$(DEPDIR)/iperf3_profile-iperf_sctp.Po \
./$(DEPDIR)/iperf3_profile-iperf_server_api.Po \
./$(DEPDIR)/iperf3_profile-iperf_tcp.Po \
+ ./$(DEPDIR)/iperf3_profile-iperf_time.Po \
./$(DEPDIR)/iperf3_profile-iperf_udp.Po \
./$(DEPDIR)/iperf3_profile-iperf_util.Po \
./$(DEPDIR)/iperf3_profile-main.Po \
@@ -230,11 +233,12 @@ am__depfiles_remade = ./$(DEPDIR)/cjson.Plo ./$(DEPDIR)/dscp.Plo \
./$(DEPDIR)/iperf_auth.Plo ./$(DEPDIR)/iperf_client_api.Plo \
./$(DEPDIR)/iperf_error.Plo ./$(DEPDIR)/iperf_locale.Plo \
./$(DEPDIR)/iperf_sctp.Plo ./$(DEPDIR)/iperf_server_api.Plo \
- ./$(DEPDIR)/iperf_tcp.Plo ./$(DEPDIR)/iperf_udp.Plo \
- ./$(DEPDIR)/iperf_util.Plo ./$(DEPDIR)/net.Plo \
- ./$(DEPDIR)/t_timer-t_timer.Po ./$(DEPDIR)/t_units-t_units.Po \
- ./$(DEPDIR)/t_uuid-t_uuid.Po ./$(DEPDIR)/tcp_info.Plo \
- ./$(DEPDIR)/timer.Plo ./$(DEPDIR)/units.Plo
+ ./$(DEPDIR)/iperf_tcp.Plo ./$(DEPDIR)/iperf_time.Plo \
+ ./$(DEPDIR)/iperf_udp.Plo ./$(DEPDIR)/iperf_util.Plo \
+ ./$(DEPDIR)/net.Plo ./$(DEPDIR)/t_timer-t_timer.Po \
+ ./$(DEPDIR)/t_units-t_units.Po ./$(DEPDIR)/t_uuid-t_uuid.Po \
+ ./$(DEPDIR)/tcp_info.Plo ./$(DEPDIR)/timer.Plo \
+ ./$(DEPDIR)/units.Plo
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
@@ -613,6 +613,8 @@ libiperf_la_SOURCES = \
iperf_server_api.c \
iperf_tcp.c \
iperf_tcp.h \
+ iperf_time.c \
+ iperf_time.h \
iperf_udp.c \
iperf_udp.h \
iperf_sctp.c \
@@ -850,6 +854,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf3_profile-iperf_sctp.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf3_profile-iperf_server_api.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf3_profile-iperf_tcp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf3_profile-iperf_time.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf3_profile-iperf_udp.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf3_profile-iperf_util.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf3_profile-main.Po@am__quote@ # am--include-marker
@@ -865,6 +870,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf_sctp.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf_server_api.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf_tcp.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf_time.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf_udp.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf_util.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net.Plo@am__quote@ # am--include-marker
@@ -1084,6 +1090,20 @@ iperf3_profile-iperf_util.obj: iperf_util.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(iperf3_profile_CFLAGS) $(CFLAGS) -c -o iperf3_profile-iperf_util.obj `if test -f 'iperf_util.c'; then $(CYGPATH_W) 'iperf_util.c'; else $(CYGPATH_W) '$(srcdir)/iperf_util.c'; fi`
+iperf3_profile-iperf_time.o: iperf_time.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(iperf3_profile_CFLAGS) $(CFLAGS) -MT iperf3_profile-iperf_time.o -MD -MP -MF $(DEPDIR)/iperf3_profile-iperf_time.Tpo -c -o iperf3_profile-iperf_time.o `test -f 'iperf_time.c' || echo '$(srcdir)/'`iperf_time.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/iperf3_profile-iperf_time.Tpo $(DEPDIR)/iperf3_profile-iperf_time.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='iperf_time.c' object='iperf3_profile-iperf_time.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(iperf3_profile_CFLAGS) $(CFLAGS) -c -o iperf3_profile-iperf_time.o `test -f 'iperf_time.c' || echo '$(srcdir)/'`iperf_time.c
+
+iperf3_profile-iperf_time.obj: iperf_time.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(iperf3_profile_CFLAGS) $(CFLAGS) -MT iperf3_profile-iperf_time.obj -MD -MP -MF $(DEPDIR)/iperf3_profile-iperf_time.Tpo -c -o iperf3_profile-iperf_time.obj `if test -f 'iperf_time.c'; then $(CYGPATH_W) 'iperf_time.c'; else $(CYGPATH_W) '$(srcdir)/iperf_time.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/iperf3_profile-iperf_time.Tpo $(DEPDIR)/iperf3_profile-iperf_time.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='iperf_time.c' object='iperf3_profile-iperf_time.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(iperf3_profile_CFLAGS) $(CFLAGS) -c -o iperf3_profile-iperf_time.obj `if test -f 'iperf_time.c'; then $(CYGPATH_W) 'iperf_time.c'; else $(CYGPATH_W) '$(srcdir)/iperf_time.c'; fi`
+
iperf3_profile-dscp.o: dscp.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(iperf3_profile_CFLAGS) $(CFLAGS) -MT iperf3_profile-dscp.o -MD -MP -MF $(DEPDIR)/iperf3_profile-dscp.Tpo -c -o iperf3_profile-dscp.o `test -f 'dscp.c' || echo '$(srcdir)/'`dscp.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/iperf3_profile-dscp.Tpo $(DEPDIR)/iperf3_profile-dscp.Po
@@ -1634,6 +1654,7 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/iperf3_profile-iperf_sctp.Po
-rm -f ./$(DEPDIR)/iperf3_profile-iperf_server_api.Po
-rm -f ./$(DEPDIR)/iperf3_profile-iperf_tcp.Po
+ -rm -f ./$(DEPDIR)/iperf3_profile-iperf_time.Po
-rm -f ./$(DEPDIR)/iperf3_profile-iperf_udp.Po
-rm -f ./$(DEPDIR)/iperf3_profile-iperf_util.Po
-rm -f ./$(DEPDIR)/iperf3_profile-main.Po
@@ -1649,6 +1670,7 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/iperf_sctp.Plo
-rm -f ./$(DEPDIR)/iperf_server_api.Plo
-rm -f ./$(DEPDIR)/iperf_tcp.Plo
+ -rm -f ./$(DEPDIR)/iperf_time.Plo
-rm -f ./$(DEPDIR)/iperf_udp.Plo
-rm -f ./$(DEPDIR)/iperf_util.Plo
-rm -f ./$(DEPDIR)/net.Plo
@@ -1716,6 +1738,7 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/iperf3_profile-iperf_sctp.Po
-rm -f ./$(DEPDIR)/iperf3_profile-iperf_server_api.Po
-rm -f ./$(DEPDIR)/iperf3_profile-iperf_tcp.Po
+ -rm -f ./$(DEPDIR)/iperf3_profile-iperf_time.Po
-rm -f ./$(DEPDIR)/iperf3_profile-iperf_udp.Po
-rm -f ./$(DEPDIR)/iperf3_profile-iperf_util.Po
-rm -f ./$(DEPDIR)/iperf3_profile-main.Po
@@ -1731,6 +1754,7 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/iperf_sctp.Plo
-rm -f ./$(DEPDIR)/iperf_server_api.Plo
-rm -f ./$(DEPDIR)/iperf_tcp.Plo
+ -rm -f ./$(DEPDIR)/iperf_time.Plo
-rm -f ./$(DEPDIR)/iperf_udp.Plo
-rm -f ./$(DEPDIR)/iperf_util.Plo
-rm -f ./$(DEPDIR)/net.Plo

View File

@ -0,0 +1,231 @@
From 299b356df6939f71619bf45bf7a7d2222e17d840 Mon Sep 17 00:00:00 2001
From: Sarah Larsen <swlarsen@Sarahs-MBP.lan>
Date: Wed, 20 Mar 2024 17:02:31 -0700
Subject: [PATCH] Using OAEP padding instead of PKCS1 padding for OpenSSL. Fix
for CVE-2024-26306.
Special thanks to Hubert Kario at Red Hat for finding the vulnerability.
diff --git a/src/iperf.h b/src/iperf.h
index f137b07..f6c0313 100755
--- a/src/iperf.h
+++ b/src/iperf.h
@@ -260,6 +260,7 @@ struct iperf_test
int ctrl_sck_mss; /* MSS for the control channel */
char *server_rsa_private_key;
char *server_authorized_users;
+ int use_pkcs1_padding;
/* boolean variables for Options */
int daemon; /* -D option */
diff --git a/src/iperf_api.c b/src/iperf_api.c
index d40561c10..7fb741e77 100644
--- a/src/iperf_api.c
+++ b/src/iperf_api.c
@@ -1137,6 +1137,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
{"rsa-public-key-path", required_argument, NULL, OPT_CLIENT_RSA_PUBLIC_KEY},
{"rsa-private-key-path", required_argument, NULL, OPT_SERVER_RSA_PRIVATE_KEY},
{"authorized-users-path", required_argument, NULL, OPT_SERVER_AUTHORIZED_USERS},
+ {"use-pkcs1-padding", no_argument, NULL, OPT_USE_PKCS1_PADDING},
#endif /* HAVE_SSL */
{"fq-rate", required_argument, NULL, OPT_FQ_RATE},
{"pacing-timer", required_argument, NULL, OPT_PACING_TIMER},
@@ -1630,6 +1631,9 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
case OPT_SERVER_AUTHORIZED_USERS:
test->server_authorized_users = strdup(optarg);
break;
+ case OPT_USE_PKCS1_PADDING:
+ test->use_pkcs1_padding = 1;
+ break;
#endif /* HAVE_SSL */
case OPT_PACING_TIMER:
test->settings->pacing_timer = unit_atoi(optarg);
@@ -1100,7 +1104,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
i_errno = IESETCLIENTAUTH;
return -1;
}
- encode_auth_setting(client_username, client_password, client_rsa_public_key, &test->settings->authtoken);
+ encode_auth_setting(client_username, client_password, client_rsa_public_key, &test->settings->authtoken, test->use_pkcs1_padding);
}
if (test->role == 'c' && (test->server_rsa_private_key || test->server_authorized_users)){
@@ -1346,7 +1350,7 @@ int test_is_authorized(struct iperf_test *test){
if (test->settings->authtoken){
char *username = NULL, *password = NULL;
time_t ts;
- decode_auth_setting(test->debug, test->settings->authtoken, test->server_rsa_private_key, &username, &password, &ts);
+ decode_auth_setting(test->debug, test->settings->authtoken, test->server_rsa_private_key, &username, &password, &ts, test->use_pkcs1_padding);
int ret = check_authentication(username, password, ts, test->server_authorized_users);
if (ret == 0){
iperf_printf(test, report_authetication_successed, username, ts);
diff --git a/src/iperf_locale.c b/src/iperf_locale.c
index d5a5354..3b6860d 100644
--- a/src/iperf_locale.c
+++ b/src/iperf_locale.c
@@ -128,6 +128,7 @@ const char usage_longstr[] = "Usage: iperf3 [-s|-c host] [options]\n"
" authentication credentials\n"
" --authorized-users-path path to the configuration file containing user\n"
" credentials\n"
+ " --use-pkcs1-padding use pkcs1 padding at your own risk\n"
#endif //HAVE_SSL
"Client specific:\n"
" -c, --client <host> run in client mode, connecting to <host>\n"
diff --git a/src/iperf_api.h b/src/iperf_api.h
index 3a5df03..255227c 100755
--- a/src/iperf_api.h
+++ b/src/iperf_api.h
@@ -68,6 +68,7 @@ struct iperf_stream;
#define OPT_SERVER_AUTHORIZED_USERS 15
#define OPT_PACING_TIMER 16
#define OPT_CONNECT_TIMEOUT 17
+#define OPT_USE_PKCS1_PADDING 30
/* states */
#define TEST_START 1
diff --git a/src/iperf_auth.h b/src/iperf_auth.h
index 38971d8..1f78699 100644
--- a/src/iperf_auth.h
+++ b/src/iperf_auth.h
@@ -30,7 +30,7 @@
int test_load_pubkey(const char *public_keyfile);
int test_load_private_key(const char *private_keyfile);
-int encode_auth_setting(const char *username, const char *password, const char *public_keyfile, char **authtoken);
-int decode_auth_setting(int enable_debug, const char *authtoken, const char *private_keyfile, char **username, char **password, time_t *ts);
+int encode_auth_setting(const char *username, const char *password, const char *public_keyfile, char **authtoken, int use_pkcs1_padding);
+int decode_auth_setting(int enable_debug, const char *authtoken, const char *private_keyfile, char **username, char **password, time_t *ts, int use_pkcs1_padding);
int check_authentication(const char *username, const char *password, const time_t ts, const char *filename);
ssize_t iperf_getpass (char **lineptr, size_t *n, FILE *stream);
diff --git a/src/iperf3.1 b/src/iperf3.1
index 1be8cc3..87c3e02 100644
--- a/src/iperf3.1
+++ b/src/iperf3.1
@@ -155,6 +155,15 @@ send output to a log file.
force flushing output at every interval.
Used to avoid buffering when sending output to pipe.
.TP
+.BR --use-pkcs1-padding
+This option is only meaningful when using iperf3's authentication
+features. Versions of iperf3 prior to 3.17 used PCKS1 padding in the
+RSA-encrypted credentials, which was vulnerable to a side-channel
+attack that could reveal a server's private key. Beginning with
+iperf-3.17, OAEP padding is used, however this is a breaking change
+that is not compatible with older iperf3 versions. Use this option to
+preserve the less secure, but more compatible, behavior.
+.TP
.BR -d ", " --debug " "
emit debugging output.
Primarily (perhaps exclusively) of use to developers.
diff --git a/src/iperf_auth.c b/src/iperf_auth.c
index f8d2b0a..2d7d519 100644
--- a/src/iperf_auth.c
+++ b/src/iperf_auth.c
@@ -194,11 +194,12 @@ int test_load_private_key(const char *file){
return 0;
}
-int encrypt_rsa_message(const char *plaintext, const char *public_keyfile, unsigned char **encryptedtext) {
+int encrypt_rsa_message(const char *plaintext, const char *public_keyfile, unsigned char **encryptedtext, int use_pkcs1_padding) {
EVP_PKEY *public_key = NULL;
RSA *rsa = NULL;
- unsigned char *rsa_buffer = NULL, pad = RSA_PKCS1_PADDING;
- int keysize, encryptedtext_len, rsa_buffer_len;
+ unsigned char *rsa_buffer = NULL;
+ size_t encryptedtext_len = 0;
+ int rsa_buffer_len, keysize;
public_key = load_pubkey(public_keyfile);
rsa = EVP_PKEY_get1_RSA(public_key);
@@ -210,20 +211,35 @@ int encrypt_rsa_message(const char *plaintext, const char *public_keyfile, unsig
BIO *bioBuff = BIO_new_mem_buf((void*)plaintext, (int)strlen(plaintext));
rsa_buffer_len = BIO_read(bioBuff, rsa_buffer, keysize * 2);
- encryptedtext_len = RSA_public_encrypt(rsa_buffer_len, rsa_buffer, *encryptedtext, rsa, pad);
+
+ int padding = RSA_PKCS1_OAEP_PADDING;
+ if (use_pkcs1_padding){
+ padding = RSA_PKCS1_PADDING;
+ }
+
+ encryptedtext_len = RSA_public_encrypt(rsa_buffer_len, rsa_buffer, *encryptedtext, rsa, padding);
RSA_free(rsa);
OPENSSL_free(rsa_buffer);
- OPENSSL_free(bioBuff);
+ OPENSSL_free(bioBuff);
+
+ if (encryptedtext_len < 0) {
+ goto errreturn;
+ }
+
+ return encryptedtext_len;
- return encryptedtext_len;
+ errreturn:
+ fprintf(stderr, "%s\n", ERR_error_string(ERR_get_error(), NULL));
+ return 0;
}
-int decrypt_rsa_message(const unsigned char *encryptedtext, const int encryptedtext_len, const char *private_keyfile, unsigned char **plaintext) {
+int decrypt_rsa_message(const unsigned char *encryptedtext, const int encryptedtext_len, const char *private_keyfile, unsigned char **plaintext, int use_pkcs1_padding) {
EVP_PKEY *private_key = NULL;
RSA *rsa = NULL;
- unsigned char *rsa_buffer = NULL, pad = RSA_PKCS1_PADDING;
- int plaintext_len, rsa_buffer_len, keysize;
+ unsigned char *rsa_buffer = NULL;
+ size_t plaintext_len = 0;
+ int rsa_buffer_len, keysize;
private_key = load_key(private_keyfile);
rsa = EVP_PKEY_get1_RSA(private_key);
@@ -235,35 +250,45 @@ int decrypt_rsa_message(const unsigned char *encryptedtext, const int encryptedt
BIO *bioBuff = BIO_new_mem_buf((void*)encryptedtext, encryptedtext_len);
rsa_buffer_len = BIO_read(bioBuff, rsa_buffer, keysize * 2);
- plaintext_len = RSA_private_decrypt(rsa_buffer_len, rsa_buffer, *plaintext, rsa, pad);
+
+ int padding = RSA_PKCS1_OAEP_PADDING;
+ if (use_pkcs1_padding){
+ padding = RSA_PKCS1_PADDING;
+ }
+
+ plaintext_len = RSA_private_decrypt(rsa_buffer_len, rsa_buffer, *plaintext, rsa, padding);
RSA_free(rsa);
OPENSSL_free(rsa_buffer);
OPENSSL_free(bioBuff);
+ if (plaintext_len < 0) {
+ plaintext_len = 0;
+ }
+
return plaintext_len;
}
-int encode_auth_setting(const char *username, const char *password, const char *public_keyfile, char **authtoken){
+int encode_auth_setting(const char *username, const char *password, const char *public_keyfile, char **authtoken, int use_pkcs1_padding){
time_t t = time(NULL);
time_t utc_seconds = mktime(localtime(&t));
char text[150];
sprintf (text, "user: %s\npwd: %s\nts: %ld", username, password, utc_seconds);
unsigned char *encrypted = NULL;
int encrypted_len;
- encrypted_len = encrypt_rsa_message(text, public_keyfile, &encrypted);
+ encrypted_len = encrypt_rsa_message(text, public_keyfile, &encrypted, use_pkcs1_padding);
Base64Encode(encrypted, encrypted_len, authtoken);
return (0); //success
}
-int decode_auth_setting(int enable_debug, char *authtoken, const char *private_keyfile, char **username, char **password, time_t *ts){
+int decode_auth_setting(int enable_debug, char *authtoken, const char *private_keyfile, char **username, char **password, time_t *ts, int use_pkcs1_padding){
unsigned char *encrypted_b64 = NULL;
size_t encrypted_len_b64;
Base64Decode(authtoken, &encrypted_b64, &encrypted_len_b64);
unsigned char *plaintext = NULL;
int plaintext_len;
- plaintext_len = decrypt_rsa_message(encrypted_b64, encrypted_len_b64, private_keyfile, &plaintext);
+ plaintext_len = decrypt_rsa_message(encrypted_b64, encrypted_len_b64, private_keyfile, &plaintext, use_pkcs1_padding);
plaintext[plaintext_len] = '\0';
char s_username[20], s_password[20];

View File

@ -1,16 +1,21 @@
Name: iperf3
Version: 3.9
Release: 9%{?dist}
Version: 3.5
Release: 10%{?dist}
Summary: Measurement tool for TCP/UDP bandwidth performance
Group: Applications/Internet
License: BSD
URL: https://github.com/esnet/iperf
Source0: https://github.com/esnet/iperf/archive/%{version}.tar.gz
BuildRequires: libuuid-devel
BuildRequires: gcc
URL: http://github.com/esnet/iperf
Source0: http://downloads.es.net/pub/iperf/iperf-%{version}.tar.gz
BuildRequires: libuuid-devel git-core gcc make
BuildRequires: lksctp-tools-devel
BuildRequires: openssl-devel
BuildRequires: make
Patch0002: 0002-udp-counters-manpage.patch
Patch0003: 0003-covscan-sctp.patch
Patch0004: 0004-cve-2023-38403.patch
Patch0005: 0005-cve-2023-7250.patch
Patch0006: 0006-cve-2024-26306.patch
%description
Iperf is a tool to measure maximum TCP bandwidth, allowing the tuning of
@ -19,6 +24,7 @@ jitter, data-gram loss.
%package devel
Summary: Development files for %{name}
Group: Development/Libraries
Requires: %{name}%{?_isa} = %{version}-%{release}
%description devel
@ -26,7 +32,7 @@ The %{name}-devel package contains libraries and header files for
developing applications that use %{name}.
%prep
%setup -q -n iperf-%{version}
%autosetup -S git -n iperf-%{version}
%build
%configure --disable-static
@ -41,64 +47,54 @@ mkdir -p %{buildroot}%{_mandir}/man1
rm -f %{buildroot}%{_libdir}/libiperf.la
%files
%doc README.md LICENSE RELNOTES.md
%defattr(-,root,root,-)
%doc README.md LICENSE RELEASE_NOTES
%{_mandir}/man1/iperf3.1.gz
%{_mandir}/man3/libiperf.3.gz
%{_bindir}/iperf3
%{_libdir}/*.so.*
%post -p /sbin/ldconfig
%postun -p /sbin/ldconfig
%files devel
%defattr(-,root,root,-)
%{_includedir}/iperf_api.h
%{_libdir}/*.so
%changelog
* Mon Aug 09 2021 Mohan Boddu <mboddu@redhat.com> - 3.9-9
- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
Related: rhbz#1991688
* Tue Jun 11 2024 Michal Ruprich <mruprich@redhat.com> - 3.5-10
- Resolves: RHEL-29578 - vulnerable to marvin attack if the authentication option is used
* Wed Jun 16 2021 Mohan Boddu <mboddu@redhat.com> - 3.9-8
- Rebuilt for RHEL 9 BETA for openssl 3.0
Related: rhbz#1971065
* Tue Jun 04 2024 Michal Ruprich <mruprich@redhat.com> - 3.5-9
- Resolves: RHEL-17069 - possible denial of service
* Fri Apr 16 2021 Mohan Boddu <mboddu@redhat.com> - 3.9-7
- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937
* Fri Jul 28 2023 Michal Ruprich <mruprich@redhat.com> - 3.5-8
- Related: #2222205 - bumping nvr for correct update path
* Tue Jan 26 2021 Fedora Release Engineering <releng@fedoraproject.org> - 3.9-6
- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild
* Tue Jul 18 2023 Jonathan Wright <jonathan@almalinux.org> - 3.5-7
- Fixes CVE-2023-38403
Resolves: rhbz#2223729
* Sat Oct 31 2020 Kevin Fenzi <kevin@scrye.com> - 3.9-5
- Update to 3.9. Fixes bug #1846161
* Tue May 05 2020 Michal Ruprich <michalruprich@gmail.com> - 3.5-6
- Related: #1665142 - Fixing a couple of covscan issues
* Tue Jul 28 2020 Fedora Release Engineering <releng@fedoraproject.org> - 3.7-5
- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
* Fri Mar 13 2020 Michal Ruprich <michalruprich@gmail.com> - 3.5-5
- Related: #1665142 - Removing patch that deletes sctp from manpage
* Wed Feb 19 2020 Michal Ruprich <mruprich@redhat.com> - 3.7-4
- Add openssl-devel to BuildRequires to enable authentization of client
* Mon Mar 09 2020 Michal Ruprich <mruprich@redhat.com> - 3.5-4
- Resolves: #1665142 - [RFE] enable SCTP support in iperf3
- Resolves: #1656429 - option --udp-counters-64bit shown in --help output but not in man page
- Resolves: #1700497 - [RFE] enable SSL support in iperf3
* Wed Jan 29 2020 Fedora Release Engineering <releng@fedoraproject.org> - 3.7-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
* Sun Dec 16 2018 Michal Ruprich <mruprich@redhat.com> - 3.5-3
- Related: #1647413 - Removing nstreams and xbind from man since these are SCTP-related options
* Thu Jul 25 2019 Fedora Release Engineering <releng@fedoraproject.org> - 3.7-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
* Thu Nov 22 2018 Michal Ruprich <mruprich@redhat.com> - 3.5-2
- Related: #1647413 - adding some BuildRequires
* Sat Jun 22 2019 Kevin Fenzi <kevin@scrye.com> - 3.7-1
- Update to 3.7. Fixes bug #1723020
* Tue Feb 26 2019 Tomas Korbar <tkorbar@redhat.com> - 3.6-5
- Add lksctp-tools-devel to BuildRequires
- Fix bug #1647385
* Fri Feb 01 2019 Fedora Release Engineering <releng@fedoraproject.org> - 3.6-4
- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
* Fri Jul 20 2018 Kevin Fenzi <kevin@scrye.com> - 3.6-3
- Fix FTBFS bug #1604377 by adding BuildRequires: gcc
* Fri Jul 13 2018 Fedora Release Engineering <releng@fedoraproject.org> - 3.6-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
* Thu Jun 28 2018 Kevin Fenzi <kevin@scrye.com> - 3.6-1
- Update to 3.6. Fixes bug #1594995
* Thu Nov 22 2018 Michal Ruprich <mruprich@redhat.com> - 3.5-2
- Resolves: #1647413 - iperf3 with option --sctp in client mode fails with error 'iperf3: unrecognized option --sctp'
* Sat Mar 03 2018 Kevin Fenzi <kevin@scrye.com> - 3.5-1
- Update to 3.5. Fixes bug #1551166