Merge tag '3.7' into HEAD

This removes a bunch of workarounds which are no longer necessary,
greatly reducing the diff between us and upstream. The diffstat is now:

  .gitignore                   |   2 --
  BUILD.gn                     |  93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  README.fuchsia               |  19 +++++++++++++++++++
  meta/iperf3.cmx              |  13 +++++++++++++
  src/fuchsia/fuchsia-compat.c | 174 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  src/fuchsia/fuchsia-compat.h |  16 ++++++++++++++++
  src/iperf_api.c              |   2 ++
  src/iperf_client_api.c       |   7 +++++++
  src/iperf_config.h           | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  src/iperf_sctp.c             |   5 +++++
  src/iperf_server_api.c       |  10 ++++++++++
  src/iperf_tcp.c              |   5 +++++
  src/iperf_util.c             |  30 ++++++++++++++++++++++++++++++
  src/main.c                   |   3 ++-
  src/net.c                    |   5 +++++
  src/version.h                |  27 +++++++++++++++++++++++++++
  16 files changed, 529 insertions(+), 3 deletions(-)

which should make future merges simpler.

Test:
  as client: fx shell iperf3 -c fe80::2bb1:ddd5:10c7:d54e%2
  as server: fx shell iperf3 -s -6 # exercises IPV6_ONLY

Change-Id: I9fb62d791c9ed4420692fc9e75fe7a01ff3e0372
diff --git a/.gitignore b/.gitignore
index 424b143..5d34faa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,8 +16,6 @@
 src/.deps
 src/.libs
 src/Makefile
-src/iperf_config.h
-src/version.h
 src/stamp-h1
 src/iperf3
 src/iperf3_profile
