Upgrade iperf3 to 3.7

Test: None
Change-Id: I022a655ee5627904e9fe60c9403608de4d61e747
diff --git a/METADATA b/METADATA
index 78bbb0d..1477e70 100644
--- a/METADATA
+++ b/METADATA
@@ -9,10 +9,10 @@
     type: GIT
     value: "https://github.com/esnet/iperf.git"
   }
-  version: "2679640c0f6dfc28f0e243adb3bfdf8c41cbb027"
+  version: "3.7"
   last_upgrade_date {
     year: 2019
-    month: 6
+    month: 7
     day: 2
   }
 }
diff --git a/README.md b/README.md
index b3c0964..356784b 100644
--- a/README.md
+++ b/README.md
@@ -124,14 +124,14 @@
 
     -C, --linux-congestion    set congestion control algorithm (Linux only)
                               (-Z in iperf2)
-
+    --bidir                   bidirectional testing mode
+                              (-d in iperf2)
 
 Deprecated options:
 
 Not planning to support these iperf2 flags. If you really miss these
 options, please submit a request in the issue tracker:
 
-    -d, --dualtest           Do a bidirectional test simultaneously
     -r, --tradeoff           Do a bidirectional test individually
     -T, --ttl                time-to-live, for multicast (default 1)
     -x, --reportexclude [CDMSV]   exclude C(connection) D(data) M(multicast) 
diff --git a/RELEASE_NOTES b/RELNOTES.md
similarity index 87%
rename from RELEASE_NOTES
rename to RELNOTES.md
index 6d4b98b..ff02ba9 100644
--- a/RELEASE_NOTES
+++ b/RELNOTES.md
@@ -1,35 +1,74 @@
-== iperf 3.6 2018-06-25 ==
+iperf3 Release Notes
+====================
+
+iperf 3.7 2019-06-21
+--------------------
 
 * Notable user-visible changes
 
