diff options
Diffstat (limited to '')
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/Makefile.in | 50 | ||||
-rw-r--r-- | src/cjson.c | 22 | ||||
-rw-r--r-- | src/cjson.h | 2 | ||||
-rw-r--r-- | src/iperf.h | 33 | ||||
-rw-r--r-- | src/iperf3.1 | 20 | ||||
-rw-r--r-- | src/iperf_api.c | 153 | ||||
-rw-r--r-- | src/iperf_api.h | 8 | ||||
-rw-r--r-- | src/iperf_auth.c | 37 | ||||
-rw-r--r-- | src/iperf_auth.h | 4 | ||||
-rw-r--r-- | src/iperf_client_api.c | 12 | ||||
-rw-r--r-- | src/iperf_config.h.in | 20 | ||||
-rw-r--r-- | src/iperf_error.c | 34 | ||||
-rw-r--r-- | src/iperf_locale.c | 27 | ||||
-rw-r--r-- | src/iperf_pthread.c | 40 | ||||
-rw-r--r-- | src/iperf_pthread.h | 21 | ||||
-rw-r--r-- | src/iperf_server_api.c | 2 | ||||
-rw-r--r-- | src/iperf_tcp.c | 35 | ||||
-rw-r--r-- | src/iperf_udp.c | 16 | ||||
-rw-r--r-- | src/libiperf.3 | 1 | ||||
-rw-r--r-- | src/main.c | 4 | ||||
-rw-r--r-- | src/net.c | 1 | ||||
-rw-r--r-- | src/portable_endian.h | 2 | ||||
-rw-r--r-- | src/t_api.c | 2 | ||||
-rw-r--r-- | src/t_auth.c | 7 | ||||
-rw-r--r-- | src/t_timer.c | 2 | ||||
-rw-r--r-- | src/t_units.c | 2 | ||||
-rw-r--r-- | src/units.c | 2 |
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 ); @@ -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)); @@ -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> |