diff --git a/BUILD.gn b/BUILD.gn
new file mode 100644
index 0000000..29779e6
--- /dev/null
+++ b/BUILD.gn
@@ -0,0 +1,93 @@
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import("//build/package.gni")
+
+package("iperf") {
+  meta = [
+    {
+      path = "meta/iperf3.cmx"
+      dest = "iperf3.cmx"
+    },
+  ]
+
+  deps = [ ":iperf3" ]
+
+  binaries = [
+    {
+      name = "iperf3"
+      shell = true
+    },
+  ]
+}
+
+config("iperf_config") {
+  visibility = [ ":*" ]
+  include_dirs = [ "src" ]
+}
+
+source_set("fuchsia-compat") {
+  sources = [ "src/fuchsia/fuchsia-compat.c" ]
+  public_deps = [ "//zircon/public/lib/fdio" ]
+}
+
+executable("iperf3") {
+  sources = [
+    "src/cjson.c",
+    "src/dscp.c",
+    "src/iperf_api.c",
+    "src/iperf_auth.c",
+    "src/iperf_client_api.c",
+    "src/iperf_error.c",
+    "src/iperf_locale.c",
+    "src/iperf_server_api.c",
+    "src/iperf_tcp.c",
+    "src/iperf_time.c",
+    "src/iperf_udp.c",
+    "src/iperf_util.c",
+    "src/main.c",
+    "src/net.c",
+    "src/tcp_info.c",
+    "src/timer.c",
+    "src/units.c",
+  ]
+  defines = [
+    "_BSD_SOURCE",
+    "_POSIX_C_SOURCE=200809L",
+  ]
+  cflags_c = [
+    "-Wno-format",
+    "-Wno-implicit-int-float-conversion",
+    "-Wno-int-conversion",
+    "-Wno-pointer-sign",
+    "-Wno-sign-compare",
+  ]
+  libs = [ "zircon" ]
+  deps = [ ":fuchsia-compat" ]
+}
diff --git a/README.fuchsia b/README.fuchsia
new file mode 100644
index 0000000..7d5dab2
--- /dev/null
+++ b/README.fuchsia
@@ -0,0 +1,19 @@
+Modifications from upstream for Fuchsia compatibility
+-------
+* Use Fuchsia specific random in iperf_util.c
+* Shim rusage in iperf_util.c
+* Avoid sys/resource.h imports
+
+Testing Changes
+-------
+Common commands to ensure that things are working correctly
+
+### Server side: ###
+iperf3 -s -4 #Starts a server with IPV4 only
+
+### Client side: ###
+iperf3 -c <host ip> #Short 10-second max-rate TCP test
+iperf3 -c <host ip> -b 20M #20Mbps 'good-put'
+iperf3 -c <host ip> -P 40 #40 streams in parallel, max rate TCP
+
+Also try using the -R option to reverse the data flow
diff --git a/meta/iperf3.cmx b/meta/iperf3.cmx
new file mode 100644
index 0000000..a534e9a
--- /dev/null
+++ b/meta/iperf3.cmx
@@ -0,0 +1,13 @@
+{
+    "program": {
+        "binary": "bin/iperf3"
+    },
+    "sandbox": {
+        "features": [
+            "isolated-temp"
+        ],
+        "services": [
+            "fuchsia.posix.socket.Provider"
+        ]
+    }
+}
diff --git a/src/fuchsia/fuchsia-compat.c b/src/fuchsia/fuchsia-compat.c
new file mode 100644
index 0000000..85f956d
--- /dev/null
+++ b/src/fuchsia/fuchsia-compat.c
@@ -0,0 +1,174 @@
+// Copyright 2019 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <assert.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <lib/fdio/fd.h>
+#include <lib/fdio/io.h>
+#include <lib/fdio/spawn.h>
+#include <lib/fdio/unsafe.h>
+#include <zircon/syscalls.h>
+#include <zircon/syscalls/port.h>
+
+// This is a very inefficient way to emulate select() by creating a port, adding all of the fds
+// of interest as async waits, and blocking until we get a port packet back.
+// The callers of this (like serverloop) generally have a static set of fds they care about, so
+// it'd be much more efficient for them to register async waits on a port object that persists
+// across blocking calls.
+int fuchsia_select(int nfds, void* readfds, void* writefds, struct timeval *timeout) {
+	fd_set* readfds_fd_set = (fd_set*) readfds;
+	fd_set* writefds_fd_set = (fd_set*) writefds;
+
+	int ret = 0;
+	zx_handle_t port = ZX_HANDLE_INVALID;
+	fdio_t* ios[FD_SETSIZE] = { 0 };
+
+	// Create a fresh port for this wait.
+	zx_status_t st = zx_port_create(0, &port);
+
+	if (st != ZX_OK) {
+		fprintf(stderr, "Can't allocate new port.\n");
+		errno = EINVAL;
+		ret = -1;
+		goto cleanup;
+	}
+
+
+	// Register port waits for file descriptors in the read and write sets.
+	for (int fd = 0; fd < nfds; ++fd) {
+		uint32_t events = 0;
+		if (readfds_fd_set && FD_ISSET(fd, readfds_fd_set)) {
+			events |= POLLIN;
+		}
+		if (writefds_fd_set && FD_ISSET(fd, writefds_fd_set)) {
+			events |= POLLOUT;
+		}
+		if (!events)
+			continue;
+
+		fdio_t* io;
+		// This acquires a reference to the fdio which is released in the cleanup path below.
+		if ((io = fdio_unsafe_fd_to_io(fd)) == NULL) {
+			errno = EBADF;
+			ret = -1;
+			goto cleanup;
+		}
+		ios[fd] = io;
+		zx_handle_t h;
+		zx_signals_t sigs;
+		// Translate the poll-style events to fdio-specific signal bits to wait on.
+		fdio_unsafe_wait_begin(io, events, &h, &sigs);
+		if (h == ZX_HANDLE_INVALID) {
+			errno = EBADF;
+			ret = -1;
+			goto cleanup;
+		}
+		uint64_t key = fd;
+		st = zx_object_wait_async(h, port, key, sigs, ZX_WAIT_ASYNC_ONCE);
+		if (st != ZX_OK) {
+			fprintf(stderr, "Can't wait on object %d.\n", st);
+			errno = EINVAL;
+			ret = -1;
+			goto cleanup;
+		}
+	}
+
+	zx_time_t deadline = (timeout == NULL) ? ZX_TIME_INFINITE :
+			zx_deadline_after(ZX_SEC(timeout->tv_sec) + ZX_USEC(timeout->tv_usec));
+
+	for (;;) {
+		zx_port_packet_t packet;
+		st = zx_port_wait(port, deadline, &packet);
+
+		// We expect zx_port_wait to return either ZX_ERR_TIMED_OUT if nothing happened, or ZX_OK
+		// if at least one thing happened.
+		if (st == ZX_OK) {
+			if (packet.type != ZX_PKT_TYPE_SIGNAL_ONE) {
+				fprintf(stderr, "Unexpected port packet type %u\n", packet.type);
+				errno = EINVAL;
+				ret = -1;
+				goto cleanup;
+			}
+			// We've heard about an fd in the set we care about. Update the read/write
+			// sets to reflect this information, then remove them from the set we are
+			// listening to.
+			int fd = (int)packet.key;
+			uint32_t events = 0;
+			fdio_t* io = ios[fd];
+			if (!io) {
+				fprintf(stderr, "Can't find fd for packet key %d.\n", fd);
+				errno = EINVAL;
+				ret = -1;
+				goto cleanup;
+			}
+			// fdio_unsafe_wait_end translates the signals back to poll-style flags.
+			fdio_unsafe_wait_end(io, packet.signal.observed, &events);
+			if (readfds_fd_set && FD_ISSET(fd, readfds_fd_set)) {
+				if (events & POLLIN)
+					ret++;
+				else
+					FD_CLR(fd, readfds_fd_set);
+			}
+			if (writefds_fd_set && FD_ISSET(fd, writefds_fd_set)) {
+				if (events & POLLOUT)
+					ret++;
+				else
+					FD_CLR(fd, writefds_fd_set);
+			}
+			// The read and write sets for this fd are now updated, and our wait has expired, so
+			// remove this fd from the set of things we care about.
+			ios[fd] = NULL;
+			fdio_unsafe_release(io);
+		} else if (st == ZX_ERR_TIMED_OUT) {
+			break;
+		} else {
+			fprintf(stderr, "Port wait return unexpected error %d.\n", st);
+			errno = EINVAL;
+			ret = -1;
+			goto cleanup;
+		}
+
+		// After pulling the first packet out, poll without blocking by doing another wait with a
+		// deadline in the past. This will populate any other members of the read/write set that
+		// are ready to go now.
+		deadline = 0;
+	}
+
+	// If there are any entries left in ios at this point, we have not received a port packet
+	// indicating that those fds are readable or writable and so we should clear those from the
+	// read/write sets.
+	for (int fd = 0; fd < nfds; ++fd) {
+		if (ios[fd]) {
+			if (readfds_fd_set && FD_ISSET(fd, readfds_fd_set)) {
+				FD_CLR(fd, readfds_fd_set);
+			}
+			if (writefds_fd_set && FD_ISSET(fd, writefds_fd_set)) {
+				FD_CLR(fd, writefds_fd_set);
+			}
+		}
+	}
+
+cleanup:
+	// Release reference to any fdio objects we acquired with fdio_unsafe_fd_to_io().
+	for (int fd = 0; fd < nfds; ++fd) {
+		if (ios[fd]) {
+			fdio_unsafe_release(ios[fd]);
+		}
+	}
+
+	if (port != ZX_HANDLE_INVALID) {
+		zx_handle_close(port);
+	}
+	return ret;
+}
diff --git a/src/fuchsia/fuchsia-compat.h b/src/fuchsia/fuchsia-compat.h
new file mode 100644
index 0000000..1ca0660
--- /dev/null
+++ b/src/fuchsia/fuchsia-compat.h
@@ -0,0 +1,16 @@
+// Copyright 2019 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#pragma once
+#include <zircon/types.h>
+
+struct timeval;
+
+// This implements the subset of select() functionality used by openssh.
+// Uses void* instead of fd_set* for the read/write fd sets since this compat
+// header is included in smult_curve25519_ref.c, which declares a completely
+// unrelated function called select(). Doesn't export exceptfds.
+int fuchsia_select(int nfds, void* readfds, void* writefds,
+                   struct timeval* timeout);
+
diff --git a/src/iperf_api.c b/src/iperf_api.c
index e1bbfa5..5c3f153 100755
--- a/src/iperf_api.c
+++ b/src/iperf_api.c
@@ -51,7 +51,9 @@
 #endif
 #include <netinet/tcp.h>
 #include <sys/time.h>