- * A new --extra-data option can be used to fill in a user-defined
-   string field that appears in JSON output.  (#600 / #729)
+  * Support for simultaneous bidirectional tests with the --bidir flag
+    (#201/#780).
 
- * A new --repeating-payload option makes iperf3 use a payload pattern
-   similar to that used by iperf2, which could help in recreating
-   results that might be affected by payload entropy (for example,
-   compression).  (#726)
+  * Use POSIX standard clock_gettime(3) interface for timekeeping where
+    available (#253/#738).
 
- * -B now works properly with SCTP tests.  (#678 / #715)
+  * Passwords for authentication can be provided via environment
+    variable (#815).
 
- * A compile fix for Solaris 10 was added.  (#711)
+  * Specifying --repeating-payload and --reverse now works (#867).
 
- * Some minor bug fixes for JSON output.  In particular, warnings for
-   debug and/or verbose modes with --json output (#737) and a fix for
-   JSON output on CentOS 6 (#727 / #744).
+  * Failed authentication doesn't count for --one-off (#864/#877).
 
- * software.es.net and downloads.es.net now support HTTPS, so URLs in
-   documentation that refer to those two hosts now use https://
-   instead of http:// URLs. (#759)
+  * Several memory leaks related to authenticated use were fixed
+    (#881/#888).
+
+  * The delay for tearing down the control connection for the default
+    timed tests has been increased, to more gracefully handle
+    high-delay paths (#751/#859).
 
 * Notable developer-visible changes
 
- * Functions related to authenticated iperf3 connections have been
-   exposed via libiperf.  (#712 / #713)
+  * Various improvements to the libiperf APIs (#767, #775, #869, #870,
+    #871)
 
- * The ToS byte is now exposed in the libiperf API. (#719)
+  * Fixed build behavior when OpenSSL is absent (#854).
 
-== iperf 3.5 2018-03-02 ==
+  * Portability fixes (#821/#874).
+
+iperf 3.6 2018-06-25
+--------------------
+
+* Notable user-visible changes
+
+  * A new --extra-data option can be used to fill in a user-defined
+    string field that appears in JSON output.  (#600 / #729)
+
+  * A new --repeating-payload option makes iperf3 use a payload pattern
+    similar to that used by iperf2, which could help in recreating
+    results that might be affected by payload entropy (for example,
+    compression).  (#726)
+
+  * -B now works properly with SCTP tests.  (#678 / #715)
+
+  * A compile fix for Solaris 10 was added.  (#711)
+
+  * Some minor bug fixes for JSON output.  In particular, warnings for
+    debug and/or verbose modes with --json output (#737) and a fix for
+    JSON output on CentOS 6 (#727 / #744).
+
+  * software.es.net and downloads.es.net now support HTTPS, so URLs in
+    documentation that refer to those two hosts now use https://
+    instead of http:// URLs. (#759)
+
+* Notable developer-visible changes
+
+  * Functions related to authenticated iperf3 connections have been
+    exposed via libiperf.  (#712 / #713)
+
+  * The ToS byte is now exposed in the libiperf API. (#719)
+
+iperf 3.5 2018-03-02
+--------------------
 
 * Notable user-visible changes
 
@@ -41,7 +80,8 @@
     paths.  Many thanks to @FuzzyStatic for providing access to a test
     environment for diagnosing this issue (#692).
 
-== iperf 3.4 2018-02-14 ==
+iperf 3.4 2018-02-14
+--------------------
 
 * Notable user-visible changes
 
@@ -80,7 +120,8 @@
     #668).  Also some code was cleaned up to eliminate (or at least
     reduce) compiler warnings (#664, #671).
 
-== iperf 3.3 2017-10-31 ==
+iperf 3.3 2017-10-31
+--------------------
 
 * Notable user-visible changes
 
@@ -109,7 +150,8 @@
 
 * Notable developer-visible changes
 
-== iperf 3.2 2017-06-26 ==
+iperf 3.2 2017-06-26
+--------------------
 
 * User-visible changes
 
@@ -196,13 +238,15 @@
 
   * Some dead code has been removed.
 
-== iperf 3.1.7 2017-03-06 ==
+iperf 3.1.7 2017-03-06
+----------------------
 
 iperf 3.1.7 is functionally identical to iperf 3.1.6.  Its only
 changes consist of updated documentation files and text in the RPM
 spec file.
 
-== iperf 3.1.6 2017-02-02 ==
+iperf 3.1.6 2017-02-02
+----------------------
 
 The release notes for iperf 3.1.6 describe changes, including bug
 fixes and new functionality, made since iperf 3.1.5.
@@ -217,7 +261,8 @@
   * Fixed a bug where two recently-added diagnostic messages spammed
     the JSON output on UDP tests.
 
-== iperf 3.1.5 2017-01-12 ==
+iperf 3.1.5 2017-01-12
+----------------------
 
 The release notes for iperf 3.1.5 describe changes, including bug
 fixes and new functionality, made since iperf 3.1.4.
@@ -273,7 +318,8 @@
 
   * A systemd service file has been added (#340, #430).
 
-== iperf 3.1.4 2016-10-31 ==
+iperf 3.1.4 2016-10-31
+----------------------
 
 The release notes for iperf 3.1.4 describe changes, including bug
 fixes and new functionality, made since iperf 3.1.3.
@@ -297,7 +343,8 @@
 
   * Various bug fixes (issue #459, pull request #429, issue #388).
 
-== iperf 3.1.3 2016-06-08 ==
+iperf 3.1.3 2016-06-08
+----------------------
 
 The release notes for iperf 3.1.3 describe changes, including bug
 fixes and new functionality, made since iperf 3.1.2.
@@ -335,7 +382,8 @@
 
   * Fixed various coding errors (issue #423, issue #425).
 
-== iperf 3.1.2 2016-02-01 ==
+iperf 3.1.2 2016-02-01
+----------------------
 
 The release notes for iperf 3.1.2 describe changes, including bug
 fixes and new functionality, made since iperf 3.1.1.
@@ -353,7 +401,8 @@
 
 * Developer-visible changes
 
-== iperf 3.1.1 2015-11-19 ==
+iperf 3.1.1 2015-11-19
+----------------------
 
 The release notes for iperf 3.1.1 describe changes and new
 functionality in iperf 3.1.1, but not present in 3.1.
@@ -374,7 +423,8 @@
   * A regression with C++ compatibility in one of the iperf header
     files has been fixed (issue #323).
 
-== iperf 3.1 2015-10-16 ==
+iperf 3.1 2015-10-16
+--------------------
 
 The release notes for iperf 3.1 describe changes and new
 functionality in iperf 3.1, but not present in 3.0.11 or any earlier
@@ -428,7 +478,8 @@
 
   * Out-of-tree builds now work (issue #265).
 
-== iperf 3.0.11 2015-01-09 ==
+iperf 3.0.11 2015-01-09
+-----------------------
 
 * User-visible changes
 
@@ -441,7 +492,8 @@
   * Added 30-second timeout for UDP tests if unable to establish UDP
     connectivity between sender and receiver (issue #222).
 
-== iperf 3.0.10 2014-12-16 ==
+iperf 3.0.10 2014-12-16
+-----------------------
 
 * User-visible changes
 
@@ -458,7 +510,8 @@
   * Fixed potential filename collision with a system header (issue
     #203).
 
-== iperf 3.0.9 2014-10-14 ==
+iperf 3.0.9 2014-10-14
+----------------------
 
 * User-visible changes
 
@@ -472,7 +525,8 @@
 
   * None.
 
-== iperf 3.0.8 2014-09-30 ==
+iperf 3.0.8 2014-09-30
+----------------------
 
 * User-visible changes
 
@@ -484,7 +538,8 @@
 
   * None.
 
-== iperf 3.0.7 2014-08-28 ==
+iperf 3.0.7 2014-08-28
+----------------------
 
 * User-visible changes
 
@@ -501,7 +556,8 @@
 
 * Developer-visible changes
 
-== iperf 3.0.6 2014-07-28 ==
+iperf 3.0.6 2014-07-28
+----------------------
 
 * User-visible changes
 
@@ -516,7 +572,8 @@
   * The {get,set}_test_bind_address API calls have been added to
     expose the -B functionality to API consumers (issue #197).
 
-== iperf 3.0.5 2014-06-16 ==
+iperf 3.0.5 2014-06-16
+----------------------
 
 * User-visible changes
 
@@ -550,9 +607,11 @@
     versions.  AM_MAINTAINER_MODE is now used to avoid requiring these
     tools at build-time.
 
-== iperf 3.0.4 was not released ==
+iperf 3.0.4 was not released
+----------------------------
 
-== iperf 3.0.3 2014-03-26 ==
+iperf 3.0.3 2014-03-26
+----------------------
 
 * User-visible changes
 
@@ -574,7 +633,8 @@
   * Example programs now build correctly, after having been broken in
     the 3.0.2 release (issue #152).
 
-== iperf 3.0.2 2014-03-10 ==
+iperf 3.0.2 2014-03-10
+----------------------
 
 * User-visible changes
 
@@ -619,7 +679,9 @@
     While technically an incompatible API change, the former behavior
     generated unusable JSON.
 
-== iperf 3.0.1 2014-01-10 ==
+iperf 3.0.1 2014-01-10
+----------------------
+
   * Added the following new flags
      -D, --daemon	       run server as a daemon
      -L, --flowlabel           set IPv6 flow label (Linux only)
@@ -628,7 +690,9 @@
      	 	      	       (instead of -t or -n)
   * Bug fixes
 
-== iperf 3.0-RC5 2013-11-15 ==
+iperf 3.0-RC5 2013-11-15
+------------------------
+
   * Added the following new flags
      -F, --file name           xmit/recv the specified file
      -A, --affinity n/n,m      set CPU affinity (Linux only)
@@ -640,7 +704,8 @@
   * Many bug fixes
 
 
-== iperf 3.0b4 2010-08-02 ==
+iperf 3.0b4 2010-08-02
+----------------------
 
   * Added support for binding to a specific interface (-B)
   * Added support for IPv6 mode (-6)
@@ -654,7 +719,8 @@
       * Support for decimal values
   * Many bug fixes
 
-== iperf 3.0b3 2010-07-23 ==
+iperf 3.0b3 2010-07-23
+----------------------
 
   * Better error handling
       * All errors now handled with iperf_error()
@@ -668,7 +734,8 @@
           * on_test_finish - executes after the test is finished
   * Added early support for verbose mode (-V)
 
-== iperf 3.0b2 2010-07-15 ==
+iperf 3.0b2 2010-07-15
+----------------------
 
   * UDP mode now supported
       * Support for setting bandwidth (-b)
@@ -678,7 +745,8 @@
   * Support for setting TCP MSS (-M)
       * Note: This feature is still in development. It is still very buggy.
 
-== iperf 3.0b1 2010-07-08 ==
+iperf 3.0b1 2010-07-08
+----------------------
 
   * TCP control socket now manages messages between client and server
   * Dynamic server (gets test parameters from client)
diff --git a/configure b/configure
index 679da39..c9e1015 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for iperf 3.6+.
+# Generated by GNU Autoconf 2.69 for iperf 3.7.
 #
 # Report bugs to <https://github.com/esnet/iperf>.
 #
@@ -590,8 +590,8 @@
 # Identity of this package.
 PACKAGE_NAME='iperf'
 PACKAGE_TARNAME='iperf'
-PACKAGE_VERSION='3.6+'
-PACKAGE_STRING='iperf 3.6+'
+PACKAGE_VERSION='3.7'
+PACKAGE_STRING='iperf 3.7'
 PACKAGE_BUGREPORT='https://github.com/esnet/iperf'
 PACKAGE_URL='https://software.es.net/iperf/'
 
@@ -1324,7 +1324,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures iperf 3.6+ to adapt to many kinds of systems.
+\`configure' configures iperf 3.7 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1394,7 +1394,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of iperf 3.6+:";;
+     short | recursive ) echo "Configuration of iperf 3.7:";;
    esac
   cat <<\_ACEOF
 
@@ -1510,7 +1510,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-iperf configure 3.6+
+iperf configure 3.7
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1879,7 +1879,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by iperf $as_me 3.6+, which was
+It was created by iperf $as_me 3.7, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2811,7 +2811,7 @@
 
 # Define the identity of the package.
  PACKAGE='iperf'
- VERSION='3.6+'
+ VERSION='3.7'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -13724,7 +13724,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by iperf $as_me 3.6+, which was
+This file was extended by iperf $as_me 3.7, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -13791,7 +13791,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-iperf config.status 3.6+
+iperf config.status 3.7
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
diff --git a/configure.ac b/configure.ac
index cea094a..0ff6549 100644
--- a/configure.ac
+++ b/configure.ac
@@ -24,7 +24,7 @@
 # file for complete information.
 
 # Initialize the autoconf system for the specified tool, version and mailing list
-AC_INIT(iperf, 3.6+, https://github.com/esnet/iperf, iperf, https://software.es.net/iperf/)
+AC_INIT(iperf, 3.7, https://github.com/esnet/iperf, iperf, https://software.es.net/iperf/)
 m4_include([config/ax_check_openssl.m4])
 AC_LANG(C)
 
diff --git a/src/iperf.h b/src/iperf.h
index b8a6e58..6ce77f5 100755
--- a/src/iperf.h
+++ b/src/iperf.h
@@ -1,5 +1,5 @@
 /*
- * iperf, Copyright (c) 2014-2018, The Regents of the University of
+ * iperf, Copyright (c) 2014-2019, 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.
@@ -385,4 +385,6 @@
 #define MAX_MSS (9 * 1024)
 #define MAX_STREAMS 128
 
+extern int gerror; /* error value from getaddrinfo(3), for use in internal error handling */
+
 #endif /* !__IPERF_H */
diff --git a/src/iperf_api.c b/src/iperf_api.c
index 014a560..e1bbfa5 100755
--- a/src/iperf_api.c
+++ b/src/iperf_api.c
@@ -1,5 +1,5 @@
 /*
- * iperf, Copyright (c) 2014-2018, The Regents of the University of
+ * iperf, Copyright (c) 2014-2019, 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.
@@ -391,6 +391,12 @@
 }
 
 void
+iperf_set_test_logfile(struct iperf_test *ipt, char *logfile)
+{
+    ipt->logfile = strdup(logfile);
+}
+
+void
 iperf_set_test_rate(struct iperf_test *ipt, uint64_t rate)
 {
     ipt->settings->rate = rate;
@@ -836,6 +842,7 @@
         {NULL, 0, NULL, 0}
     };
     int flag;
+    int portno;
     int blksize;
     int server_flag, client_flag, rate_flag, duration_flag;
     char *endptr;
@@ -855,7 +862,12 @@
     while ((flag = getopt_long(argc, argv, "p:f:i:D1VJvsc:ub:t:n:k:l:P:Rw:B:M:N46S:L:ZO:F:A:T:C:dI:hX:", longopts, NULL)) != -1) {
         switch (flag) {
             case 'p':
-                test->server_port = atoi(optarg);
+		portno = atoi(optarg);
+		if (portno < 1 || portno > 65535) {
+		    i_errno = IEBADPORT;
+		    return -1;
+		}
+		test->server_port = portno;
                 break;
             case 'f':
 		if (!optarg) {
@@ -1019,7 +1031,12 @@
                 test->bind_address = strdup(optarg);
                 break;
             case OPT_CLIENT_PORT:
-                test->bind_port = atoi(optarg);
+		portno = atoi(optarg);
+		if (portno < 1 || portno > 65535) {
+		    i_errno = IEBADPORT;
+		    return -1;
+		}
+                test->bind_port = portno;
                 break;
             case 'M':
                 test->settings->mss = atoi(optarg);
@@ -1217,15 +1234,6 @@
         }
     }
 
-    /* Set logging to a file if specified, otherwise use the default (stdout) */
-    if (test->logfile) {
-        test->outfile = fopen(test->logfile, "a+");
-        if (test->outfile == NULL) {
-            i_errno = IELOGFILE;
-            return -1;
-        }
-    }
-
     /* Check flag / role compatibility. */
     if (test->role == 'c' && server_flag) {
         i_errno = IESERVERONLY;
@@ -1249,8 +1257,10 @@
 
         char *client_password = NULL;
         size_t s;
-        if ((client_password = getenv("IPERF3_PASSWORD")) == NULL &&
-            iperf_getpass(&client_password, &s, stdin) < 0){
+        /* Need to copy env var, so we can do a common free */
+        if ((client_password = getenv("IPERF3_PASSWORD")) != NULL)
+             client_password = strdup(client_password);
+        else if (iperf_getpass(&client_password, &s, stdin) < 0){
             return -1;
         } 
 
@@ -1267,6 +1277,8 @@
         test->settings->client_username = client_username;
         test->settings->client_password = client_password;
         test->settings->client_rsa_pubkey = load_pubkey_from_file(client_rsa_public_key);
+	free(client_rsa_public_key);
+	client_rsa_public_key = NULL;
     }
 
     if (test->role == 'c' && (server_rsa_private_key || test->server_authorized_users)){
@@ -1276,11 +1288,14 @@
         !(server_rsa_private_key && test->server_authorized_users)) {
          i_errno = IESETSERVERAUTH;
         return -1;
-    } else if (test->role == 's' && server_rsa_private_key && test_load_private_key_from_file(server_rsa_private_key) < 0){
-        i_errno = IESETSERVERAUTH;
-        return -1;
-    } else {
+    } else if (test->role == 's' && server_rsa_private_key) {
         test->server_rsa_private_key = load_privkey_from_file(server_rsa_private_key);
+        if (test->server_rsa_private_key == NULL){
+            i_errno = IESETSERVERAUTH;
+            return -1;
+        }
+	free(server_rsa_private_key);
+	server_rsa_private_key = NULL;
     }
 
 #endif //HAVE_SSL
@@ -1350,6 +1365,20 @@
     return 0;
 }
 
+/*
+ * Open the file specified by test->logfile and set test->outfile to its' FD.
+ */
+int iperf_open_logfile(struct iperf_test *test)
+{
+    test->outfile = fopen(test->logfile, "a+");
+    if (test->outfile == NULL) {
+        i_errno = IELOGFILE;
+        return -1;
+    }
+
+    return 0;
+}
+
 int
 iperf_set_send_state(struct iperf_test *test, signed char state)
 {
@@ -1534,9 +1563,13 @@
         int ret = check_authentication(username, password, ts, test->server_authorized_users);
         if (ret == 0){
             iperf_printf(test, report_authetication_successed, username, ts);
+            free(username);
+            free(password);
             return 0;
         } else {
             iperf_printf(test, report_authetication_failed, username, ts);
+            free(username);
+            free(password);
             return -1;
         }
     }
@@ -1732,7 +1765,10 @@
         r = -1;
     } else {
 	if (test->debug) {
-	    printf("get_parameters:\n%s\n", cJSON_Print(j));
+            char *str;
+            str = cJSON_Print(j);
+            printf("get_parameters:\n%s\n", str );
+            free(str);
 	}
 
 	if ((j_p = cJSON_GetObjectItem(j, "tcp")) != NULL)
@@ -1897,7 +1933,9 @@
 		}
 	    }
 	    if (r == 0 && test->debug) {
-		printf("send_results\n%s\n", cJSON_Print(j));
+                char *str = cJSON_Print(j);
+		printf("send_results\n%s\n", str);
+                free(str);
 	    }
 	    if (r == 0 && JSON_write(test->ctrl_sck, j) < 0) {
 		i_errno = IESENDRESULTS;
@@ -1953,7 +1991,9 @@
 	    r = -1;
 	} else {
 	    if (test->debug) {
-		printf("get_results\n%s\n", cJSON_Print(j));
+                char *str = cJSON_Print(j);
+                printf("get_results\n%s\n", str);
+                free(str);
 	    }
 
 	    test->remote_cpu_util[0] = j_cpu_util_total->valuedouble;
@@ -2370,7 +2410,6 @@
         SLIST_REMOVE_HEAD(&test->streams, streams);
         iperf_free_stream(sp);
     }
-
     if (test->server_hostname)
 	free(test->server_hostname);
     if (test->tmp_template)
@@ -2389,6 +2428,26 @@
             free(xbe);
         }
     }
+#if defined(HAVE_SSL)
+
+    if (test->server_rsa_private_key)
+      EVP_PKEY_free(test->server_rsa_private_key);
+    test->server_rsa_private_key = NULL;
+
+    free(test->settings->authtoken);
+    test->settings->authtoken = NULL;
+
+    free(test->settings->client_username);
+    test->settings->client_username = NULL;
+
+    free(test->settings->client_password);
+    test->settings->client_password = NULL;
+
+    if (test->settings->client_rsa_pubkey)
+      EVP_PKEY_free(test->settings->client_rsa_pubkey);
+    test->settings->client_rsa_pubkey = NULL;
+#endif /* HAVE_SSL */
+
     if (test->settings)
     free(test->settings);
     if (test->title)
@@ -2487,6 +2546,9 @@
 
     SLIST_INIT(&test->streams);
 
+    if (test->remote_congestion_used)
+        free(test->remote_congestion_used);
+    test->remote_congestion_used = NULL;
     test->role = 's';
     test->mode = RECEIVER;
     test->sender_has_retransmits = 0;
diff --git a/src/iperf_api.h b/src/iperf_api.h
index 7daf974..f9f964e 100755
--- a/src/iperf_api.h
+++ b/src/iperf_api.h
@@ -1,5 +1,5 @@
 /*
- * iperf, Copyright (c) 2014-2018, The Regents of the University of
+ * iperf, Copyright (c) 2014-2019, 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.
@@ -138,6 +138,7 @@
 void	iperf_set_test_stats_interval( struct iperf_test* ipt, double stats_interval );
 void	iperf_set_test_state( struct iperf_test* ipt, signed char state );
 void	iperf_set_test_blksize( struct iperf_test* ipt, int blksize );
+void	iperf_set_test_logfile( struct iperf_test* ipt, char *logfile );
 void	iperf_set_test_rate( struct iperf_test* ipt, uint64_t rate );
 void    iperf_set_test_pacing_timer( struct iperf_test* ipt, int pacing_timer );
 void    iperf_set_test_bytes( struct iperf_test* ipt, uint64_t bytes );
@@ -267,6 +268,7 @@
 int iperf_init_test(struct iperf_test *);
 int iperf_create_send_timers(struct iperf_test *);
 int iperf_parse_arguments(struct iperf_test *, int, char **);
+int iperf_open_logfile(struct iperf_test *);
 void iperf_reset_test(struct iperf_test *);
 void iperf_reset_stats(struct iperf_test * test);
 
@@ -340,6 +342,7 @@
     IESETSERVERAUTH = 23,   // Bad configuration of server authentication
     IEBADFORMAT = 24,	    // Bad format argument to -f
     IEREVERSEBIDIR = 25,    // Iperf cannot be both reverse and bidirectional
+    IEBADPORT = 26,	    // Bad port number
     /* Test errors */
     IENEWTEST = 100,        // Unable to create a new test (check perror)
     IEINITTEST = 101,       // Test initialization failed (check perror)
diff --git a/src/iperf_auth.c b/src/iperf_auth.c
index b9cd98a..9965e19 100644
--- a/src/iperf_auth.c
+++ b/src/iperf_auth.c
@@ -95,6 +95,7 @@
         s_username = strtok(buf, ",");
         s_password = strtok(NULL, ",");
         if (strcmp( username, s_username ) == 0 && strcmp( passwordHash, s_password ) == 0){
+            fclose(ptr_file);
             return 0;
         }
     }
@@ -115,11 +116,9 @@
     BIO_write(bio, buffer, length);
     BIO_flush(bio);
     BIO_get_mem_ptr(bio, &bufferPtr);
-    BIO_set_close(bio, BIO_NOCLOSE);
+    *b64text = strndup( (*bufferPtr).data, (*bufferPtr).length );
     BIO_free_all(bio);
 
-    *b64text=(*bufferPtr).data;
-    (*b64text)[(*bufferPtr).length] = '\0';
     return (0); //success
 }
 
@@ -157,10 +156,12 @@
     BIO *key = NULL;
     EVP_PKEY *pkey = NULL;
 
-    key = BIO_new_file(file, "r");
-    pkey = PEM_read_bio_PUBKEY(key, NULL, NULL, NULL);
+    if (file) {
+      key = BIO_new_file(file, "r");
+      pkey = PEM_read_bio_PUBKEY(key, NULL, NULL, NULL);
 
-    BIO_free(key);
+      BIO_free(key);
+    }
     return (pkey);
 }   
 
@@ -179,10 +180,12 @@
     BIO *key = NULL;
     EVP_PKEY *pkey = NULL;
 
-    key = BIO_new_file(file, "r");
-    pkey = PEM_read_bio_PrivateKey(key, NULL, NULL, NULL);
+    if (file) {
+      key = BIO_new_file(file, "r");
+      pkey = PEM_read_bio_PrivateKey(key, NULL, NULL, NULL);
 
-    BIO_free(key);
+      BIO_free(key);
+    }
     return (pkey);
 }
 
@@ -222,7 +225,7 @@
 
     RSA_free(rsa);
     OPENSSL_free(rsa_buffer);
-    OPENSSL_free(bioBuff);  
+    BIO_free(bioBuff);
 
     return encryptedtext_len;  
 }
@@ -244,7 +247,7 @@
 
     RSA_free(rsa);
     OPENSSL_free(rsa_buffer);
-    OPENSSL_free(bioBuff);   
+    BIO_free(bioBuff);
 
     return plaintext_len;
 }
@@ -258,6 +261,8 @@
     int encrypted_len;
     encrypted_len = encrypt_rsa_message(text, public_key, &encrypted);
     Base64Encode(encrypted, encrypted_len, authtoken);
+    OPENSSL_free(encrypted);
+
     return (0); //success
 }
 
@@ -270,6 +275,7 @@
     int plaintext_len;
     plaintext_len = decrypt_rsa_message(encrypted_b64, encrypted_len_b64, private_key, &plaintext);
     plaintext[plaintext_len] = '\0';
+    free(encrypted_b64);
 
     char s_username[20], s_password[20];
     sscanf ((char *)plaintext,"user: %s\npwd:  %s\nts:   %ld", s_username, s_password, ts);
@@ -281,6 +287,7 @@
     *password = (char *) calloc(21, sizeof(char));
     strncpy(*username, s_username, 20);
     strncpy(*password, s_password, 20);
+    OPENSSL_free(plaintext);
     return (0);
 }
 
diff --git a/src/iperf_client_api.c b/src/iperf_client_api.c
index 46c283b..20ea6fd 100644
--- a/src/iperf_client_api.c
+++ b/src/iperf_client_api.c
@@ -454,6 +454,10 @@
     struct timeval* timeout = NULL;
     struct iperf_stream *sp;
 
+    if (test->logfile)
+        if (iperf_open_logfile(test) < 0)
+            return -1;
+
     if (test->affinity != -1)
 	if (iperf_setaffinity(test, test->affinity) != 0)
 	    return -1;
diff --git a/src/iperf_error.c b/src/iperf_error.c
index 3d34b63..fd3cccc 100644
--- a/src/iperf_error.c
+++ b/src/iperf_error.c
@@ -1,5 +1,5 @@
 /*
- * iperf, Copyright (c) 2014-2018, The Regents of the University of
+ * iperf, Copyright (c) 2014-2019, 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.
@@ -33,6 +33,8 @@
 #include "iperf.h"
 #include "iperf_api.h"
 
+int gerror;
+
 /* Do a printf to stderr. */
 void
 iperf_err(struct iperf_test *test, const char *format, ...)
@@ -140,6 +142,9 @@
 	case IEBADFORMAT:
 	    snprintf(errstr, len, "bad format specifier (valid formats are in the set [kmgtKMGT])");
 	    break;
+	case IEBADPORT:
+	    snprintf(errstr, len, "port number must be between 1 and 65535 inclusive");
+	    break;
         case IEMSS:
             snprintf(errstr, len, "TCP MSS too large (maximum = %d bytes)", MAX_MSS);
             break;
@@ -182,11 +187,13 @@
             break;
         case IELISTEN:
             snprintf(errstr, len, "unable to start listener for connections");
+	    herr = 1;
             perr = 1;
             break;
         case IECONNECT:
             snprintf(errstr, len, "unable to connect to server");
             perr = 1;
+	    herr = 1;
             break;
         case IEACCEPT:
             snprintf(errstr, len, "unable to accept connection from client");
@@ -314,6 +321,7 @@
             break;
         case IESTREAMLISTEN:
             snprintf(errstr, len, "unable to start stream listener");
+	    herr = 1;
             perr = 1;
             break;
         case IESTREAMCONNECT:
@@ -380,10 +388,15 @@
 	
     }
 
+    /* Append the result of strerror() or gai_strerror() if appropriate */
     if (herr || perr)
         strncat(errstr, ": ", len - strlen(errstr) - 1);
     if (errno && perr)
         strncat(errstr, strerror(errno), len - strlen(errstr) - 1);
+    else if (herr && gerror) {
+        strncat(errstr, gai_strerror(gerror), len - strlen(errstr) - 1);
+	gerror = 0;
+    }
 
     return errstr;
 }
diff --git a/src/iperf_sctp.c b/src/iperf_sctp.c
index c1cb134..06e1e23 100644
--- a/src/iperf_sctp.c
+++ b/src/iperf_sctp.c
@@ -1,5 +1,5 @@
 /*
- * iperf, Copyright (c) 2014-2018, The Regents of the University of
+ * iperf, Copyright (c) 2014-2019, 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.
@@ -178,7 +178,7 @@
     }
     hints.ai_socktype = SOCK_STREAM;
     hints.ai_flags = AI_PASSIVE;
-    if (getaddrinfo(test->bind_address, portstr, &hints, &res) != 0) {
+    if ((gerror = getaddrinfo(test->bind_address, portstr, &hints, &res)) != 0) {
         i_errno = IESTREAMLISTEN;
         return -1;
     }
@@ -266,7 +266,7 @@
         memset(&hints, 0, sizeof(hints));
         hints.ai_family = test->settings->domain;
         hints.ai_socktype = SOCK_STREAM;
-        if (getaddrinfo(test->bind_address, NULL, &hints, &local_res) != 0) {
+        if ((gerror = getaddrinfo(test->bind_address, NULL, &hints, &local_res)) != 0) {
             i_errno = IESTREAMCONNECT;
             return -1;
         }
@@ -276,7 +276,7 @@
     hints.ai_family = test->settings->domain;
     hints.ai_socktype = SOCK_STREAM;
     snprintf(portstr, sizeof(portstr), "%d", test->server_port);
-    if (getaddrinfo(test->server_hostname, portstr, &hints, &server_res) != 0) {
+    if ((gerror = getaddrinfo(test->server_hostname, portstr, &hints, &server_res)) != 0) {
 	if (test->bind_address)
 	    freeaddrinfo(local_res);
         i_errno = IESTREAMCONNECT;
@@ -548,7 +548,7 @@
         xbe0 = TAILQ_FIRST(&test->xbind_addrs);
         TAILQ_REMOVE(&test->xbind_addrs, xbe0, link);
 
-        if (getaddrinfo(xbe0->name, servname, &hints, &xbe0->ai) != 0) {
+        if ((gerror = getaddrinfo(xbe0->name, servname, &hints, &xbe0->ai)) != 0) {
             i_errno = IESETSCTPBINDX;
             retval = -1;
             goto out;
@@ -592,7 +592,7 @@
     TAILQ_FOREACH(xbe, &test->xbind_addrs, link) {
         if (xbe->ai != NULL)
             freeaddrinfo(xbe->ai);
-        if (getaddrinfo(xbe->name, servname, &hints, &xbe->ai) != 0) {
+        if ((gerror = getaddrinfo(xbe->name, servname, &hints, &xbe->ai)) != 0) {
             i_errno = IESETSCTPBINDX;
             retval = -1;
             goto out;
diff --git a/src/iperf_server_api.c b/src/iperf_server_api.c
index 079da89..40d99bc 100644
--- a/src/iperf_server_api.c
+++ b/src/iperf_server_api.c
@@ -270,6 +270,9 @@
 {
     struct iperf_time now;
     TimerClientData cd;
+    int max_rtt = 4; /* seconds */
+    int state_transitions = 10; /* number of state transitions in iperf3 */
+    int grace_period = max_rtt * state_transitions;
 
     if (iperf_time_now(&now) < 0) {
 	i_errno = IEINITTEST;
@@ -279,7 +282,7 @@
     test->timer = test->stats_timer = test->reporter_timer = NULL;
     if (test->duration != 0 ) {
         test->done = 0;
-        test->timer = tmr_create(&now, server_timer_proc, cd, (test->duration + test->omit + 5) * SEC_TO_US, 0);
+        test->timer = tmr_create(&now, server_timer_proc, cd, (test->duration + test->omit + grace_period) * SEC_TO_US, 0);
         if (test->timer == NULL) {
             i_errno = IEINITTEST;
             return -1;
@@ -398,6 +401,10 @@
     struct timeval* timeout;
     int flag;
 
+    if (test->logfile)
+        if (iperf_open_logfile(test) < 0)
+            return -1;
+
     if (test->affinity != -1) 
 	if (iperf_setaffinity(test, test->affinity) != 0)
 	    return -2;
diff --git a/src/iperf_tcp.c b/src/iperf_tcp.c
index f6ef78f..232aaa1 100644
--- a/src/iperf_tcp.c
+++ b/src/iperf_tcp.c
@@ -1,5 +1,5 @@
 /*
- * iperf, Copyright (c) 2014-2018, The Regents of the University of
+ * iperf, Copyright (c) 2014-2019, 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.
@@ -184,7 +184,7 @@
 	}
         hints.ai_socktype = SOCK_STREAM;
         hints.ai_flags = AI_PASSIVE;
-        if (getaddrinfo(test->bind_address, portstr, &hints, &res) != 0) {
+        if ((gerror = getaddrinfo(test->bind_address, portstr, &hints, &res)) != 0) {
             i_errno = IESTREAMLISTEN;
             return -1;
         }
@@ -375,7 +375,7 @@
         memset(&hints, 0, sizeof(hints));
         hints.ai_family = test->settings->domain;
         hints.ai_socktype = SOCK_STREAM;
-        if (getaddrinfo(test->bind_address, NULL, &hints, &local_res) != 0) {
+        if ((gerror = getaddrinfo(test->bind_address, NULL, &hints, &local_res)) != 0) {
             i_errno = IESTREAMCONNECT;
             return -1;
         }
@@ -385,7 +385,7 @@
     hints.ai_family = test->settings->domain;
     hints.ai_socktype = SOCK_STREAM;
     snprintf(portstr, sizeof(portstr), "%d", test->server_port);
-    if (getaddrinfo(test->server_hostname, portstr, &hints, &server_res) != 0) {
+    if ((gerror = getaddrinfo(test->server_hostname, portstr, &hints, &server_res)) != 0) {
 	if (test->bind_address)
 	    freeaddrinfo(local_res);
         i_errno = IESTREAMCONNECT;
diff --git a/src/main.c b/src/main.c
index 9d72d77..fe10a2f 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,5 +1,5 @@
 /*
- * iperf, Copyright (c) 2014, 2015, 2017, The Regents of the University of
+ * iperf, Copyright (c) 2014, 2015, 2017, 2019, 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.
@@ -157,8 +157,13 @@
 		    }
                 }
                 iperf_reset_test(test);
-                if (iperf_get_test_one_off(test))
-                    break;
+                if (iperf_get_test_one_off(test)) {
+		    /* Authentication failure doesn't count for 1-off test */
+		    if (rc < 0 && i_errno == IEAUTHTEST) {
+			continue;
+		    }
+		    break;
+		}
             }
 	    iperf_delete_pidfile(test);
             break;
diff --git a/src/net.c b/src/net.c
index fd525ee..96fb7ed 100644
--- a/src/net.c
+++ b/src/net.c
@@ -1,5 +1,5 @@
 /*
- * iperf, Copyright (c) 2014-2018, The Regents of the University of
+ * iperf, Copyright (c) 2014-2019, 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.
@@ -65,6 +65,13 @@
 #include "timer.h"
 
 /*
+ * Declaration of gerror in iperf_error.c.  Most other files in iperf3 can get this
+ * by including "iperf.h", but net.c lives "below" this layer.  Clearly the
+ * presence of this declaration is a sign we need to revisit this layering.
+ */
+extern int gerror;
+
+/*
  * timeout_connect adapted from netcat, via OpenBSD and FreeBSD
  * Copyright (c) 2001 Eric Jackson <ericj@monkey.org>
  */
@@ -122,14 +129,14 @@
         memset(&hints, 0, sizeof(hints));
         hints.ai_family = domain;
         hints.ai_socktype = proto;
-        if (getaddrinfo(local, NULL, &hints, &local_res) != 0)
+        if ((gerror = getaddrinfo(local, NULL, &hints, &local_res)) != 0)
             return -1;
     }
 
     memset(&hints, 0, sizeof(hints));
     hints.ai_family = domain;
     hints.ai_socktype = proto;
-    if (getaddrinfo(server, NULL, &hints, &server_res) != 0)
+    if ((gerror = getaddrinfo(server, NULL, &hints, &server_res)) != 0)
         return -1;
 
     s = socket(server_res->ai_family, proto, 0);
@@ -238,7 +245,7 @@
     }
     hints.ai_socktype = proto;
     hints.ai_flags = AI_PASSIVE;
-    if (getaddrinfo(local, portstr, &hints, &res) != 0)
+    if ((gerror = getaddrinfo(local, portstr, &hints, &res)) != 0)
         return -1; 
 
     s = socket(res->ai_family, proto, 0);