summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:27:01 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:27:01 +0000
commitdc990bc79d0d7663bd6e775d2253e158b74686b4 (patch)
tree8e3731e353efeffbf1319921c34e579fa403033b /src
parentReleasing progress-linux version 3.16-1~progress7.99u1. (diff)
downloadiperf3-dc990bc79d0d7663bd6e775d2253e158b74686b4.tar.xz
iperf3-dc990bc79d0d7663bd6e775d2253e158b74686b4.zip
Merging upstream version 3.17.1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--src/Makefile.am2
-rw-r--r--src/Makefile.in50
-rw-r--r--src/cjson.c22
-rw-r--r--src/cjson.h2
-rw-r--r--src/iperf.h33
-rw-r--r--src/iperf3.120
-rw-r--r--src/iperf_api.c153
-rw-r--r--src/iperf_api.h8
-rw-r--r--src/iperf_auth.c37
-rw-r--r--src/iperf_auth.h4
-rw-r--r--src/iperf_client_api.c12
-rw-r--r--src/iperf_config.h.in20
-rw-r--r--src/iperf_error.c34
-rw-r--r--src/iperf_locale.c27
-rw-r--r--src/iperf_pthread.c40
-rw-r--r--src/iperf_pthread.h21
-rw-r--r--src/iperf_server_api.c2
-rw-r--r--src/iperf_tcp.c35
-rw-r--r--src/iperf_udp.c16
-rw-r--r--src/libiperf.31
-rw-r--r--src/main.c4
-rw-r--r--src/net.c1
-rw-r--r--src/portable_endian.h2
-rw-r--r--src/t_api.c2
-rw-r--r--src/t_auth.c7
-rw-r--r--src/t_timer.c2
-rw-r--r--src/t_units.c2
-rw-r--r--src/units.c2
28 files changed, 372 insertions, 189 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 11d3e17..bdd638f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -33,6 +33,8 @@ libiperf_la_SOURCES = \
iperf_util.h \
iperf_time.c \
iperf_time.h \
+ iperf_pthread.c \
+ iperf_pthread.h \
dscp.c \
net.c \
net.h \
diff --git a/src/Makefile.in b/src/Makefile.in
index e13e4ed..9816502 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -150,8 +150,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 iperf_time.lo dscp.lo net.lo tcp_info.lo \
- timer.lo units.lo
+ iperf_util.lo iperf_time.lo iperf_pthread.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@)
@@ -168,9 +168,9 @@ am__iperf3_profile_SOURCES_DIST = main.c cjson.c cjson.h flowlabel.h \
iperf_auth.c iperf_client_api.c iperf_locale.c iperf_locale.h \
iperf_server_api.c iperf_tcp.c iperf_tcp.h iperf_udp.c \
iperf_udp.h iperf_sctp.c iperf_sctp.h iperf_util.c \
- iperf_util.h iperf_time.c iperf_time.h dscp.c net.c net.h \
- portable_endian.h queue.h tcp_info.c timer.c timer.h units.c \
- units.h version.h
+ iperf_util.h iperf_time.c iperf_time.h iperf_pthread.c \
+ iperf_pthread.h dscp.c net.c net.h portable_endian.h queue.h \
+ tcp_info.c timer.c timer.h units.c units.h version.h
am__objects_1 = iperf3_profile-cjson.$(OBJEXT) \
iperf3_profile-iperf_api.$(OBJEXT) \
iperf3_profile-iperf_error.$(OBJEXT) \
@@ -183,6 +183,7 @@ am__objects_1 = iperf3_profile-cjson.$(OBJEXT) \
iperf3_profile-iperf_sctp.$(OBJEXT) \
iperf3_profile-iperf_util.$(OBJEXT) \
iperf3_profile-iperf_time.$(OBJEXT) \
+ iperf3_profile-iperf_pthread.$(OBJEXT) \
iperf3_profile-dscp.$(OBJEXT) iperf3_profile-net.$(OBJEXT) \
iperf3_profile-tcp_info.$(OBJEXT) \
iperf3_profile-timer.$(OBJEXT) iperf3_profile-units.$(OBJEXT)
@@ -248,6 +249,7 @@ am__depfiles_remade = ./$(DEPDIR)/cjson.Plo ./$(DEPDIR)/dscp.Plo \
./$(DEPDIR)/iperf3_profile-iperf_client_api.Po \
./$(DEPDIR)/iperf3_profile-iperf_error.Po \
./$(DEPDIR)/iperf3_profile-iperf_locale.Po \
+ ./$(DEPDIR)/iperf3_profile-iperf_pthread.Po \
./$(DEPDIR)/iperf3_profile-iperf_sctp.Po \
./$(DEPDIR)/iperf3_profile-iperf_server_api.Po \
./$(DEPDIR)/iperf3_profile-iperf_tcp.Po \
@@ -261,14 +263,14 @@ am__depfiles_remade = ./$(DEPDIR)/cjson.Plo ./$(DEPDIR)/dscp.Plo \
./$(DEPDIR)/iperf3_profile-units.Po ./$(DEPDIR)/iperf_api.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_time.Plo \
- ./$(DEPDIR)/iperf_udp.Plo ./$(DEPDIR)/iperf_util.Plo \
- ./$(DEPDIR)/net.Plo ./$(DEPDIR)/t_api-t_api.Po \
- ./$(DEPDIR)/t_auth-t_auth.Po ./$(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_pthread.Plo ./$(DEPDIR)/iperf_sctp.Plo \
+ ./$(DEPDIR)/iperf_server_api.Plo ./$(DEPDIR)/iperf_tcp.Plo \
+ ./$(DEPDIR)/iperf_time.Plo ./$(DEPDIR)/iperf_udp.Plo \
+ ./$(DEPDIR)/iperf_util.Plo ./$(DEPDIR)/net.Plo \
+ ./$(DEPDIR)/t_api-t_api.Po ./$(DEPDIR)/t_auth-t_auth.Po \
+ ./$(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)
@@ -665,6 +667,8 @@ libiperf_la_SOURCES = \
iperf_util.h \
iperf_time.c \
iperf_time.h \
+ iperf_pthread.c \
+ iperf_pthread.h \
dscp.c \
net.c \
net.h \
@@ -908,6 +912,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf3_profile-iperf_client_api.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf3_profile-iperf_error.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf3_profile-iperf_locale.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf3_profile-iperf_pthread.Po@am__quote@ # am--include-marker
@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
@@ -924,6 +929,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf_client_api.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf_error.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf_locale.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf_pthread.Plo@am__quote@ # am--include-marker
@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
@@ -1163,6 +1169,20 @@ iperf3_profile-iperf_time.obj: iperf_time.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_time.obj `if test -f 'iperf_time.c'; then $(CYGPATH_W) 'iperf_time.c'; else $(CYGPATH_W) '$(srcdir)/iperf_time.c'; fi`
+iperf3_profile-iperf_pthread.o: iperf_pthread.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(iperf3_profile_CFLAGS) $(CFLAGS) -MT iperf3_profile-iperf_pthread.o -MD -MP -MF $(DEPDIR)/iperf3_profile-iperf_pthread.Tpo -c -o iperf3_profile-iperf_pthread.o `test -f 'iperf_pthread.c' || echo '$(srcdir)/'`iperf_pthread.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/iperf3_profile-iperf_pthread.Tpo $(DEPDIR)/iperf3_profile-iperf_pthread.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='iperf_pthread.c' object='iperf3_profile-iperf_pthread.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_pthread.o `test -f 'iperf_pthread.c' || echo '$(srcdir)/'`iperf_pthread.c
+
+iperf3_profile-iperf_pthread.obj: iperf_pthread.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(iperf3_profile_CFLAGS) $(CFLAGS) -MT iperf3_profile-iperf_pthread.obj -MD -MP -MF $(DEPDIR)/iperf3_profile-iperf_pthread.Tpo -c -o iperf3_profile-iperf_pthread.obj `if test -f 'iperf_pthread.c'; then $(CYGPATH_W) 'iperf_pthread.c'; else $(CYGPATH_W) '$(srcdir)/iperf_pthread.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/iperf3_profile-iperf_pthread.Tpo $(DEPDIR)/iperf3_profile-iperf_pthread.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='iperf_pthread.c' object='iperf3_profile-iperf_pthread.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_pthread.obj `if test -f 'iperf_pthread.c'; then $(CYGPATH_W) 'iperf_pthread.c'; else $(CYGPATH_W) '$(srcdir)/iperf_pthread.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
@@ -1751,6 +1771,7 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/iperf3_profile-iperf_client_api.Po
-rm -f ./$(DEPDIR)/iperf3_profile-iperf_error.Po
-rm -f ./$(DEPDIR)/iperf3_profile-iperf_locale.Po
+ -rm -f ./$(DEPDIR)/iperf3_profile-iperf_pthread.Po
-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
@@ -1767,6 +1788,7 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/iperf_client_api.Plo
-rm -f ./$(DEPDIR)/iperf_error.Plo
-rm -f ./$(DEPDIR)/iperf_locale.Plo
+ -rm -f ./$(DEPDIR)/iperf_pthread.Plo
-rm -f ./$(DEPDIR)/iperf_sctp.Plo
-rm -f ./$(DEPDIR)/iperf_server_api.Plo
-rm -f ./$(DEPDIR)/iperf_tcp.Plo
@@ -1837,6 +1859,7 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/iperf3_profile-iperf_client_api.Po
-rm -f ./$(DEPDIR)/iperf3_profile-iperf_error.Po
-rm -f ./$(DEPDIR)/iperf3_profile-iperf_locale.Po
+ -rm -f ./$(DEPDIR)/iperf3_profile-iperf_pthread.Po
-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
@@ -1853,6 +1876,7 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/iperf_client_api.Plo
-rm -f ./$(DEPDIR)/iperf_error.Plo
-rm -f ./$(DEPDIR)/iperf_locale.Plo
+ -rm -f ./$(DEPDIR)/iperf_pthread.Plo
-rm -f ./$(DEPDIR)/iperf_sctp.Plo
-rm -f ./$(DEPDIR)/iperf_server_api.Plo
-rm -f ./$(DEPDIR)/iperf_tcp.Plo
diff --git a/src/cjson.c b/src/cjson.c
index 02d8d60..46495f4 100644
--- a/src/cjson.c
+++ b/src/cjson.c
@@ -45,9 +45,8 @@
#include <limits.h>
#include <ctype.h>
#include <float.h>
-#ifdef HAVE_STDINT_H
#include <stdint.h>
-#endif
+#include <inttypes.h>
#include <sys/types.h>
#ifdef ENABLE_LOCALES
@@ -90,25 +89,6 @@
#endif
#endif
-#if defined(HAVE_INTTYPES_H)
-# include <inttypes.h>
-#else
-# ifndef PRIu64
-# if sizeof(long) == 8
-# define PRIu64 "lu"
-# else
-# define PRIu64 "llu"
-# endif
-# ifndef PRId64
-# if sizeof(long) == 8
-# define PRId64 "ld"
-# else
-# define PRId64 "lld"
-# endif
-# endif
-# endif
-#endif
-
typedef struct {
const unsigned char *json;
size_t position;
diff --git a/src/cjson.h b/src/cjson.h
index 52da40d..3aa83cb 100644
--- a/src/cjson.h
+++ b/src/cjson.h
@@ -23,9 +23,7 @@
#ifndef cJSON__h
#define cJSON__h
-#ifdef HAVE_STDINT_H
#include <stdint.h>
-#endif
#ifdef __cplusplus
extern "C"
diff --git a/src/iperf.h b/src/iperf.h
index 7b270bd..527e549 100644
--- a/src/iperf.h
+++ b/src/iperf.h
@@ -31,9 +31,8 @@
#include <sys/time.h>
#include <sys/types.h>
-#ifdef HAVE_STDINT_H
#include <stdint.h>
-#endif
+#include <inttypes.h>
#include <sys/select.h>
#include <sys/socket.h>
#ifndef _GNU_SOURCE
@@ -51,31 +50,18 @@
#include <sys/cpuset.h>
#endif /* HAVE_CPUSET_SETAFFINITY */
-#if defined(HAVE_INTTYPES_H)
-# include <inttypes.h>
-#else
-# ifndef PRIu64
-# if sizeof(long) == 8
-# define PRIu64 "lu"
-# else
-# define PRIu64 "llu"
-# endif
-# endif
-#endif
-
#include "timer.h"
#include "queue.h"
#include "cjson.h"
#include "iperf_time.h"
+#include "portable_endian.h"
#if defined(HAVE_SSL)
#include <openssl/bio.h>
#include <openssl/evp.h>
#endif // HAVE_SSL
-#ifdef HAVE_PTHREAD
-#include <pthread.h>
-#endif // HAVE_PTHREAD
+#include "iperf_pthread.h"
/*
* Atomic types highly desired, but if not, we approximate what we need
@@ -93,6 +79,10 @@ typedef uint_fast64_t iperf_size_t;
typedef atomic_uint_fast64_t atomic_iperf_size_t;
#endif // __IPERF_API_H
+#if (defined(__vxworks)) || (defined(__VXWORKS__))
+typedef unsigned int uint
+#endif // __vxworks or __VXWORKS__
+
struct iperf_interval_results
{
atomic_iperf_size_t bytes_transferred; /* bytes transferred in this interval */
@@ -329,6 +319,7 @@ struct iperf_test
char *server_authorized_users;
EVP_PKEY *server_rsa_private_key;
int server_skew_threshold;
+ int use_pkcs1_padding;
#endif // HAVE_SSL
/* boolean variables for Options */
@@ -339,6 +330,7 @@ struct iperf_test
int bidirectional; /* --bidirectional */
int verbose; /* -V option - verbose mode */
int json_output; /* -J option - JSON output */
+ int json_stream; /* --json-stream */
int zerocopy; /* -Z option - use sendfile */
int debug; /* -d option - enable debug */
enum debug_level debug_level; /* -d option option - level of debug messages to show */
@@ -453,9 +445,16 @@ struct iperf_test
extern int gerror; /* error value from getaddrinfo(3), for use in internal error handling */
/* UDP "connect" message and reply (textual value for Wireshark, etc. readability - legacy was numeric) */
+
+#if BYTE_ORDER == BIG_ENDIAN
+#define UDP_CONNECT_MSG 0x39383736
+#define UDP_CONNECT_REPLY 0x36373839
+#define LEGACY_UDP_CONNECT_REPLY 0xb168de3a
+#else
#define UDP_CONNECT_MSG 0x36373839 // "6789" - legacy value was 123456789
#define UDP_CONNECT_REPLY 0x39383736 // "9876" - legacy value was 987654321
#define LEGACY_UDP_CONNECT_REPLY 987654321 // Old servers may still reply with the legacy value
+#endif
/* In Reverse mode, maximum number of packets to wait for "accept" response - to handle out of order packets */
#define MAX_REVERSE_OUT_OF_ORDER_PACKETS 2
diff --git a/src/iperf3.1 b/src/iperf3.1
index 344a762..f8eff48 100644
--- a/src/iperf3.1
+++ b/src/iperf3.1
@@ -1,4 +1,4 @@
-.TH IPERF3 1 "November 2023" ESnet "User Manuals"
+.TH IPERF3 1 "May 2024" ESnet "User Manuals"
.SH NAME
iperf3 \- perform network throughput tests
.SH SYNOPSIS
@@ -96,9 +96,11 @@ test by specifying the --get-server-output flag.
Either the client or the server can produce its output in a JSON
structure, useful for integration with other programs, by passing it
the -J flag.
-Because the contents of the JSON structure are only completely known
+Normally the contents of the JSON structure are only competely known
after the test has finished, no JSON output will be emitted until the
end of the test.
+By enabling line-delimited JSON multiple objects will be emitted to
+provide a real-time parsable JSON output.
.PP
iperf3 has a (overly) large set of command-line options that can be
used to set the parameters of a test.
@@ -157,6 +159,9 @@ give more detailed output
.BR -J ", " --json " "
output in JSON format
.TP
+.BR --json-stream " "
+output in line-delimited JSON format
+.TP
.BR --logfile " \fIfile\fR"
send output to a log file.
.TP
@@ -178,7 +183,7 @@ follow the \fB--timestamps\fR option with no whitespace intervening.
.BR --rcv-timeout " \fI#\fR"
set idle timeout for receiving data during active tests. The receiver
will halt a test if no data is received from the sender for this
-number of ms (default to 12000 ms, or 2 minutes).
+number of ms (default to 120000 ms, or 2 minutes).
.TP
.BR --snd-timeout " \fI#\fR"
set timeout for unacknowledged TCP data (on both test and control
@@ -188,6 +193,15 @@ parameter is specified in ms, and defaults to the system settings.
This functionality depends on the TCP_USER_TIMEOUT socket option, and
will not work on systems that do not support it.
.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_api.c b/src/iperf_api.c
index eb23403..7fb741e 100644
--- a/src/iperf_api.c
+++ b/src/iperf_api.c
@@ -1,5 +1,5 @@
/*
- * iperf, Copyright (c) 2014-2022, The Regents of the University of
+ * iperf, Copyright (c) 2014-2024, 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.
@@ -46,9 +46,7 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
-#ifdef HAVE_STDINT_H
#include <stdint.h>
-#endif
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/mman.h>
@@ -102,6 +100,7 @@ static int diskfile_recv(struct iperf_stream *sp);
static int JSON_write(int fd, cJSON *json);
static void print_interval_results(struct iperf_test *test, struct iperf_stream *sp, cJSON *json_interval_streams);
static cJSON *JSON_read(int fd);
+static int JSONStream_Output(struct iperf_test *test, const char* event_name, cJSON* obj);
/*************************** Print usage functions ****************************/
@@ -327,6 +326,12 @@ iperf_get_test_json_output_string(struct iperf_test *ipt)
}
int
+iperf_get_test_json_stream(struct iperf_test *ipt)
+{
+ return ipt->json_stream;
+}
+
+int
iperf_get_test_zerocopy(struct iperf_test *ipt)
{
return ipt->zerocopy;
@@ -682,6 +687,12 @@ iperf_set_test_json_output(struct iperf_test *ipt, int json_output)
ipt->json_output = json_output;
}
+void
+iperf_set_test_json_stream(struct iperf_test *ipt, int json_stream)
+{
+ ipt->json_stream = json_stream;
+}
+
int
iperf_has_zerocopy( void )
{
@@ -881,7 +892,7 @@ void
iperf_on_test_start(struct iperf_test *test)
{
if (test->json_output) {
- cJSON_AddItemToObject(test->json_start, "test_start", iperf_json_printf("protocol: %s num_streams: %d blksize: %d omit: %d duration: %d bytes: %d blocks: %d reverse: %d tos: %d target_bitrate: %d bidir: %d fqrate: %d", test->protocol->name, (int64_t) test->num_streams, (int64_t) test->settings->blksize, (int64_t) test->omit, (int64_t) test->duration, (int64_t) test->settings->bytes, (int64_t) test->settings->blocks, test->reverse?(int64_t)1:(int64_t)0, (int64_t) test->settings->tos, (int64_t) test->settings->rate, (int64_t) test->bidirectional, (uint64_t) test->settings->fqrate));
+ cJSON_AddItemToObject(test->json_start, "test_start", iperf_json_printf("protocol: %s num_streams: %d blksize: %d omit: %d duration: %d bytes: %d blocks: %d reverse: %d tos: %d target_bitrate: %d bidir: %d fqrate: %d interval: %f", test->protocol->name, (int64_t) test->num_streams, (int64_t) test->settings->blksize, (int64_t) test->omit, (int64_t) test->duration, (int64_t) test->settings->bytes, (int64_t) test->settings->blocks, test->reverse?(int64_t)1:(int64_t)0, (int64_t) test->settings->tos, (int64_t) test->settings->rate, (int64_t) test->bidirectional, (uint64_t) test->settings->fqrate, test->stats_interval));
} else {
if (test->verbose) {
if (test->settings->bytes)
@@ -892,8 +903,12 @@ iperf_on_test_start(struct iperf_test *test)
iperf_printf(test, test_start_time, test->protocol->name, test->num_streams, test->settings->blksize, test->omit, test->duration, test->settings->tos);
}
}
+ if (test->json_stream) {
+ JSONStream_Output(test, "start", test->json_start);
+ }
}
+
/* This converts an IPv6 string address from IPv4-mapped format into regular
** old IPv4 format, which is easier on the eyes of network veterans.
**
@@ -1058,6 +1073,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
{"one-off", no_argument, NULL, '1'},
{"verbose", no_argument, NULL, 'V'},
{"json", no_argument, NULL, 'J'},
+ {"json-stream", no_argument, NULL, OPT_JSON_STREAM},
{"version", no_argument, NULL, 'v'},
{"server", no_argument, NULL, 's'},
{"client", required_argument, NULL, 'c'},
@@ -1121,6 +1137,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
{"rsa-private-key-path", required_argument, NULL, OPT_SERVER_RSA_PRIVATE_KEY},
{"authorized-users-path", required_argument, NULL, OPT_SERVER_AUTHORIZED_USERS},
{"time-skew-threshold", required_argument, NULL, OPT_SERVER_SKEW_THRESHOLD},
+ {"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},
@@ -1207,6 +1224,10 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
case 'J':
test->json_output = 1;
break;
+ case OPT_JSON_STREAM:
+ test->json_output = 1;
+ test->json_stream = 1;
+ break;
case 'v':
printf("%s (cJSON %s)\n%s\n%s\n", version, cJSON_Version(), get_system_info(),
get_optional_features());
@@ -1293,7 +1314,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
break;
case 't':
test->duration = atoi(optarg);
- if (test->duration > MAX_TIME) {
+ if (test->duration > MAX_TIME || test->duration < 0) {
i_errno = IEDURATION;
return -1;
}
@@ -1610,6 +1631,9 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
return -1;
}
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);
@@ -2050,7 +2074,7 @@ int test_is_authorized(struct iperf_test *test){
if (test->settings->authtoken){
char *username = NULL, *password = NULL;
time_t ts;
- int rc = decode_auth_setting(test->debug, test->settings->authtoken, test->server_rsa_private_key, &username, &password, &ts);
+ int rc = decode_auth_setting(test->debug, test->settings->authtoken, test->server_rsa_private_key, &username, &password, &ts, test->use_pkcs1_padding);
if (rc) {
return -1;
}
@@ -2235,7 +2259,7 @@ send_parameters(struct iperf_test *test)
#if defined(HAVE_SSL)
/* Send authentication parameters */
if (test->settings->client_username && test->settings->client_password && test->settings->client_rsa_pubkey){
- int rc = encode_auth_setting(test->settings->client_username, test->settings->client_password, test->settings->client_rsa_pubkey, &test->settings->authtoken);
+ int rc = encode_auth_setting(test->settings->client_username, test->settings->client_password, test->settings->client_rsa_pubkey, &test->settings->authtoken, test->use_pkcs1_padding);
if (rc) {
cJSON_Delete(j);
@@ -2738,6 +2762,35 @@ JSON_read(int fd)
/*************************************************************/
/**
+ * JSONStream_Output - outputs an obj as event without distrubing it
+ */
+
+static int
+JSONStream_Output(struct iperf_test * test, const char * event_name, cJSON * obj)
+{
+ cJSON *event = cJSON_CreateObject();
+ if (!event)
+ return -1;
+ cJSON_AddStringToObject(event, "event", event_name);
+ cJSON_AddItemReferenceToObject(event, "data", obj);
+ char *str = cJSON_PrintUnformatted(event);
+ if (str == NULL)
+ return -1;
+ if (pthread_mutex_lock(&(test->print_mutex)) != 0) {
+ perror("iperf_json_finish: pthread_mutex_lock");
+ }
+ fprintf(test->outfile, "%s\n", str);
+ if (pthread_mutex_unlock(&(test->print_mutex)) != 0) {
+ perror("iperf_json_finish: pthread_mutex_unlock");
+ }
+ iflush(test);
+ cJSON_free(str);
+ cJSON_Delete(event);
+ return 0;
+}
+
+/*************************************************************/
+/**
* add_to_interval_list -- adds new interval to the interval_list
*/
@@ -3209,6 +3262,7 @@ iperf_reset_test(struct iperf_test *test)
test->settings->socket_bufsize = 0;
test->settings->blksize = DEFAULT_TCP_BLKSIZE;
test->settings->rate = 0;
+ test->settings->fqrate = 0;
test->settings->burst = 0;
test->settings->mss = 0;
test->settings->tos = 0;
@@ -3400,6 +3454,7 @@ iperf_print_intermediate(struct iperf_test *test)
int lower_mode, upper_mode;
int current_mode;
+ int discard_json;
/*
* Due to timing oddities, there can be cases, especially on the
@@ -3445,11 +3500,20 @@ iperf_print_intermediate(struct iperf_test *test)
return;
}
+ /*
+ * When we use streamed json, we don't actually need to keep the interval
+ * results around unless we're the server and the client requested the server output.
+ *
+ * This avoids unneeded memory build up for long sessions.
+ */
+ discard_json = test->json_stream == 1 && !(test->role == 's' && test->get_server_output);
+
if (test->json_output) {
json_interval = cJSON_CreateObject();
if (json_interval == NULL)
return;
- cJSON_AddItemToArray(test->json_intervals, json_interval);
+ if (!discard_json)
+ cJSON_AddItemToArray(test->json_intervals, json_interval);
json_interval_streams = cJSON_CreateArray();
if (json_interval_streams == NULL)
return;
@@ -3600,6 +3664,11 @@ iperf_print_intermediate(struct iperf_test *test)
}
}
}
+
+ if (test->json_stream)
+ JSONStream_Output(test, "interval", json_interval);
+ if (discard_json)
+ cJSON_Delete(json_interval);
}
/**
@@ -4710,7 +4779,15 @@ iperf_create_pidfile(struct iperf_test *test)
if (pid > 0) {
/* See if the process exists. */
+#if (defined(__vxworks)) || (defined(__VXWORKS__))
+#if (defined(_WRS_KERNEL)) && (defined(_WRS_CONFIG_LP64))
+ if (kill((_Vx_TASK_ID)pid, 0) == 0) {
+#else
+ if (kill(pid, 0) == 0) {
+#endif // _WRS_KERNEL and _WRS_CONFIG_LP64
+#else
if (kill(pid, 0) == 0) {
+#endif // __vxworks or __VXWORKS__
/*
* Make sure not to try to delete existing PID file by
* scribbling over the pathname we'd use to refer to it.
@@ -4798,31 +4875,51 @@ iperf_json_finish(struct iperf_test *test)
if (test->server_output_text) {
cJSON_AddStringToObject(test->json_top, "server_output_text", test->server_output_text);
}
- // Get ASCII rendering of JSON structure. Then make our
- // own copy of it and return the storage that cJSON allocated
- // on our behalf. We keep our own copy around.
- char *str = cJSON_Print(test->json_top);
- if (str == NULL) {
- return -1;
- }
- test->json_output_string = strdup(str);
- cJSON_free(str);
- if (test->json_output_string == NULL) {
- return -1;
- }
- if (pthread_mutex_lock(&(test->print_mutex)) != 0) {
- perror("iperf_json_finish: pthread_mutex_lock");
+ /* --json-stream, so we print various individual objects */
+ if (test->json_stream) {
+ cJSON *error = cJSON_GetObjectItem(test->json_top, "error");
+ if (error) {
+ JSONStream_Output(test, "error", error);
+ }
+ if (test->json_server_output) {
+ JSONStream_Output(test, "server_output_json", test->json_server_output);
+ }
+ if (test->server_output_text) {
+ JSONStream_Output(test, "server_output_text", cJSON_CreateString(test->server_output_text));
+ }
+ JSONStream_Output(test, "end", test->json_end);
}
- fprintf(test->outfile, "%s\n", test->json_output_string);
- if (pthread_mutex_unlock(&(test->print_mutex)) != 0) {
- perror("iperf_json_finish: pthread_mutex_unlock");
+ /* Original --json output, single monolithic object */
+ else {
+ /*
+ * Get ASCII rendering of JSON structure. Then make our
+ * own copy of it and return the storage that cJSON
+ * allocated on our behalf. We keep our own copy
+ * around.
+ */
+ char *str = cJSON_Print(test->json_top);
+ if (str == NULL) {
+ return -1;
+ }
+ test->json_output_string = strdup(str);
+ cJSON_free(str);
+ if (test->json_output_string == NULL) {
+ return -1;
+ }
+ if (pthread_mutex_lock(&(test->print_mutex)) != 0) {
+ perror("iperf_json_finish: pthread_mutex_lock");
+ }
+ fprintf(test->outfile, "%s\n", test->json_output_string);
+ if (pthread_mutex_unlock(&(test->print_mutex)) != 0) {
+ perror("iperf_json_finish: pthread_mutex_unlock");
+ }
+ iflush(test);
}
- iflush(test);
cJSON_Delete(test->json_top);
- test->json_top = NULL;
}
- test->json_start = test->json_connected = test->json_intervals = test->json_server_output = test->json_end = NULL;
+
+ test->json_top = test->json_start = test->json_connected = test->json_intervals = test->json_server_output = test->json_end = NULL;
return 0;
}
diff --git a/src/iperf_api.h b/src/iperf_api.h
index 9e70d44..1313142 100644
--- a/src/iperf_api.h
+++ b/src/iperf_api.h
@@ -31,9 +31,7 @@
#include <sys/time.h>
#include <setjmp.h>
#include <stdio.h>
-#ifdef HAVE_STDINT_H
#include <stdint.h>
-#endif
#ifdef __cplusplus
extern "C" { /* open extern "C" */
#endif
@@ -100,7 +98,9 @@ typedef atomic_uint_fast64_t atomic_iperf_size_t;
#define OPT_IDLE_TIMEOUT 25
#define OPT_DONT_FRAGMENT 26
#define OPT_RCV_TIMEOUT 27
-#define OPT_SND_TIMEOUT 28
+#define OPT_JSON_STREAM 28
+#define OPT_SND_TIMEOUT 29
+#define OPT_USE_PKCS1_PADDING 30
/* states */
#define TEST_START 1
@@ -151,6 +151,7 @@ char* iperf_get_test_template( struct iperf_test* ipt );
int iperf_get_test_protocol_id( struct iperf_test* ipt );
int iperf_get_test_json_output( struct iperf_test* ipt );
char* iperf_get_test_json_output_string ( struct iperf_test* ipt );
+int iperf_get_test_json_stream( struct iperf_test* ipt );
int iperf_get_test_zerocopy( struct iperf_test* ipt );
int iperf_get_test_get_server_output( struct iperf_test* ipt );
char iperf_get_test_unit_format(struct iperf_test *ipt);
@@ -195,6 +196,7 @@ void iperf_set_test_server_hostname( struct iperf_test* ipt, const char* server_
void iperf_set_test_template( struct iperf_test *ipt, const char *tmp_template );
void iperf_set_test_reverse( struct iperf_test* ipt, int reverse );
void iperf_set_test_json_output( struct iperf_test* ipt, int json_output );
+void iperf_set_test_json_stream( struct iperf_test* ipt, int json_stream );
int iperf_has_zerocopy( void );
void iperf_set_test_zerocopy( struct iperf_test* ipt, int zerocopy );
void iperf_set_test_get_server_output( struct iperf_test* ipt, int get_server_output );
diff --git a/src/iperf_auth.c b/src/iperf_auth.c
index c89bde7..72e85fc 100644
--- a/src/iperf_auth.c
+++ b/src/iperf_auth.c
@@ -230,7 +230,7 @@ int test_load_private_key_from_file(const char *file){
return 0;
}
-int encrypt_rsa_message(const char *plaintext, EVP_PKEY *public_key, unsigned char **encryptedtext) {
+int encrypt_rsa_message(const char *plaintext, EVP_PKEY *public_key, unsigned char **encryptedtext, int use_pkcs1_padding) {
#if OPENSSL_VERSION_MAJOR >= 3
EVP_PKEY_CTX *ctx;
#else
@@ -257,12 +257,19 @@ int encrypt_rsa_message(const char *plaintext, EVP_PKEY *public_key, unsigned ch
BIO *bioBuff = BIO_new_mem_buf((void*)plaintext, (int)strlen(plaintext));
rsa_buffer_len = BIO_read(bioBuff, rsa_buffer, keysize * 2);
+
+ int padding = RSA_PKCS1_OAEP_PADDING;
+ if (use_pkcs1_padding){
+ padding = RSA_PKCS1_PADDING;
+ }
#if OPENSSL_VERSION_MAJOR >= 3
EVP_PKEY_encrypt_init(ctx);
+ EVP_PKEY_CTX_set_rsa_padding(ctx, padding);
+
EVP_PKEY_encrypt(ctx, *encryptedtext, &encryptedtext_len, rsa_buffer, rsa_buffer_len);
EVP_PKEY_CTX_free(ctx);
#else
- encryptedtext_len = RSA_public_encrypt(rsa_buffer_len, rsa_buffer, *encryptedtext, rsa, RSA_PKCS1_PADDING);
+ encryptedtext_len = RSA_public_encrypt(rsa_buffer_len, rsa_buffer, *encryptedtext, rsa, padding);
RSA_free(rsa);
#endif
@@ -280,7 +287,7 @@ int encrypt_rsa_message(const char *plaintext, EVP_PKEY *public_key, unsigned ch
return 0;
}
-int decrypt_rsa_message(const unsigned char *encryptedtext, const int encryptedtext_len, EVP_PKEY *private_key, unsigned char **plaintext) {
+int decrypt_rsa_message(const unsigned char *encryptedtext, const int encryptedtext_len, EVP_PKEY *private_key, unsigned char **plaintext, int use_pkcs1_padding) {
#if OPENSSL_VERSION_MAJOR >= 3
EVP_PKEY_CTX *ctx;
#else
@@ -307,21 +314,31 @@ 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);
+
+ int padding = RSA_PKCS1_OAEP_PADDING;
+ if (use_pkcs1_padding){
+ padding = RSA_PKCS1_PADDING;
+ }
#if OPENSSL_VERSION_MAJOR >= 3
plaintext_len = keysize;
EVP_PKEY_decrypt_init(ctx);
+ int ret = EVP_PKEY_CTX_set_rsa_padding(ctx, padding);
+ if (ret < 0){
+ goto errreturn;
+ }
EVP_PKEY_decrypt(ctx, *plaintext, &plaintext_len, rsa_buffer, rsa_buffer_len);
EVP_PKEY_CTX_free(ctx);
#else
- plaintext_len = RSA_private_decrypt(rsa_buffer_len, rsa_buffer, *plaintext, rsa, RSA_PKCS1_PADDING);
+ plaintext_len = RSA_private_decrypt(rsa_buffer_len, rsa_buffer, *plaintext, rsa, padding);
RSA_free(rsa);
#endif
OPENSSL_free(rsa_buffer);
BIO_free(bioBuff);
- if (plaintext_len <= 0) {
- goto errreturn;
+ /* Treat a decryption error as an empty string. */
+ if (plaintext_len < 0) {
+ plaintext_len = 0;
}
return plaintext_len;
@@ -331,7 +348,7 @@ int decrypt_rsa_message(const unsigned char *encryptedtext, const int encryptedt
return 0;
}
-int encode_auth_setting(const char *username, const char *password, EVP_PKEY *public_key, char **authtoken){
+int encode_auth_setting(const char *username, const char *password, EVP_PKEY *public_key, char **authtoken, int use_pkcs1_padding){
time_t t = time(NULL);
time_t utc_seconds = mktime(localtime(&t));
@@ -348,7 +365,7 @@ int encode_auth_setting(const char *username, const char *password, EVP_PKEY *pu
unsigned char *encrypted = NULL;
int encrypted_len;
- encrypted_len = encrypt_rsa_message(text, public_key, &encrypted);
+ encrypted_len = encrypt_rsa_message(text, public_key, &encrypted, use_pkcs1_padding);
free(text);
if (encrypted_len < 0) {
return -1;
@@ -359,7 +376,7 @@ int encode_auth_setting(const char *username, const char *password, EVP_PKEY *pu
return (0); //success
}
-int decode_auth_setting(int enable_debug, const char *authtoken, EVP_PKEY *private_key, char **username, char **password, time_t *ts){
+int decode_auth_setting(int enable_debug, const char *authtoken, EVP_PKEY *private_key, char **username, char **password, time_t *ts, int use_pkcs1_padding){
unsigned char *encrypted_b64 = NULL;
size_t encrypted_len_b64;
int64_t utc_seconds;
@@ -367,7 +384,7 @@ int decode_auth_setting(int enable_debug, const char *authtoken, EVP_PKEY *priva
unsigned char *plaintext = NULL;
int plaintext_len;
- plaintext_len = decrypt_rsa_message(encrypted_b64, encrypted_len_b64, private_key, &plaintext);
+ plaintext_len = decrypt_rsa_message(encrypted_b64, encrypted_len_b64, private_key, &plaintext, use_pkcs1_padding);
free(encrypted_b64);
if (plaintext_len < 0) {
return -1;
diff --git a/src/iperf_auth.h b/src/iperf_auth.h
index ffadbf3..eedd45a 100644
--- a/src/iperf_auth.h
+++ b/src/iperf_auth.h
@@ -35,7 +35,7 @@ EVP_PKEY *load_pubkey_from_file(const char *file);
EVP_PKEY *load_pubkey_from_base64(const char *buffer);
EVP_PKEY *load_privkey_from_file(const char *file);
EVP_PKEY *load_privkey_from_base64(const char *buffer);
-int encode_auth_setting(const char *username, const char *password, EVP_PKEY *public_key, char **authtoken);
-int decode_auth_setting(int enable_debug, const char *authtoken, EVP_PKEY *private_key, char **username, char **password, time_t *ts);
+int encode_auth_setting(const char *username, const char *password, EVP_PKEY *public_key, char **authtoken, int use_pkcs1_padding);
+int decode_auth_setting(int enable_debug, const char *authtoken, EVP_PKEY *private_key, 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, int skew_threshold);
ssize_t iperf_getpass (char **lineptr, size_t *n, FILE *stream);
diff --git a/src/iperf_client_api.c b/src/iperf_client_api.c
index 5b33369..7ad4c93 100644
--- a/src/iperf_client_api.c
+++ b/src/iperf_client_api.c
@@ -614,7 +614,19 @@ iperf_run_client(struct iperf_test * test)
timeout = &used_timeout;
}
+#if (defined(__vxworks)) || (defined(__VXWORKS__))
+ if (timeout != NULL && timeout->tv_sec == 0 && timeout->tv_usec == 0) {
+ taskDelay (1);
+ }
+
+ result = select(test->max_fd + 1,
+ &read_set,
+ (test->state == TEST_RUNNING && !test->reverse) ? &write_set : NULL,
+ NULL,
+ timeout);
+#else
result = select(test->max_fd + 1, &read_set, &write_set, NULL, timeout);
+#endif // __vxworks or __VXWORKS__
if (result < 0 && errno != EINTR) {
i_errno = IESELECT;
goto cleanup_and_fail;
diff --git a/src/iperf_config.h.in b/src/iperf_config.h.in
index bb8853f..c85b195 100644
--- a/src/iperf_config.h.in
+++ b/src/iperf_config.h.in
@@ -1,15 +1,15 @@
/* src/iperf_config.h.in. Generated from configure.ac by autoheader. */
-/* Define to 1 if you have the `clock_gettime' function. */
+/* Define to 1 if you have the 'clock_gettime' function. */
#undef HAVE_CLOCK_GETTIME
-/* Define to 1 if you have the `cpuset_setaffinity' function. */
+/* Define to 1 if you have the 'cpuset_setaffinity' function. */
#undef HAVE_CPUSET_SETAFFINITY
/* Have CPU affinity support. */
#undef HAVE_CPU_AFFINITY
-/* Define to 1 if you have the `daemon' function. */
+/* Define to 1 if you have the 'daemon' function. */
#undef HAVE_DAEMON
/* Define to 1 if you have the <dlfcn.h> header file. */
@@ -24,7 +24,7 @@
/* Have IPv6 flowlabel support. */
#undef HAVE_FLOWLABEL
-/* Define to 1 if you have the `getline' function. */
+/* Define to 1 if you have the 'getline' function. */
#undef HAVE_GETLINE
/* Define to 1 if you have the <inttypes.h> header file. */
@@ -54,16 +54,16 @@
/* Have PTHREAD_PRIO_INHERIT. */
#undef HAVE_PTHREAD_PRIO_INHERIT
-/* Define to 1 if you have the `sched_setaffinity' function. */
+/* Define to 1 if you have the 'sched_setaffinity' function. */
#undef HAVE_SCHED_SETAFFINITY
/* Have SCTP support. */
#undef HAVE_SCTP_H
-/* Define to 1 if you have the `sendfile' function. */
+/* Define to 1 if you have the 'sendfile' function. */
#undef HAVE_SENDFILE
-/* Define to 1 if you have the `SetProcessAffinityMask' function. */
+/* Define to 1 if you have the 'SetProcessAffinityMask' function. */
#undef HAVE_SETPROCESSAFFINITYMASK
/* Have SO_BINDTODEVICE sockopt. */
@@ -93,7 +93,7 @@
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
-/* Define to 1 if the system has the type `struct sctp_assoc_value'. */
+/* Define to 1 if the system has the type 'struct sctp_assoc_value'. */
#undef HAVE_STRUCT_SCTP_ASSOC_VALUE
/* Define to 1 if you have the <sys/endian.h> header file. */
@@ -148,7 +148,7 @@
your system. */
#undef PTHREAD_CREATE_JOINABLE
-/* Define to 1 if all of the C90 standard headers exist (not just the ones
+/* Define to 1 if all of the C89 standard headers exist (not just the ones
required in a freestanding environment). This macro is provided for
backward compatibility; new code need not use it. */
#undef STDC_HEADERS
@@ -156,5 +156,5 @@
/* Version number of package */
#undef VERSION
-/* Define to empty if `const' does not conform to ANSI C. */
+/* Define to empty if 'const' does not conform to ANSI C. */
#undef const
diff --git a/src/iperf_error.c b/src/iperf_error.c
index 6426554..0fedf31 100644
--- a/src/iperf_error.c
+++ b/src/iperf_error.c
@@ -47,10 +47,6 @@ iperf_err(struct iperf_test *test, const char *format, ...)
struct tm *ltm = NULL;
char *ct = NULL;
- if (pthread_mutex_lock(&(test->print_mutex)) != 0) {
- perror("iperf_err: pthread_mutex_lock");
- }
-
/* Timestamp if requested */
if (test != NULL && test->timestamps) {
time(&now);
@@ -64,6 +60,10 @@ iperf_err(struct iperf_test *test, const char *format, ...)
if (test != NULL && test->json_output && test->json_top != NULL)
cJSON_AddStringToObject(test->json_top, "error", str);
else {
+ if (pthread_mutex_lock(&(test->print_mutex)) != 0) {
+ perror("iperf_err: pthread_mutex_lock");
+ }
+
if (test && test->outfile && test->outfile != stdout) {
if (ct) {
fprintf(test->outfile, "%s", ct);
@@ -76,12 +76,13 @@ iperf_err(struct iperf_test *test, const char *format, ...)
}
fprintf(stderr, "iperf3: %s\n", str);
}
- }
- va_end(argp);
- if (pthread_mutex_unlock(&(test->print_mutex)) != 0) {
- perror("iperf_err: pthread_mutex_unlock");
+ if (pthread_mutex_unlock(&(test->print_mutex)) != 0) {
+ perror("iperf_err: pthread_mutex_unlock");
+ }
+
}
+ va_end(argp);
}
/* Do a printf to stderr or log file as appropriate, then exit. */
@@ -94,10 +95,6 @@ iperf_errexit(struct iperf_test *test, const char *format, ...)
struct tm *ltm = NULL;
char *ct = NULL;
- if (pthread_mutex_lock(&(test->print_mutex)) != 0) {
- perror("iperf_errexit: pthread_mutex_lock");
- }
-
/* Timestamp if requested */
if (test != NULL && test->timestamps) {
time(&now);
@@ -113,7 +110,11 @@ iperf_errexit(struct iperf_test *test, const char *format, ...)
cJSON_AddStringToObject(test->json_top, "error", str);
}
iperf_json_finish(test);
- } else
+ } else {
+ if (pthread_mutex_lock(&(test->print_mutex)) != 0) {
+ perror("iperf_errexit: pthread_mutex_lock");
+ }
+
if (test && test->outfile && test->outfile != stdout) {
if (ct) {
fprintf(test->outfile, "%s", ct);
@@ -127,8 +128,9 @@ iperf_errexit(struct iperf_test *test, const char *format, ...)
fprintf(stderr, "iperf3: %s\n", str);
}
- if (pthread_mutex_unlock(&(test->print_mutex)) != 0) {
- perror("iperf_errexit: pthread_mutex_unlock");
+ if (pthread_mutex_unlock(&(test->print_mutex)) != 0) {
+ perror("iperf_errexit: pthread_mutex_unlock");
+ }
}
va_end(argp);
@@ -166,7 +168,7 @@ iperf_strerror(int int_errno)
snprintf(errstr, len, "some option you are trying to set is client only");
break;
case IEDURATION:
- snprintf(errstr, len, "test duration too long (maximum = %d seconds)", MAX_TIME);
+ snprintf(errstr, len, "test duration valid values are 0 to %d seconds", MAX_TIME);
break;
case IENUMSTREAMS:
snprintf(errstr, len, "number of parallel streams too large (maximum = %d)", MAX_STREAMS);
diff --git a/src/iperf_locale.c b/src/iperf_locale.c
index 838086e..9d94e02 100644
--- a/src/iperf_locale.c
+++ b/src/iperf_locale.c
@@ -81,17 +81,7 @@
#include "version.h"
-#if defined(HAVE_INTTYPES_H)
-# include <inttypes.h>
-#else
-# ifndef PRIu64
-# if sizeof(long) == 8
-# define PRIu64 "lu"
-# else
-# define PRIu64 "llu"
-# endif
-# endif
-#endif
+#include <inttypes.h>
#ifdef __cplusplus
extern "C"
@@ -115,7 +105,8 @@ const char usage_longstr[] = "Usage: iperf3 [-s|-c host] [options]\n"
" -I, --pidfile file write PID file\n"
" -F, --file name xmit/recv the specified file\n"
#if defined(HAVE_CPU_AFFINITY)
- " -A, --affinity n/n,m set CPU affinity\n"
+ " -A, --affinity n[,m] set CPU affinity core number to n (the core the process will use)\n"
+ " (optional Client only m - the Server's core number for this test)\n"
#endif /* HAVE_CPU_AFFINITY */
#if defined(HAVE_SO_BINDTODEVICE)
" -B, --bind <host>[%%<dev>] bind to the interface associated with the address <host>\n"
@@ -126,6 +117,7 @@ const char usage_longstr[] = "Usage: iperf3 [-s|-c host] [options]\n"
#endif /* HAVE_SO_BINDTODEVICE */
" -V, --verbose more detailed output\n"
" -J, --json output in JSON format\n"
+ " --json-stream output in line-delimited JSON format\n"
" --logfile f send output to a log file\n"
" --forceflush force flushing output at every interval\n"
" --timestamps<=format> emit a timestamp at the start of each output line\n"
@@ -156,6 +148,7 @@ const char usage_longstr[] = "Usage: iperf3 [-s|-c host] [options]\n"
" credentials\n"
" --time-skew-threshold time skew threshold (in seconds) between the server\n"
" and client during the authentication process\n"
+ " --use-pkcs1-padding use pkcs1 padding at your own risk\n"
#endif //HAVE_SSL
"Client specific:\n"
" -c, --client <host>[%%<dev>] run in client mode, connecting to <host>\n"
@@ -394,13 +387,13 @@ const char report_bw_retrans_cwnd_format[] =
"[%3d]%s %6.2f-%-6.2f sec %ss %ss/sec %3u %ss %s\n";
const char report_bw_udp_format[] =
-"[%3d]%s %6.2f-%-6.2f sec %ss %ss/sec %5.3f ms %" PRIu64 "/%" PRIu64 " (%.2g%%) %s\n";
+"[%3d]%s %6.2f-%-6.2f sec %ss %ss/sec %5.3f ms %" PRId64 "/%" PRId64 " (%.2g%%) %s\n";
const char report_bw_udp_format_no_omitted_error[] =
-"[%3d]%s %6.2f-%-6.2f sec %ss %ss/sec %5.3f ms Unknown/%" PRIu64 " %s\n";
+"[%3d]%s %6.2f-%-6.2f sec %ss %ss/sec %5.3f ms Unknown/%" PRId64 " %s\n";
const char report_bw_udp_sender_format[] =
-"[%3d]%s %6.2f-%-6.2f sec %ss %ss/sec %s %" PRIu64 " %s\n";
+"[%3d]%s %6.2f-%-6.2f sec %ss %ss/sec %s %" PRId64 " %s\n";
const char report_summary[] =
"Test Complete. Summary Results:\n";
@@ -412,10 +405,10 @@ const char report_sum_bw_retrans_format[] =
"[SUM]%s %6.2f-%-6.2f sec %ss %ss/sec %3d %s\n";
const char report_sum_bw_udp_format[] =
-"[SUM]%s %6.2f-%-6.2f sec %ss %ss/sec %5.3f ms %" PRIu64 "/%" PRIu64 " (%.2g%%) %s\n";
+"[SUM]%s %6.2f-%-6.2f sec %ss %ss/sec %5.3f ms %" PRId64 "/%" PRId64 " (%.2g%%) %s\n";
const char report_sum_bw_udp_sender_format[] =
-"[SUM]%s %6.2f-%-6.2f sec %ss %ss/sec %s %" PRIu64 " %s\n";
+"[SUM]%s %6.2f-%-6.2f sec %ss %ss/sec %s %" PRId64 " %s\n";
const char report_omitted[] = "(omitted)";
diff --git a/src/iperf_pthread.c b/src/iperf_pthread.c
new file mode 100644
index 0000000..ea4918b
--- /dev/null
+++ b/src/iperf_pthread.c
@@ -0,0 +1,40 @@
+#include "iperf_config.h"
+
+#if defined(HAVE_PTHREAD) && defined(__ANDROID__)
+
+/* Workaround for `pthread_cancel()` in Android, using `pthread_kill()` instead,
+ * as Android NDK does not support `pthread_cancel()`.
+ */
+
+#include <signal.h>
+#include "iperf_pthread.h"
+
+int pthread_setcanceltype(int type, int *oldtype) { return 0; }
+int pthread_setcancelstate(int state, int *oldstate) { return 0; }
+int pthread_cancel(pthread_t thread_id) {
+ int status;
+ if ((status = iperf_set_thread_exit_handler()) == 0) {
+ status = pthread_kill(thread_id, SIGUSR1);
+ }
+ return status;
+}
+
+void iperf_thread_exit_handler(int sig)
+{
+ pthread_exit(0);
+}
+
+int iperf_set_thread_exit_handler() {
+ int rc;
+ struct sigaction actions;
+
+ memset(&actions, 0, sizeof(actions));
+ sigemptyset(&actions.sa_mask);
+ actions.sa_flags = 0;
+ actions.sa_handler = iperf_thread_exit_handler;
+
+ rc = sigaction(SIGUSR1, &actions, NULL);
+ return rc;
+}
+
+#endif // defined(HAVE_PTHREAD) && defined(__ANDROID__)
diff --git a/src/iperf_pthread.h b/src/iperf_pthread.h
new file mode 100644
index 0000000..44828d6
--- /dev/null
+++ b/src/iperf_pthread.h
@@ -0,0 +1,21 @@
+#include "iperf_config.h"
+
+#if defined(HAVE_PTHREAD)
+
+#include <pthread.h>
+
+#if defined(__ANDROID__)
+
+/* Adding missing `pthread` related definitions in Android.
+ */
+
+#define PTHREAD_CANCEL_ASYNCHRONOUS 0
+#define PTHREAD_CANCEL_ENABLE NULL
+
+int pthread_setcanceltype(int type, int *oldtype);
+int pthread_setcancelstate(int state, int *oldstate);
+int pthread_cancel(pthread_t thread_id);
+
+#endif // defined(__ANDROID__)
+
+#endif // defined(HAVE_PTHREAD) \ No newline at end of file
diff --git a/src/iperf_server_api.c b/src/iperf_server_api.c
index 77e9c35..3bd20c6 100644
--- a/src/iperf_server_api.c
+++ b/src/iperf_server_api.c
@@ -40,9 +40,7 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
-#ifdef HAVE_STDINT_H
#include <stdint.h>
-#endif
#include <sys/time.h>
#include <sys/resource.h>
#include <sched.h>
diff --git a/src/iperf_tcp.c b/src/iperf_tcp.c
index ce6a522..71c40a6 100644
--- a/src/iperf_tcp.c
+++ b/src/iperf_tcp.c
@@ -126,9 +126,26 @@ iperf_tcp_accept(struct iperf_test * test)
i_errno = IESTREAMCONNECT;
return -1;
}
+#if defined(HAVE_SO_MAX_PACING_RATE)
+ /* If fq socket pacing is specified, enable it. */
+
+ if (test->settings->fqrate) {
+ /* Convert bits per second to bytes per second */
+ unsigned int fqrate = test->settings->fqrate / 8;
+ if (fqrate > 0) {
+ if (test->debug) {
+ printf("Setting fair-queue socket pacing to %u\n", fqrate);
+ }
+ if (setsockopt(s, SOL_SOCKET, SO_MAX_PACING_RATE, &fqrate, sizeof(fqrate)) < 0) {
+ warning("Unable to set socket pacing");
+ }
+ }
+ }
+#endif /* HAVE_SO_MAX_PACING_RATE */
if (Nread(s, cookie, COOKIE_SIZE, Ptcp) < 0) {
i_errno = IERECVCOOKIE;
+ close(s);
return -1;
}
@@ -240,21 +257,6 @@ iperf_tcp_listen(struct iperf_test *test)
return -1;
}
}
-#if defined(HAVE_SO_MAX_PACING_RATE)
- /* If fq socket pacing is specified, enable it. */
- if (test->settings->fqrate) {
- /* Convert bits per second to bytes per second */
- unsigned int fqrate = test->settings->fqrate / 8;
- if (fqrate > 0) {
- if (test->debug) {
- printf("Setting fair-queue socket pacing to %u\n", fqrate);
- }
- if (setsockopt(s, SOL_SOCKET, SO_MAX_PACING_RATE, &fqrate, sizeof(fqrate)) < 0) {
- warning("Unable to set socket pacing");
- }
- }
- }
-#endif /* HAVE_SO_MAX_PACING_RATE */
{
unsigned int rate = test->settings->rate / 8;
if (rate > 0) {
@@ -309,6 +311,7 @@ iperf_tcp_listen(struct iperf_test *test)
if (listen(s, INT_MAX) < 0) {
i_errno = IESTREAMLISTEN;
+ close(s);
return -1;
}
@@ -329,6 +332,7 @@ iperf_tcp_listen(struct iperf_test *test)
}
if (test->settings->socket_bufsize && test->settings->socket_bufsize > sndbuf_actual) {
i_errno = IESETBUF2;
+ close(s);
return -1;
}
@@ -346,6 +350,7 @@ iperf_tcp_listen(struct iperf_test *test)
}
if (test->settings->socket_bufsize && test->settings->socket_bufsize > rcvbuf_actual) {
i_errno = IESETBUF2;
+ close(s);
return -1;
}
diff --git a/src/iperf_udp.c b/src/iperf_udp.c
index b7aa1eb..a603236 100644
--- a/src/iperf_udp.c
+++ b/src/iperf_udp.c
@@ -34,9 +34,8 @@
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
-#ifdef HAVE_STDINT_H
#include <stdint.h>
-#endif
+#include <inttypes.h>
#include <sys/time.h>
#include <sys/select.h>
@@ -47,19 +46,6 @@
#include "timer.h"
#include "net.h"
#include "cjson.h"
-#include "portable_endian.h"
-
-#if defined(HAVE_INTTYPES_H)
-# include <inttypes.h>
-#else
-# ifndef PRIu64
-# if sizeof(long) == 8
-# define PRIu64 "lu"
-# else
-# define PRIu64 "llu"
-# endif
-# endif
-#endif
/* iperf_udp_recv
*
diff --git a/src/libiperf.3 b/src/libiperf.3
index 4b278e3..2edc954 100644
--- a/src/libiperf.3
+++ b/src/libiperf.3
@@ -32,6 +32,7 @@ Setting test parameters:
void iperf_set_test_blksize( struct iperf_test *t, int blksize );
void iperf_set_test_num_streams( struct iperf_test *t, int num_streams );
void iperf_set_test_json_output( struct iperf_test *t, int json_output );
+ void iperf_set_test_json_stream( struct iperf_test *t, int json_stream );
int iperf_has_zerocopy( void );
void iperf_set_test_zerocopy( struct iperf_test* t, int zerocopy );
void iperf_set_test_tos( struct iperf_test* t, int tos );
diff --git a/src/main.c b/src/main.c
index b179f5b..eb29f87 100644
--- a/src/main.c
+++ b/src/main.c
@@ -33,9 +33,7 @@
#include <errno.h>
#include <signal.h>
#include <unistd.h>
-#ifdef HAVE_STDINT_H
#include <stdint.h>
-#endif
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
@@ -156,7 +154,7 @@ run(struct iperf_test *test)
case 's':
if (test->daemon) {
int rc;
- rc = daemon(0, 0);
+ rc = daemon(1, 0);
if (rc < 0) {
i_errno = IEDAEMON;
iperf_errexit(test, "error - %s", iperf_strerror(i_errno));
diff --git a/src/net.c b/src/net.c
index c82caff..632ae03 100644
--- a/src/net.c
+++ b/src/net.c
@@ -145,6 +145,7 @@ create_socket(int domain, int proto, const char *local, const char *bind_dev, in
if ((gerror = getaddrinfo(server, portstr, &hints, &server_res)) != 0) {
if (local)
freeaddrinfo(local_res);
+ freeaddrinfo(server_res);
return -1;
}
diff --git a/src/portable_endian.h b/src/portable_endian.h
index c3c73ff..dbb6789 100644
--- a/src/portable_endian.h
+++ b/src/portable_endian.h
@@ -131,7 +131,9 @@
// the truth because we use the homebrew htonll, et al. implementations
// that were originally the sole implementation of this functionality
// in iperf 3.0.
+#if (!defined(__vxworks)) && (!defined(__VXWORKS__))
# warning platform not supported
+#endif
# include <endian.h>
#if BYTE_ORDER == BIG_ENDIAN
#define HTONLL(n) (n)
diff --git a/src/t_api.c b/src/t_api.c
index d822f55..d3bfb7e 100644
--- a/src/t_api.c
+++ b/src/t_api.c
@@ -27,9 +27,7 @@
#include <assert.h>
-#ifdef HAVE_STDINT_H
#include <stdint.h>
-#endif
#include <stdio.h>
#include <string.h>
diff --git a/src/t_auth.c b/src/t_auth.c
index 22c78ae..3b0fd2f 100644
--- a/src/t_auth.c
+++ b/src/t_auth.c
@@ -27,9 +27,7 @@
#include "iperf_config.h"
#include <assert.h>
-#ifdef HAVE_STDINT_H
#include <stdint.h>
-#endif
#include <stdio.h>
#include <string.h>
@@ -103,8 +101,9 @@ test_authtoken(const char *authUser, const char *authPassword, EVP_PKEY *pubkey,
char *decodePassword;
time_t decodeTime;
- assert(encode_auth_setting(authUser, authPassword, pubkey, &authToken) == 0);
- assert(decode_auth_setting(0, authToken, privkey, &decodeUser, &decodePassword, &decodeTime) == 0);
+ int use_pkcs1_padding = 1;
+ assert(encode_auth_setting(authUser, authPassword, pubkey, &authToken, use_pkcs1_padding) == 0);
+ assert(decode_auth_setting(0, authToken, privkey, &decodeUser, &decodePassword, &decodeTime, use_pkcs1_padding) == 0);
assert(strcmp(decodeUser, authUser) == 0);
assert(strcmp(decodePassword, authPassword) == 0);
diff --git a/src/t_timer.c b/src/t_timer.c
index 8eec7d8..fb6eb19 100644
--- a/src/t_timer.c
+++ b/src/t_timer.c
@@ -26,9 +26,7 @@
*/
#include "iperf_config.h"
-#ifdef HAVE_STDINT_H
#include <stdint.h>
-#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
diff --git a/src/t_units.c b/src/t_units.c
index 73f21a9..13883aa 100644
--- a/src/t_units.c
+++ b/src/t_units.c
@@ -25,9 +25,7 @@
* file for complete information.
*/
#include <assert.h>
-#ifdef HAVE_STDINT_H
#include <stdint.h>
-#endif
#include <stdio.h>
#include <string.h>
diff --git a/src/units.c b/src/units.c
index 7376a0b..f6b14bc 100644
--- a/src/units.c
+++ b/src/units.c
@@ -54,9 +54,7 @@
#include <stdio.h>
#include <assert.h>
#include <ctype.h>
-#ifdef HAVE_STDINT_H
#include <stdint.h>
-#endif
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/time.h>