+#ifndef __Fuchsia__
 #include <sys/resource.h>
+#endif
 #include <sys/mman.h>
 #include <sys/stat.h>
 #include <sched.h>
diff --git a/src/iperf_client_api.c b/src/iperf_client_api.c
index 20ea6fd..b3efd99 100644
--- a/src/iperf_client_api.c
+++ b/src/iperf_client_api.c
@@ -44,6 +44,9 @@
 #include "iperf_time.h"
 #include "net.h"
 #include "timer.h"
+#ifdef __Fuchsia__
+#include "fuchsia/fuchsia-compat.h"
+#endif
 
 #if defined(HAVE_TCP_CONGESTION)
 #if !defined(TCP_CA_NAME_MAX)
@@ -489,7 +492,11 @@
 	memcpy(&write_set, &test->write_set, sizeof(fd_set));
 	iperf_time_now(&now);
 	timeout = tmr_timeout(&now);
+	#ifdef __Fuchsia__
+	result = fuchsia_select(test->max_fd + 1, &read_set, &write_set, timeout);
+	#else
 	result = select(test->max_fd + 1, &read_set, &write_set, NULL, timeout);
+	#endif
 	if (result < 0 && errno != EINTR) {
   	    i_errno = IESELECT;
 	    return -1;
diff --git a/src/iperf_config.h b/src/iperf_config.h
new file mode 100644
index 0000000..1e3afd1
--- /dev/null
+++ b/src/iperf_config.h
@@ -0,0 +1,121 @@
+/* src/iperf_config.h.  Generated by hand.  */
+
+/* Define to 1 if you have the `clock_gettime' function. */
+#define HAVE_CLOCK_GETTIME 1
+
+/* 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. */
+#undef HAVE_DAEMON
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the <endian.h> header file. */
+#define HAVE_ENDIAN_H 1
+
+/* Have IPv6 flowlabel support. */
+#undef HAVE_FLOWLABEL
+
+/* Define to 1 if you have the `getline' function. */
+#undef HAVE_GETLINE
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the <netinet/sctp.h> header file. */
+#define HAVE_NETINET_SCTP_H 1
+
+/* Define to 1 if you have the <poll.h> header file. */
+#define HAVE_POLL_H 1
+
+/* Define to 1 if you have the `sched_setaffinity' function. */
+#define HAVE_SCHED_SETAFFINITY 1
+
+/* Have SCTP support. */
+#undef HAVE_SCTP
+
+/* Define to 1 if you have the `sendfile' function. */
+#define HAVE_SENDFILE 1
+
+/* Define to 1 if you have the `SetProcessAffinityMask' function. */
+#undef HAVE_SETPROCESSAFFINITYMASK
+
+/* Have SO_MAX_PACING_RATE sockopt. */
+#define HAVE_SO_MAX_PACING_RATE 1
+
+/* OpenSSL Is Available */
+#undef HAVE_SSL
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if the system has the type `struct sctp_assoc_value'. */
+#define HAVE_STRUCT_SCTP_ASSOC_VALUE 1
+
+/* Define to 1 if you have the <sys/endian.h> header file. */
+#undef HAVE_SYS_ENDIAN_H
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Have TCP_CONGESTION sockopt. */
+#undef HAVE_TCP_CONGESTION
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to the sub-directory where libtool stores uninstalled libraries. */
+#define LT_OBJDIR ".libs/"
+
+/* Name of package */
+#define PACKAGE "iperf"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "https://github.com/esnet/iperf"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "iperf"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "iperf 3.7-FUCHSIA"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "iperf"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL "https://software.es.net/iperf/"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "3.7-FUCHSIA"
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Version number of package */
+#define VERSION "3.7-FUCHSIA"
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
diff --git a/src/iperf_sctp.c b/src/iperf_sctp.c
index 06e1e23..a3487a0 100644
--- a/src/iperf_sctp.c
+++ b/src/iperf_sctp.c
@@ -209,7 +209,12 @@
 #endif /* IPV6_V6ONLY */
 
     opt = 1;
+    // TODO(eyalsoha): Remove this when SO_REUSEADDR is supported.
+#if defined(__Fuchsia__)
+    if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)) < 0) {
+#else
     if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
+#endif
         saved_errno = errno;
         close(s);
         freeaddrinfo(res);
diff --git a/src/iperf_server_api.c b/src/iperf_server_api.c
index 40d99bc..41471cb 100644
--- a/src/iperf_server_api.c
+++ b/src/iperf_server_api.c
@@ -44,7 +44,9 @@
 #include <stdint.h>
 #endif
 #include <sys/time.h>
+#ifndef __Fuchsia__
 #include <sys/resource.h>
+#endif
 #include <sched.h>
 #include <setjmp.h>
 
@@ -59,6 +61,10 @@
 #include "units.h"
 #include "iperf_util.h"
 #include "iperf_locale.h"
+#ifdef __Fuchsia__
+#include "fuchsia/fuchsia-compat.h"
+#endif
+
 
 #if defined(HAVE_TCP_CONGESTION)
 #if !defined(TCP_CA_NAME_MAX)
@@ -442,7 +448,11 @@
 
 	iperf_time_now(&now);
 	timeout = tmr_timeout(&now);
+        #ifdef __Fuchsia__
+        result = fuchsia_select(test->max_fd + 1, &read_set, &write_set, timeout);
+        #else
         result = select(test->max_fd + 1, &read_set, &write_set, NULL, timeout);
+        #endif
         if (result < 0 && errno != EINTR) {
 	    cleanup_server(test);
             i_errno = IESELECT;
diff --git a/src/iperf_tcp.c b/src/iperf_tcp.c
index 232aaa1..d311831 100644
--- a/src/iperf_tcp.c
+++ b/src/iperf_tcp.c
@@ -259,7 +259,12 @@
 	}
     }
         opt = 1;
+        // TODO(eyalsoha): Remove this when SO_REUSEADDR is supported.
+#if defined(__Fuchsia__)
+        if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)) < 0) {
+#else
         if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
+#endif
 	    saved_errno = errno;
             close(s);
 	    freeaddrinfo(res);
diff --git a/src/iperf_util.c b/src/iperf_util.c
index 412397a..c456fae 100644
--- a/src/iperf_util.c
+++ b/src/iperf_util.c
@@ -40,7 +40,29 @@
 #include <sys/select.h>
 #include <sys/types.h>
 #include <sys/time.h>
+#ifndef __Fuchsia__
 #include <sys/resource.h>
+#else
+#include <zircon/syscalls.h>
+#include <time.h>
+// NB. rusage was removed from Fuchsia in
+// https://fuchsia.googlesource.com/fuchsia/+/67fec6d without replacement.
+#define RUSAGE_SELF CLOCK_PROCESS_CPUTIME_ID
+struct rusage {
+  struct timeval ru_utime;
+};
+static inline int getrusage(int who, struct rusage* ru) {
+  struct timespec ts;
+  int r = clock_gettime(who, &ts);
+  if (r) {
+    return r;
+  }
+  ru->ru_utime.tv_sec = ts.tv_sec;
+  ru->ru_utime.tv_usec = ts.tv_nsec/1000;
+  return 0;
+}
+#define ru_stime ru_utime
+#endif
 #include <sys/utsname.h>
 #include <time.h>
 #include <errno.h>
@@ -50,6 +72,7 @@
 #include "iperf.h"
 #include "iperf_api.h"
 
+#ifndef __Fuchsia__
 /*
  * Read entropy from /dev/urandom
  * Errors are fatal.
@@ -77,6 +100,13 @@
     }
     return 0;
 }
+#else
+int readentropy(void *out, size_t outsize)
+{
+  zx_cprng_draw(out, outsize);
+  return 0;
+}
+#endif
 
 
 /*
diff --git a/src/main.c b/src/main.c
index fe10a2f..87b36ac 100644
--- a/src/main.c
+++ b/src/main.c
@@ -44,9 +44,10 @@
 
 #include "iperf.h"
 #include "iperf_api.h"
-#include "units.h"
 #include "iperf_locale.h"
+#include "iperf_util.h"
 #include "net.h"
+#include "units.h"
 
 
 static int run(struct iperf_test *test);
diff --git a/src/net.c b/src/net.c
index 96fb7ed..2788648 100644
--- a/src/net.c
+++ b/src/net.c
@@ -255,7 +255,12 @@
     }
 
     opt = 1;
+    // TODO(eyalsoha): Remove this when SO_REUSEADDR is supported.
+#if defined(__Fuchsia__)
+    if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, 
+#else
     if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, 
+#endif
 		   (char *) &opt, sizeof(opt)) < 0) {
 	saved_errno = errno;
 	close(s);
diff --git a/src/version.h b/src/version.h
new file mode 100644
index 0000000..495af71
--- /dev/null
+++ b/src/version.h
@@ -0,0 +1,27 @@
+/*
+ * iperf, Copyright (c) 2014, The Regents of the University of
+ * California, through Lawrence Berkeley National Laboratory (subject
+ * to receipt of any required approvals from the U.S. Dept. of
+ * Energy).  All rights reserved.
+ *
+ * If you have questions about your rights to use or distribute this
+ * software, please contact Berkeley Lab's Technology Transfer
+ * Department at TTD@lbl.gov.
+ *
+ * NOTICE.  This software is owned by the U.S. Department of Energy.
+ * As such, the U.S. Government has been granted for itself and others
+ * acting on its behalf a paid-up, nonexclusive, irrevocable,
+ * worldwide license in the Software to reproduce, prepare derivative
+ * works, and perform publicly and display publicly.  Beginning five
+ * (5) years after the date permission to assert copyright is obtained
+ * from the U.S. Department of Energy, and subject to any subsequent
+ * five (5) year renewals, the U.S. Government is granted for itself
+ * and others acting on its behalf a paid-up, nonexclusive,
+ * irrevocable, worldwide license in the Software to reproduce,
+ * prepare derivative works, distribute copies to the public, perform
+ * publicly and display publicly, and to permit others to do so.
+ *
+ * This code is distributed under a BSD style license, see the LICENSE
+ * file for complete information.
+ */
+#define IPERF_VERSION "3-CURRENT"