1 /*
2  *	N U T T C P . C						v8.2.2
3  *
4  * Copyright(c) 2000 - 2018 Bill Fink.  All rights reserved.
5  * Copyright(c) 2003 - 2018 Rob Scott.  All rights reserved.
6  *
7  * nuttcp is free, opensource software.  You can redistribute it and/or
8  * modify it under the terms of Version 2 of the GNU General Public
9  * License (GPL), as published by the GNU Project (http://www.gnu.org).
10  * A copy of the license can also be found in the LICENSE file.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15  * for more details.
16  *
17  * Based on nttcp
18  * Developed by Bill Fink, billfink@mindspring.com
19  *          and Rob Scott, rob@hpcmo.hpc.mil
20  * Latest version available at:
21  *	http://nuttcp.net/nuttcp/beta/
22  *
23  * Test TCP connection.  Makes a connection on port 5000(ctl)/5101(data)
24  * and transfers fabricated buffers or data copied from stdin.
25  *
26  * Run nuttcp with no arguments to get a usage statement
27  *
28  * Modified for operation under 4.2BSD, 18 Dec 84
29  *      T.C. Slattery, USNA
30  * Minor improvements, Mike Muuss and Terry Slattery, 16-Oct-85.
31  *
32  * 8.2.2, Bill Fink, 5-Oct-18
33  *	Improve warning when third party "-4/-6" is not supported
34  *	Add af=inet/inet6 to verbose UDP output
35  *	Add ip=<server_ip> to verbose UDP output for client transmitter
36  * 8.2.1, Bill Fink, 3-Oct-18
37  *	Fix to pass "-4" or "-6" argument to 3rd party
38  * 8.1.4, Rob Scott, 1-Nov-16
39  *	Fix to allow compile with -Werror=format-security as noted by Dhiru Kholia in fedora bug 1037224
40  *	Fix missing brackets caught by -Wmisleading-indentation
41  *      Add code to print out address family of connect/accept
42  *      Add code to translate v4mapped addresses
43  * 8.1.3, Bill Fink, 9-Sep-16
44  *	Fix to allow direct I/O on block devices
45  *	Fix parsing of "-R i[s]##[/##]" (blank between 'R' and 'i')
46  *	Updated Copyright notice for new year
47  * 8.1.2, Bill Fink, 5-Sep-16
48  *	Fix to not exercise 8.0.1 and 8.1.1 features for non-Linux systems
49  *	Changed nuttcp site to http://nuttcp.net/nuttcp/beta/
50  *	Added define test for NOT_LINUX to undefine LINUX for build testing
51  * 8.1.1, Bill Fink, 31-Aug-16
52  *	Add "-Ris##" option to emulate smoothed slow start behavior (Linux only)
53  * 8.0.1, Bill Fink, 22-Aug-16
54  *	Add reporting of TCP congestion window
55  * 7.3.4, Rob Scott & Bill Fink, 18-Jul-16
56  *	Use clock_gettime() on Windows/CYGWIN and Linux (if available)
57  * 7.3.3, Rob Scott, 1-May-15
58  *	Fix tos to work for ipv6 by setting traffic class
59  * 7.3.2, Bill Fink, 3-Aug-14
60  *	Allow longer server info timeout for third party via --idle-data-timeout
61  * 7.3.1, Bill Fink, 27-Jul-14
62  *	Added feature to specify source port with "-p#:#" and "-P#:#"
63  *	Updated Copyright notice for new year
64  * 7.2.2, Bill Fink, 25-May-13
65  *	Fix Linux bug of exceeding MAX_EOT_WAIT_SEC on lossy large RTT path
66  *	with large window causing false "Error: receiver not ACKing data"
67  *	Change Linux method for draining socket send queue at EOT while waiting
68  *	for any TCP retransmissions to complete - instead of checking
69  *	tcpi_unacked value from TCP_INFO getsockopt() use SIOCOUTQ ioctl()
70  *	(new error message is "Error: timeout while draining socket send queue")
71  * 7.2.1, Bill Fink, 26-Dec-12
72  *	Add "-g" option to specify multicast IP address to use
73  *	Clean up really confused transmit code for IPv4/IPv6 SSM multicast
74  *	Bug fix from Aristeu Rozanski:
75  *	    Crash caused by closing TCP_ADV_WIN_SCALE file even if open failed
76  * 7.1.6, Bill Fink, 25-Feb-12
77  *	Add "-sd" direct I/O option for non-sinkmode (Linux only)
78  *	Fix bug with server CPU affinity being parsed as %X instead of %d
79  *	For non-sinkmode insure complete network block is written to stdout
80  *	Above fixes nuttscp bug seen with --copy-dir getting premature EOF
81  *	Updated Copyright notice for new year
82  *	Whitespace style cleanups
83  * 7.1.5, Rob Scott, 19-Jul-11
84  *	Not every system has ERESTART added in 7.1.4, wrapped in ifdef
85  * 7.1.4, Bill Fink, 30-May-11
86  *	Updated Copyright notice
87  *	Use -DHAVE_SS_FAMILY to override _AIX workaround for newer AIX
88  *	AIX can get ERESTART rather than EINTR/EAGAIN error on interrupted I/O
89  *	Fix non-Linux systems to properly count TCP retrans for multiple streams
90  *	Allow xinetd nuttcp server to handle both IPv4 & IPv6 if no explicitaf
91  *	Detect EOD for non-sinkmode UDP transfers
92  *	Suppress bogus warning when using maximum size UDP packet
93  * 7.1.3, Bill Fink, 1-Apr-10
94  *	Fix compiler warnings generated by Ubuntu 9.x gcc 4.3.x/4.4.x versions
95  *	(to see warnings compile with -DWANT_WUR)
96  * 7.1.2, Bill Fink, 23-Jan-10
97  *	Updated Copyright notice
98  *	Terminate non-sinkmode after specified file size with "-n" option
99  *	Allow multilink aggregation with "-N##m" option to work for receive
100  *	Add "-sz" zero copy option for non-sinkmode when input is a regular file
101  *	Fix compiler warnings about strict-aliasing rules for variable group
102  *	Remove "-Sf" forced server mode from Usage: statement
103  *	Fix zeroing of clientaddr6 during server cleanup
104  *	Fix freeaddrinfo() processing during cleanup
105  *	Change manually started oneshot server to have parent process just exit
106  *	Some minor whitespace cleanup
107  * 7.1.1, Bill Fink, 24-Dec-09
108  *	Provide summary TCP retrans info for multi-stream TCP
109  *	Fix bug with retrans interval info when -fparse
110  *	Add "+stride" or "+n.n.n.n" syntax for multi-stream TCP (IPv4)
111  *	Fix third party bug with "-xc" option adding extraneous 't' character
112  *	Add optional client-side name resolution for third party host
113  *	Add "-N##m" option for multilink aggregation for multiple streams
114  *	Add "-xc#/#" and "-P#/#" options to Usage: statement
115  *	Some minor whitespace cleanup
116  * 7.0.1, Bill Fink, 18-Sep-09
117  *	Enable jitter measurements with "-j" option
118  *	Enable one-way delay measurements with "-o" option
119  *	Fix bug with RTT and -fparse
120  * 6.2.10, Bill Fink, 1-Aug-09
121  *	Change ctl/data port checks to < 1024 instead of < 5000
122  *	Fix "--idle-data-timeout" Usage: statement for new default minimum
123  *	Improve transmit performance with "-i" by setting poll() timeout to 0
124  *	Remove commented out code for unused normal_eod
125  *	Don't output interval retrans info if non-sinkmode (for nuttscp)
126  * 6.2.9, Bill Fink, 24-Jun-09
127  *	Make retrans info reporting work again on newer Linux distros
128  *	Skip check for unACKed data at end of transfer if -DBROKEN_UNACKED
129  * 6.2.8, Bill Fink, 8-Jun-09
130  *	Play nice with iperf (change default data port to 5101)
131  *	Delay sending of server "OK" until after successful server bind()
132  *	Client check for server errors before starting data transfer
133  *	Continue checking for server output while draining client transmission
134  *	Correct "server not ACKing data" error message (server -> receiver)
135  *	Add "--packet-burst" option for Rob
136  *	Fix "--idle-data-timeout" Usage: statement for client
137  *	Improve accuracy of retrans info timing synchronization (client xmitter)
138  *	Change reference to nuttcp repository from ftp:// to http://
139  *	Fix bug affecting nuttscp introduced in 6.2.4 (not honoring oneshot)
140  *	Whitespace cleanup: get rid of <tab><spaces><tab>, <tab>$, & <spaces>$
141  *	Whitespace cleanup: convert 8 spaces to <tab> where appropriate
142  * 6.2.7, Bill Fink, 22-May-09
143  *	Allow rate limit to be exceeded temporarily by n packets ("-Rixxx/n")
144  *	Fix several reqval parameter settings
145  * 6.2.6, Bill Fink, 17-Apr-09
146  *	Allow setting server CPU affinity from client via "-xcs" option
147  *	Allow setting client & server CPU affinity via third party
148  *	Fix bug with option processing when reqval is set
149  * 6.2.5, Bill Fink, 16-Apr-09
150  *	Allow passing of third party control port via "-Pctlport/ctlport3"
151  *	Up default idle data minimum to 15 sec to better handle net transients
152  *	Don't reset nstream until after last use (fix getaddrinfo() memory leak)
153  * 6.2.4, Bill Fink, 10-Apr-09
154  *	Fix bug with simultaneous server connections to manually started server
155  * 6.2.3, Bill Fink, 5-Apr-09
156  *	Add "-xc" option to set CPU affinity (Linux only)
157  *	Fix Usage: statement: "--idle-data-timeout" both server & client option
158  *	Don't reset priority on server cleanup
159  *	Fix priority output for "-fparse"
160  * 6.2.2, Bill Fink, 3-Apr-09
161  *	Fix bad third party bug causing >= 1 minute transfers to silently fail
162  *	Fix Usage: statement: "--idle-data-timeout" not just a server option
163  * 6.2.1, Rob Scott, 22-Mar-09
164  *	Added IPv6 and SSM MC support
165  *	Ported from Rob's 5.5.5 based code by Bill Fink
166  * 6.1.5, Bill Fink, 5-Mar-09
167  *	Fix client lockup with third party when network problem (for scripts)
168  * 6.1.4, Bill Fink, 5-Jan-09
169  *	Updated Copyright notice
170  *	Bugfix: set chk_idle_data on client (now also checks no data received)
171  *	Use argv[0] instead of "nuttcp" for third party
172  *	Bugfix: give error message again on error starting server
173  * 6.1.3, Bill Fink, 17-Sep-08
174  *	Timeout client accept() too and give nice error message (for scripts)
175  * 6.1.2, Bill Fink, 29-Aug-08
176  *	Don't wait forever for unacked data at EOT (limit to 1 minute max)
177  *	Extend no data received protection to client too (for scripts)
178  *	Give nice error messages to client for above cases
179  *	Don't hang getting server info if server exited (timeout reads)
180  * 6.1.1, Bill Fink, 26-Aug-08
181  *	Remove beta designation
182  *	Report RTT by default (use "-f-rtt" to suppress)
183  *	Moved RTT info to "connect to" line
184  *	Correct bogus IP frag warning for e.g. "-l1472" or "-l8972"
185  *	Don't report interval host-retrans if no data rcvd (e.g. initial PMTU)
186  *	Correct reporting of retrans info with "-fparse" option
187  *	Correct reporting of RTT with "-F" flip option
188  *	Report doubled send and receive window sizes (for Linux)
189  *	Add report of available send and receive window sizes (for Linux)
190  *	Touchup TODO list to remove some already completed items
191  * 6.0.7, Bill Fink, 19-Aug-08
192  *	Add delay (default 0.5 sec) to "-a" option & change max retries to 10
193  *	Updated Copyright notice
194  * 6.0.6, Bill Fink, 11-Aug-08
195  *	Delay server forking until after listen() for better error status
196  *	Above suggested by Hans Blom (jblom@science.uva.nl)
197  *	Make forced server mode the default behavior
198  *	Check address family on getpeername() so "ssh host nuttcp -S" works
199  *	Add setsid() call for manually started server to create new session
200  *	Some minor code cleanup
201  * 6.0.5, Bill Fink, 10-Aug-08
202  *	Allow "-s" from/to stdin/stdout with "-1" oneshot server mode
203  *	Switch beta vers message to stderr to not interfere with "-s" option
204  *	Don't set default timeout if "-s" specified
205  *	Give error message for "-s" with "-S" (xinetd or manually started)
206  * 6.0.4, Bill Fink, 18-Jul-08
207  *	Forgot about 3rd party support for RTT info - fix that
208  * 6.0.3, Bill Fink, 17-Jul-08
209  *	A better (and accurate) way to get RTT info (and not just Linux)
210  * 6.0.2, Bill Fink, 16-Jul-08
211  *	Add RTT info to brief output for Linux
212  * 6.0.1, Bill Fink, 17-Dec-07
213  *	Add reporting of TCP retransmissions (interval reports on Linux TX only)
214  *	Add reporting of data transfer RTT for verbose Linux output
215  *	Add beta version messages and "-f-beta" option to suppress
216  *	Automatically switch "classic" mode to oneshot server mode
217  *	Fix UDP loss info bug not updating stream_idx when not need_swap
218  *	Fix compiler warning doing sprintf of timeout
219  *	Correct comment on NODROPS define
220  * 5.5.5, Bill Fink, 1-Feb-07
221  *	Change default MC addr to be based on client addr instead of xmit addr
222  * 5.5.4, Bill Fink, 3-Nov-06
223  *	Fix bug with negative loss causing huge drop counts on interval reports
224  *	Updated Copyright notice and added GPL license notice
225  * 5.5.3, Bill Fink, 23-Oct-06
226  *	Fix bug with "-Ri" instantaneous rate limiting not working properly
227  * 5.5.2, Bill Fink, 25-Jul-06
228  *	Make manually started server multi-threaded
229  *	Add "--single-threaded" server option to restore old behavior
230  *	Add "-a" client option to retry a failed server connection "again"
231  *	(for certain possibly transient errors)
232  * 5.5.1, Bill Fink, 22-Jul-06
233  *	Fix bugs with nbuf_bytes and rate_pps used with 3rd party
234  *	Pass "-D" option to server (and also make work for third party)
235  *	Allow setting precedence with "-c##p"
236  * 5.4.3, Rob Scott & Bill Fink, 17-Jul-06
237  *	Fix bug with buflen passed to server when no buflen option speicified
238  *	(revert 5.3.2: Fix bug with default UDP buflen for 3rd party)
239  *	Better way to fix bug with default UDP buflen for 3rd party
240  *	Trim trailing '\n' character from err() calls
241  *	Use fcntl() to set O_NONBLOCK instead of MSG_DONTWAIT to send() ABORT
242  *	(and remove MSG_DONTWAIT from recv() because it's not needed)
243  *	Don't re-initialize buflen at completion of server processing
244  *	(non inetd: is needed to check for buffer memory allocation change,
245  *	caused bug if smaller "-l" followed by larger default "-l")
246  * 5.4.2, Bill Fink, 1-Jul-06
247  *	Fix bug with interrupted UDP receive reporting negative packet loss
248  *	Make sure errors (or debug) from server are propagated to the client
249  *	Make setsockopt SO_SNDBUF/SO_RCVBUF error not be fatal to server
250  *	Don't send stderr to client if nofork is set (manually started server)
251  * 5.4.1, Bill Fink, 30-Jun-06
252  *	Fix bug with UDP reporting > linerate because of bad correction
253  *	Send 2nd UDP BOD packet in case 1st is lost, e.g. waiting for ARP reply
254  *	(makes UDP BOD more robust for new separate control and data paths)
255  *	Fix bug with interval reports after EOD for UDP with small interval
256  *	Don't just exit inetd server on no data so can get partial results
257  *	(keep an eye out that servers don't start hanging again)
258  *	Make default idle data timeout 1/2 of timeout if interval not set
259  *	(with a minimum of 5 seconds and a maximum of 60 seconds)
260  *	Make server send abort via urgent TCP data if no UDP data received
261  *	(non-interval only: so client won't keep transmitting for full period)
262  *	Workaround for Windows not handling TCP_MAXSEG getsockopt()
263  * 5.3.4, Bill Fink, 21-Jun-06
264  *	Add "--idle-data-timeout" server option
265  *	(server ends transfer if no data received for the specified
266  *	timeout interval, previously it was a fixed 60 second timeout)
267  *	Shutdown client control connection for writing at end of UDP transfer
268  *	(so server can cope better with loss of all EOD packets, which is
269  *	mostly of benefit when using separate control and data paths)
270  * 5.3.3, Bill Fink & Mark S. Mathews, 18-Jun-06
271  *	Add new capability for separate control and data paths
272  *	(using syntax:  nuttcp ctl_name_or_IP/data_name_or_IP)
273  *	Extend new capability for multiple independent data paths
274  *	(using syntax:  nuttcp ctl/data1/data2/.../datan)
275  *	Above only supported for transmit or flipped/reversed receive
276  *	Fix -Wall compiler warnings on 64-bit systems
277  *	Make manually started server also pass stderr to client
278  *	(so client will get warning messages from server)
279  * 5.3.2, Bill Fink, 09-Jun-06
280  *	Fix bug with default UDP buflen for 3rd party
281  *	Fix compiler warnings with -Wall on FreeBSD
282  *	Give warning that windows doesn't support TCP_MAXSEG
283  * 5.3.1, Rob Scott, 06-Jun-06
284  *	Add "-c" COS option for setting DSCP/TOS setting
285  *	Fix builds on latest MacOS X
286  *	Fix bug with 3rd party unlimited rate UDP not working
287  *	Change "-M" option to require a value
288  *	Fix compiler warnings with -Wall (thanks to Daniel J Blueman)
289  *	Remove 'v' from nuttcp version (simplify RPM packaging)
290  * V5.2.2, Bill Fink, 13-May-06
291  *	Have client report server warnings even if not verbose
292  * V5.2.1, Bill Fink, 12-May-06
293  *	Pass "-M" option to server so it also works for receives
294  *	Make "-uu" be a shortcut for "-u -Ru"
295  * V5.1.14, Bill Fink, 11-May-06
296  *	Fix cancellation of UDP receives to work properly
297  *	Allow easy building without IPv6 support
298  *	Set default UDP buflen to largest 2^n less than MSS of ctlconn
299  *	Add /usr/local/sbin and /usr/etc to path
300  *	Allow specifying rate in pps by using 'p' suffix
301  *	Give warning if actual send/receive window size is less than requested
302  *	Make UDP transfers have a default rate limit of 1 Mbps
303  *	Allow setting MSS for client transmitter TCP transfers with "-M" option
304  *	Give more precision on reporting small UDP percentage data loss
305  *	Disallow UDP transfers in "classic" mode
306  *	Notify when using "classic" mode
307  * V5.1.13, Bill Fink, 8-Apr-06
308  *	Make "-Ri" instantaneous rate limit for very high rates more accurate
309  *	(including compensating for microsecond gettimeofday() granularity)
310  *	Fix bug giving bogus time/stats on UDP transmit side with "-Ri"
311  *	Allow fractional rate limits (for 'm' and 'g' only)
312  * V5.1.12, Bill Fink & Rob Scott, 4-Oct-05
313  *	Terminate server receiver if client control connection goes away
314  *	or if no data received from client within CHECK_CLIENT_INTERVAL
315  * V5.1.11, Rob Scott, 25-Jun-04
316  *	Add support for scoped ipv6 addresses
317  * V5.1.10, Bill Fink, 16-Jun-04
318  *	Allow 'b' suffix on "-w" option to specify window size in bytes
319  * V5.1.9, Bill Fink, 23-May-04
320  *	Fix bug with client error on "-d" option putting server into bad state
321  *	Set server accept timeout (currently 5 seconds) to prevent stuck server
322  *	Add nuttcp version info to error message from err() exit
323  * V5.1.8, Bill Fink, 22-May-04
324  *	Allow 'd|D' suffix to "-T" option to specify days
325  *	Fix compiler warning about unused variable cp in getoptvalp routine
326  *	Interval value check against timeout value should be >=
327  * V5.1.7, Bill Fink, 29-Apr-04
328  *	Drop "-nb" option in favor of "-n###[k|m|g|t|p]"
329  * V5.1.6, Bill Fink, 25-Apr-04
330  *	Fix bug with using interval option without timeout
331  * V5.1.5, Bill Fink, 23-Apr-04
332  *	Modification to allow space between option parameter and its value
333  *	Permit 'k' or 'm' suffix on "-l" option
334  *	Add "-nb" option to specify number of bytes to transfer
335  *	Permit 'k', 'm', 'g', 't', or 'p' suffix on "-n" and "-nb" options
336  * V5.1.4, Bill Fink, 21-Apr-04
337  *	Change usage statement to use standard out instead of standard error
338  *	Fix bug with interval > timeout, give warning and ignore interval
339  *	Fix bug with counting error value in nbytes on interrupted transfers
340  *	Fix bug with TCP transmitted & received nbytes not matching
341  *	Merge "-t" and "-r" options in Usage: statement
342  * V5.1.3, Bill Fink, 9-Apr-04
343  *	Add "-Sf" force server mode (useful for starting server via rsh/ssh)
344  *	Allow non-root user to find nuttcp binary in "."
345  *	Fix bug with receives terminating early with manual server mode
346  *	Fix bug with UDP receives not terminating with "-Ri" option
347  *	Clean up output formatting of nbuf (from "%d" to "%llu")
348  *	Add "-SP" to have 3rd party use same outgoing control port as incoming
349  * V5.1.2, Bill Fink & Rob Scott, 18-Mar-04
350  *	Fix bug with nbuf wrapping on really long transfers (int -> uint64_t)
351  *	Fix multicast address to be unsigned long to allow shift
352  *	Add MacOS uint8_t definition for new use of uint8_t
353  * V5.1.1, Bill Fink, 8-Nov-03
354  *	Add IPv4 multicast support
355  *	Delay receiver EOD until EOD1 (for out of order last data packet)
356  *	Above also drains UDP receive buffer (wait for fragmentation reassembly)
357  * V5.0.4, Bill Fink, 6-Nov-03
358  *	Fix bug reporting 0 drops when negative loss percentage
359  * V5.0.3, Bill Fink, 6-Nov-03
360  *	Kill server transmission if control connection goes away
361  *	Kill 3rd party nuttcp if control connection goes away
362  * V5.0.2, Bill Fink, 4-Nov-03
363  *	Fix bug: some dummy wasn't big enough :-)
364  * V5.0.1, Bill Fink, 3-Nov-03
365  *	Add third party support
366  *	Correct usage statement for "-xt" traceroute option
367  *	Improved error messages on failed options requiring client/server mode
368  * V4.1.1, David Lapsley and Bill Fink, 24-Oct-03
369  *	Added "-fparse" format option to generate key=value parsable output
370  *	Fix bug: need to open data connection on abortconn to clear listen
371  * V4.0.3, Rob Scott, 13-Oct-03
372  *	Minor tweaks to output format for alignment
373  *	Interval option "-i" with no explicit value sets interval to 1.0
374  * V4.0.2, Bill Fink, 10-Oct-03
375  *	Changed "-xt" option to do both forward and reverse traceroute
376  *	Changed to use brief output by default ("-v" for old default behavior)
377  * V4.0.1, Rob Scott, 10-Oct-03
378  *	Added IPv6 code
379  *	Changed inet get functions to protocol independent versions
380  *	Added fakepoll for hosts without poll() (macosx)
381  *	Added ifdefs to only include setprio if os supports it (non-win)
382  *	Added bits to handle systems without new inet functions (solaris < 2.8)
383  *	Removed SYSV obsolete code
384  *	Added ifdefs and code to handle cygwin and beginning of windows support
385  *	Window size can now be in meg (m|M) and gig (g|G)
386  *	Added additional directories to search for traceroute
387  *	Changed default to transmit, time limit of 10 seconds, no buffer limit
388  *	Added (h|H) as option to specify time in hours
389  *	Added getservbyname calls for port, if all fails use old defaults
390  *	Changed sockaddr to sockaddr_storage to handle v6 addresses
391  * v3.7.1, Bill Fink, 10-Aug-03
392  *	Add "-fdebugpoll" option to help debug polling for interval reporting
393  *	Fix Solaris compiler warning
394  *	Use poll instead of separate process for interval reports
395  * v3.6.2, Rob Scott, 18-Mar-03
396  *	Allow setting server window to use default value
397  *	Cleaned out BSD42 old code
398  *	Marked SYSV code for future removal as it no longer appears necessary
399  *	Also set RCVBUF/SNDBUF for udp transfers
400  *	Changed transmit SO_DEBUG code to be like receive
401  *	Some code rearrangement for setting options before accept/connect
402  * v3.6.1, Bill Fink, 1-Mar-03
403  *	Add -xP nuttcp process priority option
404  *	Add instantaneous rate limit capability ("-Ri")
405  *	Don't open data connection if server error or doing traceroute
406  *	Better cleanup on server connection error (close open data connections)
407  *	Don't give normal nuttcp output if server error requiring abort
408  *	Implement -xt traceroute option
409  * v3.5.1, Bill Fink, 27-Feb-03
410  *	Don't allow flip option to be used with UDP
411  *	Fix bug with UDP and transmit interval option (set stdin unbuffered)
412  *	Fix start of UDP timing to be when get BOD
413  *	Fix UDP timing when don't get first EOD
414  *	Fix ident option used with interval option
415  *	Add "-f-percentloss" option to not give %loss info on brief output
416  *	Add "-f-drops" option to not give packet drop info on brief output
417  *	Add packet drop info to UDP brief output (interval report and final)
418  *	Add "-frunningtotal" option to give cumulative stats for "-i"
419  *	Add "-fdebuginterval" option to help debug interval reporting
420  *	Add "-fxmitstats" option to give transmitter stats
421  *	Change flip option from "-f" to "-F"
422  *	Fix divide by zero bug with "-i" option and very low rate limit
423  *	Fix to allow compiling with Irix native compiler
424  *	Fix by Rob Scott to allow compiling on MacOS X
425  * v3.4.5, Bill Fink, 29-Jan-03
426  *	Fix client/server endian issues with UDP loss info for interval option
427  * v3.4.4, Bill Fink, 29-Jan-03
428  *	Remove some debug printout for interval option
429  *	Fix bug when using interval option reporting 0.000 MB on final
430  * v3.4.3, Bill Fink, 24-Jan-03
431  *	Added UDP approximate loss info for interval reporting
432  *	Changed nbytes and pbytes from double to uint64_t
433  *	Changed SIGUSR1 to SIGTERM to kill sleeping child when done
434  * v3.4.2, Bill Fink, 15-Jan-03
435  *	Make <control-C> work right with receive too
436  * v3.4.1, Bill Fink, 13-Jan-03
437  *	Fix bug interacting with old servers
438  *	Add "-f" flip option to reverse direction of data connection open
439  *	Fix bug by disabling interval timer when server done
440  * v3.3.2, Bill Fink, 11-Jan-03
441  *	Make "-i" option work for client transmit too
442  *	Fix bug which forced "-i" option to be at least 0.1 seconds
443  * v3.3.1, Bill Fink, 7-Jan-03
444  *	Added -i option to set interval timer (client receive only)
445  *	Fixed server bug not setting socket address family
446  * v3.2.1, Bill Fink, 25-Feb-02
447  *	Fixed bug so second <control-C> will definitely kill nuttcp
448  *	Changed default control port to 5000 (instead of data port - 1)
449  *	Modified -T option to accept fractional seconds
450  * v3.1.10, Bill Fink, 6-Feb-02
451  *	Added -I option to identify nuttcp output
452  *	Made server always verbose (filtering is done by client)
453  *	Update to usage statement
454  *	Minor fix to "-b" output when "-D" option is used
455  *	Fix bug with "-s" that appends nuttcp output to receiver data file
456  *	Fix bug with "-b" that gave bogus CPU utilization on > 1 hour transfers
457  * v3.1.9, Bill Fink, 21-Dec-01
458  *	Fix bug with "-b" option on SGI systems reporting 0% CPU utilization
459  * v3.1.8, Bill Fink, 21-Dec-01
460  *	Minor change to brief output format to make it simpler to awk
461  * v3.1.7, Bill Fink, 20-Dec-01
462  *	Implement "-b" option for brief output (old "-b" -> "-wb")
463  *	Report udp loss percentage when using client/server mode
464  *	Fix bug with nbytes on transmitter using timed transfer
465  *	Combined send/receive window size printout onto a single line
466  * v3.1.6, Bill Fink, 11-Jun-01
467  *	Fixed minor bug reporting error connecting to inetd server
468  * Previously, Bill Fink, 7-Jun-01
469  *	Added -h (usage) and -V (version) options
470  *	Fixed SGI compilation warnings
471  *	Added reporting server version to client
472  *	Added version info and changed ttcp prints to nuttcp
473  *	Fixed bug with inetd server and client using -r option
474  *	Added ability to run server from inetd
475  *	Added udp capability to server option
476  *	Added -T option to set timeout interval
477  *	Added -ws option to set server window
478  *	Added -S option to support running receiver as daemon
479  *	Allow setting UDP buflen up to MAXUDPBUFLEN
480  *	Provide -b option for braindead Solaris 2.8
481  *	Added printing of transmit rate limit
482  *	Added -w option to usage statement
483  *	Added -N option to support multiple streams
484  *	Added -R transmit rate limit option
485  *	Fix setting of destination IP address on 64-bit Irix systems
486  *	Only set window size in appropriate direction to save memory
487  *	Fix throughput calculation for large transfers (>= 2 GB)
488  *	Fix reporting of Mb/s to give actual millions of bits per second
489  *	Fix setting of INET address family in local socket
490  *	Fix setting of receiver window size
491  *
492  * TODO/Wish-List:
493  *	Transmit interval marking option
494  *	Allow at least some traceroute options
495  *	Add "-ut" option to do both UDP and TCP simultaneously
496  *	Default rate limit UDP if too much loss
497  *	Ping option
498  *	Other brief output formats
499  *	Linux window size bug/feature note
500  *	Network interface interrupts (for Linux only)
501  *	netstat -i info
502  *	Man page
503  *	Forking for multiple streams
504  *	Bidirectional option
505  *	Graphical interface
506  *	MTU info
507  *	Warning for window size limiting throughput
508  *	Auto window size optimization
509  *	Transmitter profile and playback options
510  *	Server side limitations (per client host/network)
511  *	Server side logging
512  *	Client/server security (password)
513  *	nuttcp server registration
514  *	nuttcp proxy support (firewalls)
515  *	nuttcp network idle time
516  *
517  * Distribution Status -
518  *	OpenSource(tm)
519  *	Licensed under version 2 of the GNU GPL
520  *	Please send source modifications back to the authors
521  *	Derivative works should be redistributed with a modified
522  *	source and executable name
523  */
524 
525 /*
526 #ifndef lint
527 static char RCSid[] = "@(#)$Revision: 1.2 $ (BRL)";
528 #endif
529 */
530 
531 #ifdef NOT_LINUX
532 #undef linux
533 #endif
534 
535 #ifndef WANT_WUR
536 #undef _FORTIFY_SOURCE
537 #else
538 #define _FORTIFY_SOURCE		2
539 #endif
540 
541 #define _FILE_OFFSET_BITS	64
542 
543 #if defined(linux)
544 #define _GNU_SOURCE
545 #endif
546 
547 #include <stdio.h>
548 #include <signal.h>
549 #include <ctype.h>
550 #include <errno.h>
551 #include <sys/types.h>
552 #include <sys/time.h>		/* struct timeval */
553 #include <stdlib.h>
554 
555 #ifndef _WIN32
556 #include <sys/socket.h>
557 #include <netinet/in.h>
558 #include <netinet/tcp.h>
559 #include <arpa/inet.h>
560 #include <netdb.h>
561 #include <sys/resource.h>
562 #else
563 #include "win32nuttcp.h"			/* from win32 */
564 #endif /* _WIN32 */
565 
566 #include <limits.h>
567 #include <string.h>
568 #include <fcntl.h>
569 
570 #if defined(linux)
571 #include <sys/stat.h>
572 #include <sys/sendfile.h>
573 #include <sys/ioctl.h>
574 #include <linux/sockios.h>
575 #endif
576 
577 /* Let's try changing the previous unwieldy check */
578 /* #if defined(linux) || defined(__FreeBSD__) || defined (sgi) || (defined(__MACH__) && defined(_SOCKLEN_T)) || defined(sparc) || defined(__CYGWIN__) */
579 /* to the following (hopefully equivalent) simpler form like we use
580  * for HAVE_POLL */
581 #if !defined(_WIN32) && (!defined(__MACH__) || defined(_SOCKLEN_T))
582 #include <unistd.h>
583 #include <sys/wait.h>
584 #include <strings.h>
585 #endif
586 
587 #ifndef USE_GETTIMEOFDAY
588 #ifndef HAVE_CLOCK_GETTIME
589 #if (defined(linux) && defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 17)) || defined(__CYGWIN__)
590 #define HAVE_CLOCK_GETTIME
591 #endif
592 #endif
593 #endif
594 
595 #ifdef HAVE_CLOCK_GETTIME
596 #include <time.h>		/* clock_gettime */
597 #endif
598 
599 #ifndef ULLONG_MAX
600 #define ULLONG_MAX	18446744073709551615ULL
601 #endif
602 
603 #define MAXRATE 0xffffffffUL
604 
605 #if !defined(__CYGWIN__) && !defined(_WIN32)
606 #define HAVE_SETPRIO
607 #endif
608 
609 #if defined(linux)
610 #define HAVE_SETAFFINITY
611 #endif
612 
613 #if !defined(_WIN32) && (!defined(__MACH__) || defined(_SOCKLEN_T))
614 #define HAVE_POLL
615 #endif
616 
617 #if defined(__APPLE__) && defined(__MACH__)
618 #define uint64_t u_int64_t
619 #define uint32_t u_int32_t
620 #define uint16_t u_int16_t
621 #define uint8_t u_int8_t
622 #endif
623 
624 #ifdef HAVE_POLL
625 #include <sys/poll.h>
626 #else
627 #include "fakepoll.h"			/* from missing */
628 #endif
629 
630 #ifdef HAVE_SETAFFINITY
631 #include <sched.h>
632 #endif
633 
634 #ifndef CPU_SETSIZE
635 #undef HAVE_SETAFFINITY
636 #endif
637 
638 /*
639  * _SOCKLEN_T is now defined by apple when they typedef socklen_t
640  *
641  * EAI_NONAME has nothing to do with socklen, but on sparc without it tells
642  * us it's an old enough solaris to need the typedef
643  */
644 #if (defined(__APPLE__) && defined(__MACH__)) && !defined(_SOCKLEN_T) || (defined(sparc) && !defined(EAI_NONAME))
645 typedef int socklen_t;
646 #endif
647 
648 #if defined(sparc) && !defined(EAI_NONAME) /* old sparc */
649 #define sockaddr_storage sockaddr
650 #define ss_family sa_family
651 #endif /* old sparc */
652 
653 #if defined(_AIX) && !defined(HAVE_SS_FAMILY)
654 #define ss_family __ss_family
655 #endif
656 
657 #if !defined(EAI_NONAME)
658 #include "addrinfo.h"			/* from missing */
659 #endif
660 
661 /*
662  * The following macro is from openssh defines.h by Tatu Ylonen and marked "can be used freely for any purpose"
663  */
664 #if !defined(IN6_IS_ADDR_V4MAPPED)
665 #define IN6_IS_ADDR_V4MAPPED(a)               \
666         ((*(const __uint32_t *)(const void *)(&(a)->s6_addr[0]) == 0) && \
667         (*(const __uint32_t *)(const void *)(&(a)->s6_addr[4]) == 0) && \
668         (*(const __uint32_t *)(const void *)(&(a)->s6_addr[8]) == \
669         ntohl(0x0000ffff)))
670 #endif /* !defined(IN6_IS_ADDR_V4MAPPED) */
671 
672 #define BETA_STR	"-beta8"
673 #define BETA_FEATURES	"jitter/owd"
674 
675 union sockaddr_union {
676 	struct sockaddr_storage	ss;
677 	struct sockaddr_in	sin;
678 	struct sockaddr_in6	sin6;
679 };
680 
681 static struct timeval time0;	/* Time at which timing started */
682 static struct timeval timepk;	/* Time at which last packet sent */
683 static struct timeval timepkr;	/* Time at which last packet received */
684 static struct timeval timepkri;	/* timepkr for interval reports */
685 static struct timeval timep;	/* Previous time - for interval reporting */
686 static struct timeval timetx;	/* Transmitter timestamp */
687 static struct timeval timerx;	/* Receive timestamp */
688 static struct rusage ru0;	/* Resource utilization at the start */
689 
690 static struct	sigaction sigact;	/* signal handler for alarm */
691 static struct	sigaction savesigact;
692 
693 #define PERF_FMT_OUT	  "%.4f MB in %.2f real seconds = %.2f KB/sec" \
694 			  " = %.4f Mbps\n"
695 #define PERF_FMT_BRIEF	  "%10.4f MB / %6.2f sec = %9.4f Mbps %d %%TX %d %%RX"
696 #define PERF_FMT_BRIEF2	  "%10.4f MB / %6.2f sec = %9.4f Mbps %d %%%s"
697 #define PERF_FMT_BRIEF3	  " Trans: %.4f MB"
698 #define PERF_FMT_INTERVAL  "%10.4f MB / %6.2f sec = %9.4f Mbps"
699 #define PERF_FMT_INTERVAL2 " Tot: %10.4f MB / %6.2f sec = %9.4f Mbps"
700 #define PERF_FMT_INTERVAL3 " Trans: %10.4f MB"
701 #define PERF_FMT_INTERVAL4 " Tot: %10.4f MB"
702 #define PERF_FMT_IN	  "%lf MB in %lf real seconds = %lf KB/sec = %lf Mbps\n"
703 #define CPU_STATS_FMT_IN  "%*fuser %*fsys %*d:%*dreal %d%%"
704 #define CPU_STATS_FMT_IN2 "%*fuser %*fsys %*d:%*d:%*dreal %d%%"
705 
706 #define LOSS_FMT	" %.2f%% data loss"
707 #define LOSS_FMT_BRIEF	" %.2f %%loss"
708 #define LOSS_FMT_INTERVAL " %5.2f ~%%loss"
709 #define LOSS_FMT5	" %.5f%% data loss"
710 #define LOSS_FMT_BRIEF5	" %.5f %%loss"
711 #define LOSS_FMT_INTERVAL5 " %7.5f ~%%loss"
712 #define DROP_FMT	" %lld / %lld drop/pkt"
713 #define DROP_FMT_BRIEF	" %lld / %lld drop/pkt"
714 #define DROP_FMT_INTERVAL " %5lld / %5lld ~drop/pkt"
715 #define JITTER_MIN		1
716 #define JITTER_AVG		2
717 #define JITTER_MAX		4
718 #define JITTER_IGNORE_OOO	8
719 #define JITTER_FMT	"min-jitter = %.4f ms, avg-jitter = %.4f ms, " \
720 			"max-jitter = %.4f ms"
721 #define JITTER_MIN_FMT_BRIEF " %.4f msMinJitter"
722 #define JITTER_AVG_FMT_BRIEF " %.4f msAvgJitter"
723 #define JITTER_MAX_FMT_BRIEF " %.4f msMaxJitter"
724 #define JITTER_MIN_FMT_INTERVAL " %.4f msMinJitter"
725 #define JITTER_AVG_FMT_INTERVAL " %.4f msAvgJitter"
726 #define JITTER_MAX_FMT_INTERVAL " %.4f msMaxJitter"
727 #define JITTER_FMT_IN	"jitter = %lf ms, avg-jitter = %lf ms, " \
728 			"max-jitter = %lf ms"
729 #define OWD_MIN			1
730 #define OWD_AVG			2
731 #define OWD_MAX			4
732 #define OWD_FMT		"min-OWD = %.4f ms, avg-OWD = %.4f ms, " \
733 			"max-OWD = %.4f ms"
734 #define OWD_MIN_FMT_BRIEF " %.4f msMinOWD"
735 #define OWD_AVG_FMT_BRIEF " %.4f msAvgOWD"
736 #define OWD_MAX_FMT_BRIEF " %.4f msMaxOWD"
737 #define OWD_MIN_FMT_INTERVAL " %.4f msMinOWD"
738 #define OWD_AVG_FMT_INTERVAL " %.4f msAvgOWD"
739 #define OWD_MAX_FMT_INTERVAL " %.4f msMaxOWD"
740 #define OWD_FMT_IN	"OWD = %lf ms, avg-OWD = %lf ms, max-OWD = %lf ms"
741 #define RETRANS_FMT	"%sretrans = %d"
742 #define RETRANS_FMT_BRIEF " %d %sretrans"
743 #define RETRANS_FMT_BRIEF_STR1 " %d = %d"
744 #define RETRANS_FMT_BRIEF_STR2 " retrans"
745 #define RETRANS_FMT_INTERVAL " %5d %sretrans"
746 #define RETRANS_FMT_IN	"retrans = %d"
747 #define CWND_FMT	" cwnd = %d KB"
748 #define CWND_FMT_BRIEF " %d KB-cwnd"
749 #define CWND_FMT_BRIEF_STR1 " %d = %d"
750 #define CWND_FMT_BRIEF_STR2 " KB-cwnd"
751 #define CWND_FMT_INTERVAL " %6d KB-cwnd"
752 #define CWND_FMT_IN	"cwnd = %d"
753 #define RTT_FMT		" RTT=%.3f ms"
754 #define RTT_FMT_BRIEF	" %.2f msRTT"
755 #define RTT_FMT_IN	"RTT=%lf"
756 #define RTT_FMT_INB	"RTT = %lf"
757 #define SIZEOF_TCP_INFO_RETRANS		104
758 
759 /* define NEW_TCP_INFO if struct tcp_info in /usr/include/netinet/tcp.h
760  * contains tcpi_total_retrans member
761  *
762  * tcpi_rcv_rtt, tcpi_rcv_space, & tcpi_total_retrans were added
763  * in glibc-headers-2.7 (Fedora 8) which fortunately also defined
764  * TCP_MD5SIG at the same time, so key off of that
765  */
766 #if defined(linux) && defined(TCP_MD5SIG)
767 #define NEW_TCP_INFO
768 #endif
769 
770 #ifndef NEW_TCP_INFO
771 #define OLD_TCP_INFO
772 #endif
773 
774 /* Parsable output formats */
775 
776 #define P_PERF_FMT_OUT	  "megabytes=%.4f real_seconds=%.2f " \
777 			  "rate_KBps=%.2f rate_Mbps=%.4f\n"
778 #define P_PERF_FMT_BRIEF  "megabytes=%.4f real_seconds=%.2f rate_Mbps=%.4f " \
779 			  "tx_cpu=%d rx_cpu=%d"
780 #define P_PERF_FMT_BRIEF3 " tx_megabytes=%.4f"
781 #define P_PERF_FMT_INTERVAL  "megabytes=%.4f real_sec=%.2f rate_Mbps=%.4f"
782 #define P_PERF_FMT_INTERVAL2 " total_megabytes=%.4f total_real_sec=%.2f" \
783 			     " total_rate_Mbps=%.4f"
784 #define P_PERF_FMT_INTERVAL3 " tx_megabytes=%.4f"
785 #define P_PERF_FMT_INTERVAL4 " tx_total_megabytes=%.4f"
786 #define P_PERF_FMT_IN	  "megabytes=%lf real_seconds=%lf rate_KBps=%lf " \
787 			  "rate_Mbps=%lf\n"
788 #define P_CPU_STATS_FMT_IN  "user=%*f system=%*f elapsed=%*d:%*d cpu=%d%%"
789 #define P_CPU_STATS_FMT_IN2 "user=%*f system=%*f elapsed=%*d:%*d:%*d cpu=%d%%"
790 
791 #define P_LOSS_FMT		" data_loss=%.5f"
792 #define P_LOSS_FMT_BRIEF	" data_loss=%.5f"
793 #define P_LOSS_FMT_INTERVAL	" data_loss=%.5f"
794 #define P_DROP_FMT		" drop=%lld pkt=%lld"
795 #define P_DROP_FMT_BRIEF	" drop=%lld pkt=%lld"
796 #define P_DROP_FMT_INTERVAL	" drop=%lld pkt=%lld"
797 #define P_JITTER_FMT		"msminjitter=%.4f msavgjitter=%.4f " \
798 				"msmaxjitter=%.4f"
799 #define P_JITTER_MIN_FMT_BRIEF	" msminjitter=%.4f"
800 #define P_JITTER_AVG_FMT_BRIEF	" msavgjitter=%.4f"
801 #define P_JITTER_MAX_FMT_BRIEF	" msmaxjitter=%.4f"
802 #define P_JITTER_MIN_FMT_INTERVAL " msminjitter=%.4f"
803 #define P_JITTER_AVG_FMT_INTERVAL " msavgjitter=%.4f"
804 #define P_JITTER_MAX_FMT_INTERVAL " msmaxjitter=%.4f"
805 #define P_JITTER_FMT_IN		"jitter=%lf msavgjitter=%lf msmaxjitter=%lf"
806 #define P_OWD_FMT		"msminOWD=%.4f msavgOWD=%.4f msmaxOWD=%.4f"
807 #define P_OWD_MIN_FMT_BRIEF	" msminOWD=%.4f"
808 #define P_OWD_AVG_FMT_BRIEF	" msavgOWD=%.4f"
809 #define P_OWD_MAX_FMT_BRIEF	" msmaxOWD=%.4f"
810 #define P_OWD_MIN_FMT_INTERVAL	" msminOWD=%.4f"
811 #define P_OWD_AVG_FMT_INTERVAL	" msavgOWD=%.4f"
812 #define P_OWD_MAX_FMT_INTERVAL	" msmaxOWD=%.4f"
813 #define P_OWD_FMT_IN		"OWD=%lf msavgOWD=%lf msmaxOWD=%lf"
814 #define P_RETRANS_FMT		"%sretrans=%d"
815 #define P_RETRANS_FMT_STREAMS	" retrans_by_stream=%d"
816 #define P_RETRANS_FMT_BRIEF	" %sretrans=%d"
817 #define P_RETRANS_FMT_INTERVAL	" %sretrans=%d"
818 #define P_RETRANS_FMT_IN	"retrans=%d"
819 #define P_CWND_FMT		" cwnd=%d"
820 #define P_CWND_FMT_STREAMS	" cwnd_by_stream=%d"
821 #define P_CWND_FMT_BRIEF	" cwnd=%d"
822 #define P_CWND_FMT_INTERVAL	" cwnd=%d"
823 #define P_CWND_FMT_IN		"cwnd=%d"
824 #define P_RTT_FMT		" rtt_ms=%.3f"
825 #define P_RTT_FMT_BRIEF		" rtt_ms=%.2f"
826 #define P_RTT_FMT_IN		"rtt_ms=%lf"
827 
828 #define HELO_FMT	"HELO nuttcp v%d.%d.%d\n"
829 
830 #ifndef MAXSTREAM
831 #define MAXSTREAM		128
832 #endif
833 #define DEFAULT_NBUF		2048
834 #define DEFAULT_NBYTES		134217728	/* 128 MB */
835 #define DEFAULT_TIMEOUT		10.0
836 #define DEFAULT_UDP_RATE	1000
837 #define DEFAULTUDPBUFLEN	8192
838 #define DEFAULT_MC_UDPBUFLEN	1024
839 #define MAXUDPBUFLEN		65507
840 #define LOW_RATE_HOST3		1000
841 #define MINMALLOC		1024
842 #define HI_MC			231ul
843 #define HI_MC_SSM		232ul
844 /* locally defined global scope IPv6 multicast, FF3E::8000:0-FF3E::FFFF:FFFF */
845 #define HI_MC6			"FF3E::8000:0000"
846 #define HI_MC6_LEN		13
847 #define HI_MC6_ASM		"FF2E::0"
848 #define HI_MC6_ASM_LEN		8
849 #ifndef LISTEN_BACKLOG
850 #define LISTEN_BACKLOG		64
851 #endif
852 #define ACCEPT_TIMEOUT		5
853 #ifndef MAX_CONNECT_TRIES
854 #define MAX_CONNECT_TRIES	10	/* maximum server connect attempts */
855 #endif
856 #ifndef SERVER_RETRY_USEC
857 #define SERVER_RETRY_USEC	500000	/* server retry time in usec */
858 #endif
859 #define MAX_EOT_WAIT_SEC	60.0	/* max wait for unsent data at EOT */
860 #define SRVR_INFO_TIMEOUT	60	/* timeout for reading server info */
861 #define IDLE_DATA_MIN		15.0	/* minimum value for chk_idle_data */
862 #define DEFAULT_IDLE_DATA	30.0	/* default value for chk_idle_data */
863 #define IDLE_DATA_MAX		60.0	/* maximum value for chk_idle_data */
864 #define NON_JUMBO_ETHER_MSS	1448	/* 1500 - 20:IP - 20:TCP -12:TCPOPTS */
865 #define TCP_UDP_HDRLEN_DELTA	12	/* difference in tcp & udp hdr sizes */
866 #define TCP_TIMESTAMPS_OPTLEN	12	/* size of TCP timestamps options */
867 
868 #if defined(linux)
869 #define TCP_ADV_WIN_SCALE	"/proc/sys/net/ipv4/tcp_adv_win_scale"
870 #endif
871 
872 #define DEBUGOUTPUT		"/tmp/nuttcp-debugout.foo"
873 
874 #define BRIEF_RETRANS_STREAMS	0x2	/* brief per stream retrans info */
875 #define BRIEF_CWND_STREAMS	0x4	/* brief per stream cwnd info */
876 
877 #define XMITSTATS		0x1	/* also give transmitter stats (MB) */
878 #define DEBUGINTERVAL		0x2	/* add info to assist with
879 					 * debugging interval reports */
880 #define	RUNNINGTOTAL		0x4	/* give cumulative stats for "-i" */
881 #define	NODROPS			0x8	/* no packet drop stats for "-i" */
882 #define	NOPERCENTLOSS		0x10	/* don't give percent loss for "-i" */
883 #define DEBUGPOLL		0x20	/* add info to assist with debugging
884 					 * polling for interval reports */
885 #define PARSE			0x40	/* generate key=value parsable output */
886 #define DEBUGMTU		0x80	/* debug info for MTU/MSS code */
887 #define	NORETRANS		0x100	/* no retrans stats for "-i" */
888 #define	DEBUGRETRANS		0x200	/* output info for debugging collection
889 					 * of TCP retransmission info */
890 #define	NOBETAMSG		0x400	/* suppress beta version message */
891 #define	WANTRTT			0x800	/* output RTT info (default) */
892 #define DEBUGJITTER		0x1000	/* debugging info for jitter option */
893 #define	NOCWND			0x2000	/* no cwnd stats for "-i" */
894 #define DEBUGIRATE		0x4000	/* debugging info for irate option */
895 
896 #ifdef NO_IPV6				/* Build without IPv6 support */
897 #undef AF_INET6
898 #undef IPV6_V6ONLY
899 #endif
900 
901 void sigpipe( int signum );
902 void sigint( int signum );
903 void ignore_alarm( int signum );
904 void sigalarm( int signum );
905 static void err( char *s );
906 static void mes( char *s );
907 static void errmes( char *s );
908 void pattern( char *cp, int cnt );
909 void get_timeofday( struct timeval *tv, struct timezone *tz );
910 void prep_timer();
911 double read_timer( char *str, int len );
912 static void prusage( struct rusage *r0,  struct rusage *r1, struct timeval *e, struct timeval *b, char *outp );
913 static void tvadd( struct timeval *tsum, struct timeval *t0, struct timeval *t1 );
914 static void tvsub( struct timeval *tdiff, struct timeval *t1, struct timeval *t0 );
915 static void psecs( long l, char *cp );
916 int Nread( int fd, char *buf, int count );
917 int Nwrite( int fd, char *buf, int count );
918 int delay( int us );
919 int mread( int fd, char *bufp, unsigned n );
920 int mwrite( int fd, char *bufp, unsigned n, int last_write );
921 char *getoptvalp( char **argv, int index, int reqval, int *skiparg );
922 
923 #if defined(linux) && defined(TCPI_OPT_TIMESTAMPS)
924 void print_tcpinfo();
925 #endif
926 
927 int vers_major = 8;
928 int vers_minor = 2;
929 int vers_delta = 2;
930 int ivers;
931 int rvers_major = 0;
932 int rvers_minor = 0;
933 int rvers_delta = 0;
934 int irvers;
935 int beta = 0;
936 
937 struct sockaddr_in sinme[MAXSTREAM + 1];
938 struct sockaddr_in sinhim[MAXSTREAM + 1];
939 struct sockaddr_in save_sinhim, save_mc;
940 
941 #ifdef AF_INET6
942 struct sockaddr_in6 sinme6[MAXSTREAM + 1];
943 struct sockaddr_in6 sinhim6[MAXSTREAM + 1];
944 struct sockaddr_in6 save_sinhim6, save_mc6;
945 struct in6_addr hi_mc6, hi_mc6_asm;
946 #endif
947 
948 struct sockaddr_storage frominet;
949 
950 int domain = PF_UNSPEC;
951 int af = AF_UNSPEC;
952 int mc_af = AF_UNSPEC;
953 int explicitaf = 0;		/* address family explicit specified (-4|-6) */
954 int fd[MAXSTREAM + 1];		/* fd array of network sockets */
955 int nfd;			/* fd for accept call */
956 struct pollfd pollfds[MAXSTREAM + 4];	/* used for reading interval reports */
957 socklen_t fromlen;
958 
959 int buflen = 64 * 1024;		/* length of buffer */
960 int nbuflen;
961 int mallocsize;
962 char *buf;			/* ptr to dynamic buffer */
963 unsigned long long nbuf = 0;	/* number of buffers to send in sinkmode */
964 int nbuf_bytes = 0;		/* set to 1 if nbuf is actually bytes */
965 
966 /*  nick code  */
967 int sendwin=0, sendwinval=0, origsendwin=0;
968 socklen_t optlen;
969 int rcvwin=0, rcvwinval=0, origrcvwin=0;
970 int srvrwin=0;
971 /*  end nick code  */
972 
973 #if defined(linux)
974 int sendwinavail=0, rcvwinavail=0, winadjust=0;
975 #endif
976 
977 #if defined(linux) && defined(TCPI_OPT_TIMESTAMPS)
978 #ifdef OLD_TCP_INFO
979 #define STRUCT_TCPINFO tcpinfo
980 struct tcpinfo {		/* for collecting TCP retransmission info */
981 	struct tcp_info	_tcpinf;
982 	/* add missing structure elements */
983 	u_int32_t	tcpi_rcv_rtt;
984 	u_int32_t	tcpi_rcv_space;
985 	u_int32_t	tcpi_total_retrans;
986 } tcpinf;
987 #define tcpinfo_state		_tcpinf.tcpi_state
988 #define tcpinfo_ca_state	_tcpinf.tcpi_ca_state
989 #define tcpinfo_retransmits	_tcpinf.tcpi_retransmits
990 #define tcpinfo_unacked		_tcpinf.tcpi_unacked
991 #define tcpinfo_sacked		_tcpinf.tcpi_sacked
992 #define tcpinfo_lost		_tcpinf.tcpi_lost
993 #define tcpinfo_retrans		_tcpinf.tcpi_retrans
994 #define tcpinfo_fackets		_tcpinf.tcpi_fackets
995 #define tcpinfo_rtt		_tcpinf.tcpi_rtt
996 #define tcpinfo_rttvar		_tcpinf.tcpi_rttvar
997 #define tcpinfo_snd_ssthresh	_tcpinf.tcpi_snd_ssthresh
998 #define tcpinfo_snd_cwnd	_tcpinf.tcpi_snd_cwnd
999 #else
1000 #define STRUCT_TCPINFO tcp_info
1001 struct tcp_info tcpinf;
1002 #define tcpinfo_state		tcpi_state
1003 #define tcpinfo_ca_state	tcpi_ca_state
1004 #define tcpinfo_retransmits	tcpi_retransmits
1005 #define tcpinfo_unacked		tcpi_unacked
1006 #define tcpinfo_sacked		tcpi_sacked
1007 #define tcpinfo_lost		tcpi_lost
1008 #define tcpinfo_retrans		tcpi_retrans
1009 #define tcpinfo_fackets		tcpi_fackets
1010 #define tcpinfo_rtt		tcpi_rtt
1011 #define tcpinfo_rttvar		tcpi_rttvar
1012 #define tcpinfo_snd_ssthresh	tcpi_snd_ssthresh
1013 #define tcpinfo_snd_cwnd	tcpi_snd_cwnd
1014 #endif
1015 #else
1016 #define STRUCT_TCPINFO dummy_tcp_info
1017 struct dummy_tcp_info {
1018 	int	dummy1;
1019 } tcpinf;
1020 #endif
1021 
1022 int get_retrans( int sockfd, struct STRUCT_TCPINFO *tcpinfo );
1023 
1024 int udp = 0;			/* 0 = tcp, !0 = udp */
1025 int udplossinfo = 0;		/* set to 1 to give UDP loss info for
1026 				 * interval reporting */
1027 int do_jitter = 0;		/* set to 1 to enable jitter measurements */
1028 int do_owd = 0;			/* set to 1 to enable one-way delay reports */
1029 
1030 int retransinfo = 0;		/* set to 1 to give TCP retransmission info
1031 				 * for interval reporting */
1032 int force_retrans = 0;		/* set to force sending retrans info */
1033 int send_retrans = 1;		/* set to 0 if no need to send retrans info */
1034 int do_retrans = 0;		/* set to 1 for client transmitter */
1035 int read_retrans = 1;		/* set to 0 if no need to read retrans info */
1036 int got_0retrans = 0;		/* set to 1 by client transmitter after
1037 				 * processing initial server output
1038 				 * having "0 retrans" */
1039 
1040 int init_pkt_cwnd = 0;		/* initial congestion window in packets */
1041 int sss_pkt_cwnd = 0;		/* smoothed slow start congestion window */
1042 int cwndinfo = 0;		/* set to 1 to give TCP congestion window info
1043 				 * for interval reporting */
1044 int send_cwnd = 1;		/* set to 0 if no need to send cwnd info */
1045 int do_cwnd = 0;		/* set to 1 for client transmitter */
1046 int read_cwnd = 1;		/* set to 0 if no need to read cwnd info */
1047 
1048 int need_swap;			/* client and server are different endian */
1049 int options = 0;		/* socket options */
1050 int one = 1;			/* for 4.3 BSD style setsockopt() */
1051 /* default port numbers if command arg or getserv doesn't get a port # */
1052 #define DEFAULT_PORT	5101
1053 #define DEFAULT_CTLPORT	5000
1054 #define IPERF_PORT	5001
1055 unsigned short port = 0;	/* TCP port number */
1056 unsigned short srcport = 0;	/* TCP source port */
1057 unsigned short ctlport = 0;	/* control port for server connection */
1058 unsigned short srcctlport = 0;	/* TCP source port for server connection */
1059 unsigned short ctlport3 = 0;	/* control port for 3rd party server conn */
1060 int tmpport;
1061 char *host;			/* ptr to name of host */
1062 char *stride = NULL;		/* ptr to address stride for multi-stream */
1063 char *host3 = NULL;		/* ptr to 3rd party host */
1064 int thirdparty = 0;		/* set to 1 indicates doing 3rd party nuttcp */
1065 int no3rd = 0;			/* set to 1 by server to disallow 3rd party */
1066 int forked = 0;			/* set to 1 after server has forked */
1067 int pass_ctlport = 0;		/* set to 1 to use same outgoing control port
1068 				   as incoming with 3rd party usage */
1069 char *nut_cmd;			/* command used to invoke nuttcp */
1070 char *cmdargs[50];		/* command arguments array */
1071 char tmpargs[50][50];
1072 
1073 #ifndef AF_INET6
1074 #define ADDRSTRLEN 16
1075 #else
1076 #define ADDRSTRLEN INET6_ADDRSTRLEN
1077 int v4mapped = 0;		/* set to 1 to enable v4 mapping in v6 server */
1078 #endif
1079 
1080 #define HOSTNAMELEN	80
1081 #define HOST3BUFLEN	HOSTNAMELEN + 2 + ADDRSTRLEN + 1 + ADDRSTRLEN
1082 				/* host3=[=]host3addr[+host3stride] */
1083 
1084 char hostbuf[ADDRSTRLEN];	/* buffer to hold text of address */
1085 char host3addr[ADDRSTRLEN];	/* buffer to hold text of 3rd party address */
1086 char host3buf[HOST3BUFLEN + 1];	/* buffer to hold 3rd party name or address */
1087 char clientbuf[NI_MAXHOST];	/* buffer to hold client's resolved hostname */
1088 int trans = 1;			/* 0=receive, !0=transmit mode */
1089 int sinkmode = 1;		/* 0=normal I/O, !0=sink/source mode */
1090 #if defined(linux)
1091 int zerocopy = 0;		/* set to enable zero copy via sendfile() */
1092 int directio = 0;		/* set to enable direct I/O */
1093 #endif
1094 int nofork = 0;			/* set to 1 to not fork server */
1095 int verbose = 0;		/* 0=print basic info, 1=print cpu rate, proc
1096 				 * resource usage. */
1097 int nodelay = 0;		/* set TCP_NODELAY socket option */
1098 unsigned long rate = MAXRATE;	/* transmit rate limit in Kbps */
1099 int maxburst = 1;		/* number of packets allowed to exceed rate */
1100 int nburst = 1;			/* number of packets currently exceeding rate */
1101 int irate = -1;			/* instantaneous rate limit if set */
1102 int iratesss = 0;		/* set if emulating smoothed slow start */
1103 int af3 = 0;			/* used for third party explicitaf */
1104 double pkt_time;		/* packet transmission time in seconds */
1105 double pkt_time_ms;		/* packet transmission time in milliseconds */
1106 uint64_t irate_pk_usec;		/* packet transmission time in microseconds */
1107 double irate_pk_nsec;		/* nanosecond portion of pkt xmit time */
1108 double irate_cum_nsec = 0.0;	/* cumulative nanaseconds over several pkts */
1109 int rate_pps = 0;		/* set to 1 if rate is given as pps */
1110 double timeout = 0.0;		/* timeout interval in seconds */
1111 double interval = 0.0;		/* interval timer in seconds */
1112 double chk_idle_data = 0.0;	/* server receiver checks this often */
1113 				/* for client having gone away */
1114 double chk_interval = 0.0;	/* timer (in seconds) for checking client */
1115 int ctlconnmss;			/* control connection maximum segment size */
1116 int datamss = 0;		/* data connection maximum segment size */
1117 unsigned int tos = 0;		/* 8-bit TOS field for setting DSCP/TOS */
1118 char intervalbuf[256+2];	/* buf for interval reporting */
1119 char linebuf[256+2];		/* line buffer */
1120 int do_poll = 0;		/* set to read interval reports (client xmit) */
1121 int got_done = 0;		/* set when read last of interval reports */
1122 int reverse = 0;		/* reverse direction of data connection open */
1123 int format = 0;			/* controls formatting of output */
1124 char fmt[257];
1125 int traceroute = 0;		/* do traceroute back to client if set */
1126 int skip_data = 0;		/* skip opening of data channel */
1127 #if defined(linux)
1128 int multicast = 0;		/* set to 1 for multicast UDP transfer */
1129 #else
1130 uint8_t multicast = 0;		/* set to 1 for multicast UDP transfer */
1131 #endif
1132 int ssm = -1;			/* set to 1 for Source Specific Multicast */
1133 				/* set to 0 to NOT do SSM */
1134 				/* set to -1 to have SSM follow protocol */
1135 				/* (off for ipv4, on for ipv6) */
1136 int mc_param;
1137 char *mc_addr = NULL;		/* user specified multicast IP address */
1138 char mcgaddr[ADDRSTRLEN];	/* buffer to hold text of MC group address */
1139 struct ip_mreq mc_group;	/* holds multicast group address */
1140 #ifdef AF_INET6
1141 struct ipv6_mreq mc6_group;	/* holds multicast group address */
1142 #endif
1143 #ifdef MCAST_JOIN_SOURCE_GROUP
1144 struct group_source_req group_source_req;  /* holds multicast SSM group and */
1145 					   /* source information */
1146 #endif
1147 
1148 #ifdef HAVE_SETPRIO
1149 int priority = 0;		/* nuttcp process priority */
1150 #endif
1151 
1152 /* affinity and srvr_affinity need to be defined even if don't
1153  * HAVE_SETAFFINITY, to make parameter passing between client and
1154  * server work out OK, since far end may HAVE_SETAFFINITY
1155  *
1156  * they are set to -1 so they have no effect even if don't
1157  * HAVE_SETAFFINITY
1158  */
1159 int affinity = -1;		/* nuttcp process CPU affinity */
1160 int srvr_affinity = -1;		/* nuttcp server process CPU affinity */
1161 
1162 #ifdef HAVE_SETAFFINITY
1163 int ncores = 1;			/* number of CPU cores */
1164 cpu_set_t cpu_set;		/* processor CPU set */
1165 #endif
1166 
1167 long timeout_sec = 0;
1168 struct itimerval itimer;	/* for setitimer */
1169 int srvr_helo = 1;		/* set to 0 if server doesn't send HELO */
1170 char ident[40 + 1 + 1] = "";	/* identifier for nuttcp output */
1171 int intr = 0;
1172 int abortconn = 0;
1173 int braindead = 0;		/* for braindead Solaris 2.8 systems */
1174 int brief = 1;			/* set for brief output */
1175 int brief3 = 1;			/* for third party nuttcp */
1176 int done = 0;			/* don't output interval report if done */
1177 int got_begin = 0;		/* don't output interval report if not begun */
1178 int two_bod = 0;		/* newer versions send 2 BOD packets for UDP */
1179 int handle_urg = 0;		/* newer versions send/recv urgent TCP data */
1180 int got_eod0 = 0;		/* got EOD0 packet - marks end of UDP xfer */
1181 int buflenopt = 0;		/* whether or not user specified buflen */
1182 int haverateopt = 0;		/* whether or not user specified rate */
1183 int clientserver = 0;		/* client server mode (use control channel) */
1184 int client = 0;			/* 0=server side, 1=client (initiator) side */
1185 int oneshot = 0;		/* 1=run server only once */
1186 int inetd = 0;			/* set to 1 if server run from inetd */
1187 pid_t pid;			/* process id when forking server process */
1188 pid_t wait_pid;			/* return of wait system call */
1189 int pidstat;			/* status of forked process */
1190 FILE *ctlconn;			/* uses fd[0] for control channel */
1191 FILE *debugout;			/* used for voluminous nuttcp debug output */
1192 int savestdin;			/* used to save real standard in */
1193 int savestdout;			/* used to save real standard out */
1194 int firsttime = 1;		/* flag for first pass through server */
1195 struct in_addr clientaddr;	/* IP address of client connecting to server */
1196 
1197 #ifdef AF_INET6
1198 struct in6_addr clientaddr6;	/* IP address of client connecting to server */
1199 uint32_t clientscope6;		/* scope part of IP address of client */
1200 #endif
1201 
1202 struct hostent *addr;
1203 extern int errno;
1204 
1205 const char Usage[] = "\
1206 Usage: nuttcp or nuttcp -h	prints this usage info\n\
1207 Usage: nuttcp -V		prints version info\n\
1208 Usage: nuttcp -xt [-m] host	forward and reverse traceroute to/from server\n\
1209 Usage (transmitter): nuttcp [-t] [-options] [ctl_addr/]host [3rd-party] [<in]\n\
1210       |(receiver):   nuttcp -r [-options] [host] [3rd-party] [>out]\n\
1211 	-4	Use IPv4\n"
1212 #ifdef AF_INET6
1213 "	-6	Use IPv6\n"
1214 #endif
1215 "	-c##	cos dscp value on data streams (t|T suffix for full TOS field)\n\
1216 	-l##	length of network write|read buf (default 1K|8K/udp, 64K/tcp)\n"
1217 #if defined(linux)
1218 "	-s[d][z] use stdin|stdout for data input|output instead of pattern data\n"
1219 "		('d' suboption uses direct I/O if input|output is regular file)\n"
1220 "		('z' suboption enables zero copy tx if input is regular file)\n"
1221 #else
1222 "	-s	use stdin|stdout for data input|output instead of pattern data\n"
1223 #endif
1224 "	-n##	number of source bufs written to network (default unlimited)\n\
1225 	-w##	transmitter|receiver window size in KB (or (m|M)B or (g|G)B)\n\
1226 	-ws##	server receive|transmit window size in KB (or (m|M)B or (g|G)B)\n\
1227 	-wb	braindead Solaris 2.8 (sets both xmit and rcv windows)\n\
1228 	-p##	port number to send to|listen at (default 5101)\n\
1229 	-p#:#	specify both source:destination port for -p option\n\
1230 	-P##	port number for control connection (default 5000)\n\
1231 	-P#:#	specify both source:destination port for -P option\n\
1232 	-P#/#	control port to/from 3rd-party host (default 5000)\n\
1233 	-u	use UDP instead of TCP\n\
1234 	-m##	use multicast with specified TTL instead of unicast (UDP)\n\
1235 	-gxxx	user specified multicast IP address for -m option\n\
1236 	-M##	MSS for data connection (TCP)\n\
1237 	-N##	number of streams (starting at port number), implies -B\n\
1238 	-R##	transmit rate limit in Kbps (or (m|M)bps or (g|G)bps or (p)ps)\n\
1239 	-Ri#[/#] instantaneous rate limit with optional packet burst\n"
1240 #if defined(linux)
1241 "	-Ris##  emulated smoothed slow start option for -Ri option (TCP)\n"
1242 #endif
1243 "	-T##	transmit timeout in seconds (or (m|M)inutes or (h|H)ours)\n\
1244 	-j	enable jitter measurements (assumes -u and -Ri options)\n\
1245 	-o	enable one-way delay reports (needs synchronized clocks)\n\
1246 	-i##	receiver interval reporting in seconds (or (m|M)inutes)\n\
1247 	-Ixxx	identifier for nuttcp output (max of 40 characters)\n\
1248 	-F	flip option to reverse direction of data connection open\n\
1249 	-a	retry failed server connection \"again\" for transient errors\n"
1250 #ifdef HAVE_SETPRIO
1251 "	-xP##	set nuttcp process priority (must be root)\n"
1252 #endif
1253 #ifdef HAVE_SETAFFINITY
1254 "	-xc##	set nuttcp client process CPU affinity\n"
1255 "	-xcs##	set nuttcp server process CPU affinity\n"
1256 "	-xc#/#	set nuttcp client/server process CPU affinity\n"
1257 #endif
1258 "	-d	set TCP SO_DEBUG option on data socket\n\
1259 	-v[v]	verbose [or very verbose] output\n\
1260 	-b	brief output (default)\n\
1261 	-br	add per-stream TCP retrans info to brief summary (Linux only)\n"
1262 #if defined(linux)
1263 "	-bc	add per-stream TCP cwnd info to brief summary (Linux only)\n"
1264 #endif
1265 "	-D	xmit only: don't buffer TCP writes (sets TCP_NODELAY sockopt)\n\
1266 	-B	recv only: only output full blocks of size from -l## (for TAR)\n"
1267 "	--packet-burst packet burst value for instantaneous rate limit option\n"
1268 "	--idle-data-timeout <value|minimum/default/maximum>  (default: 15/30/60)\n"
1269 "		     client timeout in seconds for idle data connection\n"
1270 #ifdef IPV6_V6ONLY
1271 "	--disable-v4-mapped disable v4 mapping in v6 server (default)\n"
1272 "	--enable-v4-mapped enable v4 mapping in v6 server\n"
1273 #endif
1274 "\n\
1275 Usage (server): nuttcp -S[P] [-options]\n\
1276 		note server mode excludes use of -s except for -1 one-shot mode\n\
1277 		'P' suboption makes 3rd party {in,out}bound control ports same\n\
1278 	-4	Use IPv4 (default)\n"
1279 #ifdef AF_INET6
1280 "	-6	Use IPv6\n"
1281 #endif
1282 "	-1	oneshot server mode (implied with inetd/xinetd), implies -S\n"
1283 #if defined(linux)
1284 "	-s[d][z] use stdin|stdout for data input|output instead of pattern data\n"
1285 "		('d' suboption uses direct I/O if input|output is regular file)\n"
1286 "		('z' suboption enables zero copy tx if input is regular file)\n"
1287 #else
1288 "	-s	use stdin|stdout for data input|output instead of pattern data\n"
1289 #endif
1290 "	-P##	port number for server connection (default 5000)\n\
1291 		note don't use with inetd/xinetd (use services file instead)\n"
1292 #ifdef HAVE_SETPRIO
1293 "	-xP##	set nuttcp process priority (must be root)\n"
1294 #endif
1295 #ifdef HAVE_SETAFFINITY
1296 "	-xc##	set nuttcp server process CPU affinity\n"
1297 #endif
1298 "	--idle-data-timeout <value|minimum/default/maximum>  (default: 15/30/60)\n"
1299 "		     server timeout in seconds for idle data connection\n"
1300 "	--no3rdparty don't allow 3rd party capability\n"
1301 "	--nofork     don't fork server\n"
1302 "	--single-threaded  make manually started server be single threaded\n"
1303 #ifdef IPV6_V6ONLY
1304 "	--disable-v4-mapped disable v4 mapping in v6 server (default)\n"
1305 "	--enable-v4-mapped enable v4 mapping in v6 server\n"
1306 #endif
1307 "\n\
1308 Multilink aggregation options (TCP only):\n\
1309 	 nuttcp [-options] -N##  [ctl_addr]/host1/host2/.../host## (xmit only)\n\
1310 	 nuttcp [-options] -N##  [ctl_addr/]host+addr_stride (IPv4 only)\n\
1311 	 nuttcp [-options] -N##  [ctl_addr/]host+n.n.n.n (IPv4 only)\n\
1312 	 nuttcp [-options] -N##m [ctl_addr/]host\n\
1313 				 where host resolves to multiple addresses\n\
1314 \n\
1315 			separate [ctl_addr/] option available only for xmit\n\
1316 \n\
1317 Format options:\n\
1318 	-fxmitstats	also give transmitter stats (MB) with -i (UDP only)\n\
1319 	-frunningtotal	also give cumulative stats on interval reports\n\
1320 	-f-drops	don't give packet drop info on brief output (UDP)\n\
1321 	-f-retrans	don't give retrans info on brief output (TCP)\n"
1322 #if defined(linux)
1323 "	-f-cwnd		don't give cwnd info on brief output (TCP)\n"
1324 #endif
1325 "	-f-percentloss	don't give %%loss info on brief output (UDP)\n\
1326 	-fparse		generate key=value parsable output\n\
1327 	-f-beta		suppress beta version message\n\
1328 	-f-rtt		suppress RTT info \n\
1329 ";
1330 
1331 char stats[128];
1332 char srvrbuf[4096];
1333 char tmpbuf[257];
1334 uint64_t nbytes = 0;		/* bytes on net */
1335 int64_t pbytes = 0;		/* previous bytes - for interval reporting */
1336 int64_t ntbytes = 0;		/* bytes sent by transmitter */
1337 int64_t ptbytes = 0;		/* previous bytes sent by transmitter */
1338 uint64_t ntbytesc = 0;		/* bytes sent by transmitter that have
1339 				 * been counted */
1340 uint64_t ntbytescp = 0;		/* previous ntbytesc count */
1341 uint64_t ntbytescpi = 0;	/* ntbytescp for interval reports */
1342 uint64_t chk_nbytes = 0;	/* byte counter used to test if no more data
1343 				 * being received by server (presumably because
1344 				 * client transmitter went away */
1345 
1346 double rtt = 0.0;		/* RTT between client and server in ms */
1347 int which_rt = 1;		/* which round trip for "-Ris" */
1348 uint32_t nretrans[MAXSTREAM+1];	/* number of TCP retransmissions */
1349 uint32_t iretrans[MAXSTREAM+1];	/* initial number of TCP retransmissions */
1350 uint32_t pretrans = 0;		/* previous number of TCP retransmissions */
1351 uint32_t sretrans = 0;		/* number of system TCP retransmissions */
1352 uint32_t cwnd[MAXSTREAM+1];	/* TCP congestion window in KB */
1353 
1354 int numCalls = 0;		/* # of NRead/NWrite calls. */
1355 int nstream = 1;		/* number of streams */
1356 int multilink = 0;		/* set to use multilink aggregation */
1357 int stream_idx = 0;		/* current stream */
1358 int start_idx = 1;		/* set to use or bypass control channel */
1359 int b_flag = 1;			/* use mread() */
1360 int got_srvr_output = 0;	/* set when server output has been read */
1361 int reading_srvr_info = 0;	/* set when starting to read server info */
1362 int retry_server = 0;		/* set to retry control connect() to server */
1363 int num_connect_tries = 0;	/* tracks attempted connects to server */
1364 int single_threaded = 0;	/* set to make server single threaded */
1365 double srvr_MB;
1366 double srvr_realt;
1367 double srvr_KBps;
1368 double srvr_Mbps;
1369 int srvr_cpu_util;
1370 
1371 double cput = 0.000001, realt = 0.000001;	/* user, real time (seconds) */
1372 double realtd = 0.000001;	/* real time delta - for interval reporting */
1373 double pkt_delta;		/* time delta between packets in ms */
1374 double jitter;			/* current jitter measurement in ms */
1375 unsigned long long njitter;	/* number of jitter measurements */
1376 double jitter_min;		/* jitter minimum */
1377 double jitter_max;		/* jitter maximum */
1378 double jitter_avg;		/* jitter average */
1379 double jitteri;			/* current jitter interval measurement in ms */
1380 unsigned long long njitteri;	/* number of jitter interval measurements */
1381 double jitter_mini;		/* jitter minimum for interval report */
1382 double jitter_maxi;		/* jitter maximum for interval report */
1383 double jitter_avgi;		/* jitter average for interval report */
1384 double owd;			/* current one-way delay measurement in ms */
1385 unsigned long long nowd;	/* number of one-way delay measurements */
1386 double owd_min;			/* one-way delay minimum */
1387 double owd_max;			/* one-way delay maximum */
1388 double owd_avg;			/* one-way delay average */
1389 unsigned long long nowdi;	/* number of OWD interval measurements */
1390 double owd_mini;		/* OWD minimum for interval report */
1391 double owd_maxi;		/* OWD maximum for interval report */
1392 double owd_avgi;		/* OWD average for interval report */
1393 
1394 void
close_data_channels()1395 close_data_channels()
1396 {
1397 	if (fd[1] == -1) return;
1398 
1399 	if (clientserver && client && !host3 && udp && trans) {
1400 		/* If all the EOD packets get lost at the end of a UDP
1401 		 * transfer, having the client do a shutdown() for writing
1402 		 * on the control connection allows the server to more
1403 		 * quickly realize that the UDP transfer has completed
1404 		 * (mostly of benefit for separate control and data paths)
1405 		 *
1406 		 * Can't do this in the opposite direction since the
1407 		 * server needs to send info back to client */
1408 		shutdown(0, SHUT_WR);
1409 	}
1410 
1411 	if (multicast && !trans) {
1412 		/* Leave the multicast group */
1413 		if ((af == AF_INET) && !ssm) {
1414 			if (setsockopt(fd[1], IPPROTO_IP, IP_DROP_MEMBERSHIP,
1415 				       (void *)&mc_group,
1416 				       sizeof(mc_group)) < 0) {
1417 				 err("setsockopt: IP_DROP_MEMBERSHIP");
1418 			}
1419 		}
1420 #ifdef AF_INET6
1421 		else if ((af == AF_INET6) && !ssm) {
1422 			if (setsockopt(fd[1], IPPROTO_IPV6, IPV6_LEAVE_GROUP,
1423 				       (void *)&mc6_group,
1424 				       sizeof(mc6_group)) < 0) {
1425 				err("setsockopt: IPV6_LEAVE_GROUP");
1426 			}
1427 		}
1428 #endif
1429 #ifdef MCAST_JOIN_SOURCE_GROUP
1430 		else if ((af == AF_INET) && ssm) {
1431 			/* Leave the source specific multicast group */
1432 			if (setsockopt(fd[1], IPPROTO_IP,
1433 				       MCAST_LEAVE_SOURCE_GROUP,
1434 				       &group_source_req,
1435 				       sizeof(group_source_req)) < 0) {
1436 				err("setsockopt: MCAST_LEAVE_SOURCE_GROUP");
1437 			}
1438 		}
1439 #ifdef AF_INET6
1440 		else if ((af == AF_INET6) && ssm) {
1441 			/* Leave the source specific multicast group */
1442 			if (setsockopt(fd[1], IPPROTO_IPV6,
1443 				       MCAST_LEAVE_SOURCE_GROUP,
1444 				       &group_source_req,
1445 				       sizeof(group_source_req)) < 0) {
1446 				err("setsockopt: MCAST_LEAVE_SOURCE_GROUP");
1447 			}
1448 		}
1449 #endif /* AF_INET6 */
1450 #endif /* MCAST_JOIN_SOURCE_GROUP */
1451 	}
1452 
1453 	for ( stream_idx = 1; stream_idx <= nstream; stream_idx++ ) {
1454 		close(fd[stream_idx]);
1455 		fd[stream_idx] = -1;
1456 	}
1457 }
1458 
1459 #ifdef SIGPIPE
1460 void
sigpipe(int signum)1461 sigpipe( int signum )
1462 {
1463 	signal(SIGPIPE, sigpipe);
1464 }
1465 #endif
1466 
1467 void
sigint(int signum)1468 sigint( int signum )
1469 {
1470 	signal(SIGINT, SIG_DFL);
1471 	fputs("\n*** transfer interrupted ***\n", stdout);
1472 	if (clientserver && client && !host3 && udp && !trans)
1473 		shutdown(0, SHUT_WR);
1474 	else
1475 		intr = 1;
1476 	done++;
1477 	return;
1478 }
1479 
1480 void
ignore_alarm(int signum)1481 ignore_alarm( int signum )
1482 {
1483 	return;
1484 }
1485 
1486 void
sigalarm(int signum)1487 sigalarm( int signum )
1488 {
1489 	struct	timeval timec;	/* Current time */
1490 	struct	timeval timed;	/* Delta time */
1491 	int64_t nrbytes;
1492 	uint64_t deltarbytes, deltatbytes;
1493 	double fractloss;
1494 	int nodata;
1495 	int i;
1496 	char *cp1, *cp2;
1497 	short save_events;
1498 	long flags, saveflags;
1499 
1500 	if (host3 && clientserver) {
1501 		if (client)
1502 			intr = 1;
1503 		return;
1504 	}
1505 
1506 	if (clientserver && client && reading_srvr_info) {
1507 		mes("Error: not receiving server info");
1508 		exit(1);
1509 	}
1510 
1511 #ifdef HAVE_CLOCK_GETTIME
1512 	timec.tv_sec  = 0;	/* silence bogus compiler warning */
1513 	timec.tv_usec = 0;	/* silence bogus compiler warning */
1514 #endif
1515 
1516 	if (interval && !trans) {
1517 		/* Get real time */
1518 		get_timeofday(&timec, (struct timezone *)0);
1519 		tvsub( &timed, &timec, &timep );
1520 		realtd = timed.tv_sec + ((double)timed.tv_usec) / 1000000;
1521 		if (realtd <= 0.0)  realtd = 0.000001;
1522 		tvsub( &timed, &timec, &time0 );
1523 		realt = timed.tv_sec + ((double)timed.tv_usec)
1524 						    / 1000000;
1525 		if (realt <= 0.0)  realt = 0.000001;
1526 	}
1527 
1528 	if (clientserver && !trans) {
1529 		struct sockaddr_in peer;
1530 		socklen_t peerlen = sizeof(peer);
1531 
1532 		nodata = 0;
1533 
1534 		if (getpeername(fd[0], (struct sockaddr *)&peer, &peerlen) < 0)
1535 			nodata = 1;
1536 
1537 		if (!client && udp && got_begin) {
1538 			/* checks if client did a shutdown() for writing
1539 			 * on the control connection */
1540 			pollfds[0].fd = fileno(ctlconn);
1541 			save_events = pollfds[0].events;
1542 			pollfds[0].events = POLLIN | POLLPRI;
1543 			pollfds[0].revents = 0;
1544 			if ((poll(pollfds, 1, 0) > 0) &&
1545 			    (pollfds[0].revents & (POLLIN | POLLPRI))) {
1546 				nodata = 1;
1547 			}
1548 			pollfds[0].events = save_events;
1549 		}
1550 
1551 		if (interval) {
1552 			chk_interval += realtd;
1553 			if (chk_interval >= chk_idle_data) {
1554 				chk_interval = 0;
1555 				if ((nbytes - chk_nbytes) == 0)
1556 					nodata = 1;
1557 				chk_nbytes = nbytes;
1558 			}
1559 		}
1560 		else {
1561 			if ((nbytes - chk_nbytes) == 0)
1562 				nodata = 1;
1563 			chk_nbytes = nbytes;
1564 		}
1565 
1566 		if (nodata) {
1567 			/* Don't just exit anymore so can get partial results
1568 			 * (shouldn't be a problem but keep an eye out that
1569 			 * servers don't start hanging again) */
1570 			if (!client && udp && !interval && handle_urg) {
1571 				/* send 'A' for ABORT as urgent TCP data
1572 				 * on control connection (don't block)
1573 				 *
1574 				 * Only server can do this since client
1575 				 * does a shutdown() for writing on the
1576 				 * control connection */
1577 				saveflags = fcntl(fd[0], F_GETFL, 0);
1578 				if (saveflags != -1) {
1579 					flags = saveflags | O_NONBLOCK;
1580 					fcntl(fd[0], F_SETFL, flags);
1581 				}
1582 				send(fd[0], "A", 1, MSG_OOB);
1583 				if (saveflags != -1) {
1584 					flags = saveflags;
1585 					fcntl(fd[0], F_SETFL, flags);
1586 				}
1587 			}
1588 			if (client) {
1589 				mes("Error: not receiving data from server");
1590 				exit(1);
1591 			}
1592 			close_data_channels();
1593 			intr = 1;
1594 			return;
1595 		}
1596 
1597 		if (!interval)
1598 			return;
1599 	}
1600 
1601 	if (interval && !trans) {
1602 		if ((udp && !got_begin) || done) {
1603 			timep.tv_sec = timec.tv_sec;
1604 			timep.tv_usec = timec.tv_usec;
1605 			return;
1606 		}
1607 		if (clientserver) {
1608 			nrbytes = nbytes;
1609 			if (udplossinfo) {
1610 				ntbytes = *(int64_t *)(buf + 24);
1611 				if (need_swap) {
1612 					cp1 = (char *)&ntbytes;
1613 					cp2 = buf + 31;
1614 					for ( i = 0; i < 8; i++ )
1615 						*cp1++ = *cp2--;
1616 				}
1617 				if (ntbytes > ntbytesc)
1618 					/* received bytes not counted yet */
1619 					nrbytes += buflen;
1620 				if ((nrbytes > ntbytes) ||
1621 				    ((nrbytes - pbytes) > (ntbytes - ptbytes)))
1622 					/* yes they were counted */
1623 					nrbytes -= buflen;
1624 			}
1625 			if (read_retrans) {
1626 				nretrans[1] = *(uint32_t *)(buf + 24);
1627 				if (need_swap) {
1628 					cp1 = (char *)&nretrans[1];
1629 					cp2 = buf + 27;
1630 					for ( i = 0; i < 4; i++ )
1631 						*cp1++ = *cp2--;
1632 				}
1633 			}
1634 			if (read_cwnd) {
1635 				cwnd[1] = *(uint32_t *)(buf + 28);
1636 				if (need_swap) {
1637 					cp1 = (char *)&cwnd[1];
1638 					cp2 = buf + 31;
1639 					for ( i = 0; i < 4; i++ )
1640 						*cp1++ = *cp2--;
1641 				}
1642 				if ((cwnd[1] == 0x5254524Eu) ||    /* "RTRN" */
1643 				    (cwnd[1] == 0x48525452u))      /* "HRTR" */
1644 					cwnd[1] = init_pkt_cwnd;
1645 			}
1646 			if (*ident)
1647 				fprintf(stdout, "%s: ", ident + 1);
1648 			if (format & PARSE)
1649 				strcpy(fmt, P_PERF_FMT_INTERVAL);
1650 			else
1651 				strcpy(fmt, PERF_FMT_INTERVAL);
1652 			fprintf(stdout, fmt,
1653 				(double)(nrbytes - pbytes)/(1024*1024), realtd,
1654 				(double)(nrbytes - pbytes)/realtd/125000);
1655 			if (udplossinfo) {
1656 				if (!(format & NODROPS)) {
1657 					if (format & PARSE)
1658 						strcpy(fmt,
1659 						       P_DROP_FMT_INTERVAL);
1660 					else
1661 						strcpy(fmt, DROP_FMT_INTERVAL);
1662 					fprintf(stdout, fmt,
1663 						((ntbytes - ptbytes)
1664 							- (nrbytes - pbytes))
1665 								/buflen,
1666 						(ntbytes - ptbytes)/buflen);
1667 				}
1668 				if (!(format & NOPERCENTLOSS)) {
1669 					deltarbytes = nrbytes - pbytes;
1670 					deltatbytes = ntbytes - ptbytes;
1671 					fractloss = (deltatbytes ?
1672 						1.0 -
1673 						    (double)deltarbytes
1674 							/(double)deltatbytes :
1675 						0.0);
1676 					if (format & PARSE)
1677 						strcpy(fmt,
1678 						       P_LOSS_FMT_INTERVAL);
1679 					else if ((fractloss != 0.0) &&
1680 						 (fractloss < 0.001))
1681 						strcpy(fmt,
1682 							LOSS_FMT_INTERVAL5);
1683 					else
1684 						strcpy(fmt, LOSS_FMT_INTERVAL);
1685 					fprintf(stdout, fmt, fractloss * 100);
1686 				}
1687 			}
1688 			if ((do_jitter & JITTER_MIN) && njitteri) {
1689 				if (format & PARSE)
1690 					strcpy(fmt, P_JITTER_MIN_FMT_INTERVAL);
1691 				else
1692 					strcpy(fmt, JITTER_MIN_FMT_INTERVAL);
1693 				fprintf(stdout, fmt, jitter_mini);
1694 			}
1695 			if ((do_jitter & JITTER_AVG) && njitteri) {
1696 				if (format & PARSE)
1697 					strcpy(fmt, P_JITTER_AVG_FMT_INTERVAL);
1698 				else
1699 					strcpy(fmt, JITTER_AVG_FMT_INTERVAL);
1700 				fprintf(stdout, fmt, jitter_avgi/njitteri);
1701 			}
1702 			if ((do_jitter & JITTER_MAX) && njitteri) {
1703 				if (format & PARSE)
1704 					strcpy(fmt, P_JITTER_MAX_FMT_INTERVAL);
1705 				else
1706 					strcpy(fmt, JITTER_MAX_FMT_INTERVAL);
1707 				fprintf(stdout, fmt, jitter_maxi);
1708 			}
1709 			if (do_jitter && njitteri) {
1710 				njitteri = 0;
1711 				jitter_mini = 1000000.0;
1712 				jitter_maxi = -1000000.0;
1713 				jitter_avgi = 0.0;
1714 			}
1715 			if (read_retrans && sinkmode) {
1716 				if (format & PARSE)
1717 					fprintf(stdout, P_RETRANS_FMT_INTERVAL,
1718 						((retransinfo == 1) ||
1719 						 !nrbytes) ?  "" : "host-",
1720 						(nretrans[1] - pretrans));
1721 				else
1722 					fprintf(stdout, RETRANS_FMT_INTERVAL,
1723 						(nretrans[1] - pretrans),
1724 						((retransinfo == 1) ||
1725 						 !nrbytes) ?  "" : "host-");
1726 			}
1727 			if (read_cwnd && sinkmode) {
1728 				if (format & PARSE)
1729 					fprintf(stdout, P_CWND_FMT_INTERVAL,
1730 						cwnd[1]);
1731 				else
1732 					fprintf(stdout, CWND_FMT_INTERVAL,
1733 						cwnd[1]);
1734 			}
1735 			if ((do_owd & OWD_MIN) && nowdi) {
1736 				if (format & PARSE)
1737 					strcpy(fmt, P_OWD_MIN_FMT_INTERVAL);
1738 				else
1739 					strcpy(fmt, OWD_MIN_FMT_INTERVAL);
1740 				fprintf(stdout, fmt, owd_mini);
1741 			}
1742 			if ((do_owd & OWD_AVG) && nowdi) {
1743 				if (format & PARSE)
1744 					strcpy(fmt, P_OWD_AVG_FMT_INTERVAL);
1745 				else
1746 					strcpy(fmt, OWD_AVG_FMT_INTERVAL);
1747 				fprintf(stdout, fmt, owd_avgi/nowdi);
1748 			}
1749 			if ((do_owd & OWD_MAX) && nowdi) {
1750 				if (format & PARSE)
1751 					strcpy(fmt, P_OWD_MAX_FMT_INTERVAL);
1752 				else
1753 					strcpy(fmt, OWD_MAX_FMT_INTERVAL);
1754 				fprintf(stdout, fmt, owd_maxi);
1755 			}
1756 			if (do_owd && nowdi) {
1757 				nowdi = 0;
1758 				owd_mini = 1000000.0;
1759 				owd_maxi = -1000000.0;
1760 				owd_avgi = 0.0;
1761 			}
1762 			if (format & RUNNINGTOTAL) {
1763 				if (format & PARSE)
1764 					strcpy(fmt, P_PERF_FMT_INTERVAL2);
1765 				else
1766 					strcpy(fmt, PERF_FMT_INTERVAL2);
1767 				fprintf(stdout, fmt,
1768 					(double)nrbytes/(1024*1024), realt,
1769 					(double)nrbytes/realt/125000);
1770 				if (udplossinfo) {
1771 					if (!(format & NODROPS)) {
1772 						if (format & PARSE)
1773 							strcpy(fmt,
1774 							  P_DROP_FMT_INTERVAL);
1775 						else
1776 							strcpy(fmt,
1777 							  DROP_FMT_INTERVAL);
1778 						fprintf(stdout, fmt,
1779 							(ntbytes - nrbytes)
1780 								/buflen,
1781 							ntbytes/buflen);
1782 					}
1783 					if (!(format & NOPERCENTLOSS)) {
1784 						fractloss = (ntbytes ?
1785 							1.0 -
1786 							    (double)nrbytes
1787 							      /(double)ntbytes :
1788 							0.0);
1789 						if (format & PARSE)
1790 							strcpy(fmt,
1791 							  P_LOSS_FMT_INTERVAL);
1792 						else if ((fractloss != 0.0) &&
1793 							 (fractloss < 0.001))
1794 							strcpy(fmt,
1795 							  LOSS_FMT_INTERVAL5);
1796 						else
1797 							strcpy(fmt,
1798 							  LOSS_FMT_INTERVAL);
1799 						fprintf(stdout, fmt,
1800 							fractloss * 100);
1801 					}
1802 				}
1803 				if (read_retrans && sinkmode) {
1804 					if (format & PARSE)
1805 						fprintf(stdout,
1806 							P_RETRANS_FMT_INTERVAL,
1807 							((retransinfo == 1) ||
1808 							 !nrbytes) ?
1809 							    "" : "host-",
1810 							nretrans[1]);
1811 					else
1812 						fprintf(stdout,
1813 							RETRANS_FMT_INTERVAL,
1814 							nretrans[1],
1815 							((retransinfo == 1) ||
1816 							 !nrbytes) ?
1817 							    "" : "host-");
1818 				}
1819 				if (read_cwnd && sinkmode) {
1820 					if (format & PARSE)
1821 						fprintf(stdout,
1822 							P_CWND_FMT_INTERVAL,
1823 							cwnd[1]);
1824 					else
1825 						fprintf(stdout,
1826 							CWND_FMT_INTERVAL,
1827 							cwnd[1]);
1828 				}
1829 			}
1830 			if (udplossinfo && (format & XMITSTATS)) {
1831 				if (format & PARSE)
1832 					strcpy(fmt, P_PERF_FMT_INTERVAL3);
1833 				else
1834 					strcpy(fmt, PERF_FMT_INTERVAL3);
1835 				fprintf(stdout, fmt,
1836 					(double)(ntbytes - ptbytes)/1024/1024);
1837 				if (format & RUNNINGTOTAL) {
1838 					if (format & PARSE)
1839 						strcpy(fmt,
1840 						       P_PERF_FMT_INTERVAL4);
1841 					else
1842 						strcpy(fmt, PERF_FMT_INTERVAL4);
1843 					fprintf(stdout, fmt,
1844 						(double)ntbytes/1024/1024);
1845 					if (format & DEBUGINTERVAL)
1846 						fprintf(stdout, " Pre: %.4f MB",
1847 							(double)ntbytesc
1848 								  /1024/1024);
1849 				}
1850 			}
1851 			fprintf(stdout, "\n");
1852 			fflush(stdout);
1853 			timep.tv_sec = timec.tv_sec;
1854 			timep.tv_usec = timec.tv_usec;
1855 			pbytes = nrbytes;
1856 			ptbytes = ntbytes;
1857 			pretrans = nretrans[1];
1858 		}
1859 	}
1860 	else
1861 		intr = 1;
1862 	return;
1863 }
1864 
1865 int
main(int argc,char ** argv)1866 main( int argc, char **argv )
1867 {
1868 	double MB;
1869 	double rate_opt;
1870 	double fractloss;
1871 	int cpu_util;
1872 	int first_read;
1873 	int first_jitter, first_jitteri;
1874 	int ocorrection = 0;
1875 	double  correction = 0.0;
1876 	int pollst = 0;
1877 	int i = 0, j = 0;
1878 	char *cp1 = NULL, *cp2 = NULL, *cp3 = NULL;
1879 	char *hostaddr;
1880 	char ch = '\0';
1881 	int error_num = 0;
1882 	int sockopterr = 0;
1883 	int save_errno;
1884 	struct servent *sp = 0;
1885 	struct addrinfo hints, *res[MAXSTREAM + 1] = { NULL },
1886 			*host3res, *mcres = NULL;
1887 	union sockaddr_union client_ipaddr;
1888 	struct sockaddr_storage dummy;
1889 	struct timeval time_eod  = {0};	/* time EOD packet was received */
1890 	struct timeval time_eod0 = {0};	/* time EOD0 packet was received */
1891 	struct timeval timed;		/* time delta */
1892 	struct timeval timeconn1 = {0};	/* time before connect() for RTT */
1893 	struct timeval timeconn2 = {0};	/* time after connect() for RTT */
1894 	struct timeval timeconn;	/* time to connect() == RTT */
1895 	union {
1896 		unsigned char	buf[sizeof(struct in_addr)];
1897 		uint32_t	ip32;
1898 	} ipad_stride;			/* IPv4 address stride */
1899 	short save_events;
1900 	int skiparg;
1901 	int reqval;
1902 	int got_srvr_retrans;
1903 	int got_srvr_cwnd;
1904 	uint32_t total_retrans = 0;	/* total retrans for all streams */
1905 	uint32_t total_snd_cwnd = 0;	/* total cwnd for all streams in KB */
1906 	double idle_data_min = IDLE_DATA_MIN;
1907 	double idle_data_max = IDLE_DATA_MAX;
1908 	double default_idle_data = DEFAULT_IDLE_DATA;
1909 	char multsrc[ADDRSTRLEN] = "\0";
1910 	char multaddr[ADDRSTRLEN] = "\0";
1911 	long flags;
1912 	int nameinfo_flags;
1913 	int implicit_hostaddr;
1914 
1915 	sendwin = 0;
1916 	rcvwin = 0;
1917 	srvrwin = -1;
1918 	format |= WANTRTT;
1919 
1920 	if (argc < 2) goto usage;
1921 
1922 	nut_cmd = argv[0];
1923 	argv++; argc--;
1924 	while (argc>0 && argv[0][0] == '-') {
1925 		skiparg = 0;
1926 		switch (argv[0][1]) {
1927 
1928 		case '4':
1929 			domain = PF_INET;
1930 			af = AF_INET;
1931 			explicitaf = 1;
1932 			break;
1933 #ifdef AF_INET6
1934 		case '6':
1935 			domain = PF_INET6;
1936 			af = AF_INET6;
1937 			explicitaf = 1;
1938 			break;
1939 #endif
1940 		case 'B':
1941 			b_flag = 1;
1942 			break;
1943 		case 't':
1944 			trans = 1;
1945 			break;
1946 		case 'r':
1947 			trans = 0;
1948 			break;
1949 		case 'd':
1950 			options |= SO_DEBUG;
1951 			break;
1952 		case 'D':
1953 			nodelay = 1;
1954 			break;
1955 		case 'n':
1956 			reqval = 0;
1957 			if (argv[0][2] == 'b') {
1958 				fprintf(stderr, "option \"-nb\" no longer supported, use \"-n###[k|m|g|t|p]\" instead\n");
1959 				fflush(stderr);
1960 				exit(1);
1961 			}
1962 			cp1 = getoptvalp(argv, 2, reqval, &skiparg);
1963 			nbuf = strtoull(cp1, NULL, 0);
1964 			if (nbuf == 0) {
1965 				if (errno == EINVAL) {
1966 					fprintf(stderr, "invalid nbuf = %s\n",
1967 						&argv[0][2]);
1968 					fflush(stderr);
1969 					exit(1);
1970 				}
1971 				else {
1972 					nbuf = DEFAULT_NBUF;
1973 					break;
1974 				}
1975 			}
1976 			if (*cp1)
1977 				ch = *(cp1 + strlen(cp1) - 1);
1978 			else
1979 				ch = '\0';
1980 			if ((ch == 'b') || (ch == 'B'))
1981 				nbuf_bytes = 1;
1982 			else if ((ch == 'k') || (ch == 'K')) {
1983 				nbuf *= 1024;
1984 				nbuf_bytes = 1;
1985 			}
1986 			else if ((ch == 'm') || (ch == 'M')) {
1987 				nbuf *= 1048576;
1988 				nbuf_bytes = 1;
1989 			}
1990 			else if ((ch == 'g') || (ch == 'G')) {
1991 				nbuf *= 1073741824;
1992 				nbuf_bytes = 1;
1993 			}
1994 			else if ((ch == 't') || (ch == 'T')) {
1995 				nbuf *= 1099511627776ull;
1996 				nbuf_bytes = 1;
1997 			}
1998 			else if ((ch == 'p') || (ch == 'P')) {
1999 				nbuf *= 1125899906842624ull;
2000 				nbuf_bytes = 1;
2001 			}
2002 			break;
2003 		case 'l':
2004 			reqval = 1;
2005 			cp1 = getoptvalp(argv, 2, reqval, &skiparg);
2006 			buflen = atoi(cp1);
2007 			buflenopt = 1;
2008 			if (buflen < 1) {
2009 				fprintf(stderr, "invalid buflen = %d\n", buflen);
2010 				fflush(stderr);
2011 				exit(1);
2012 			}
2013 			if (*cp1)
2014 				ch = *(cp1 + strlen(cp1) - 1);
2015 			else
2016 				ch = '\0';
2017 			if ((ch == 'k') || (ch == 'K'))
2018 				buflen *= 1024;
2019 			else if ((ch == 'm') || (ch == 'M'))
2020 				buflen *= 1048576;
2021 			break;
2022 		case 'w':
2023 			reqval = 1;
2024 			if (argv[0][2] == 's') {
2025 				cp1 = getoptvalp(argv, 3, reqval, &skiparg);
2026 				srvrwin = atoi(cp1);
2027 				if (*cp1)
2028 					ch = *(cp1 + strlen(cp1) - 1);
2029 				else
2030 					ch = '\0';
2031 				if ((ch == 'k') || (ch == 'K'))
2032 					srvrwin *= 1024;
2033 				else if ((ch == 'm') || (ch == 'M'))
2034 					srvrwin *= 1048576;
2035 				else if ((ch == 'g') || (ch == 'G'))
2036 					srvrwin *= 1073741824;
2037 				else if ((ch != 'b') && (ch != 'B'))
2038 					srvrwin *= 1024;
2039 				if (srvrwin < 0) {
2040 					fprintf(stderr, "invalid srvrwin = %d\n", srvrwin);
2041 					fflush(stderr);
2042 					exit(1);
2043 				}
2044 			}
2045 			else {
2046 				if (argv[0][2] == 'b') {
2047 					braindead = 1;
2048 					cp1 = getoptvalp(argv, 3, reqval,
2049 							 &skiparg);
2050 					if (*cp1 == '\0')
2051 						break;
2052 					sendwin = atoi(cp1);
2053 				}
2054 				else {
2055 					cp1 = getoptvalp(argv, 2, reqval,
2056 							 &skiparg);
2057 					sendwin = atoi(cp1);
2058 				}
2059 
2060 				if (*cp1)
2061 					ch = *(cp1 + strlen(cp1) - 1);
2062 				else
2063 					ch = '\0';
2064 				if ((ch == 'k') || (ch == 'K'))
2065 					sendwin *= 1024;
2066 				else if ((ch == 'm') || (ch == 'M'))
2067 					sendwin *= 1048576;
2068 				else if ((ch == 'g') || (ch == 'G'))
2069 					sendwin *= 1073741824;
2070 				else if ((ch != 'b') && (ch != 'B'))
2071 					sendwin *= 1024;
2072 				rcvwin = sendwin;
2073 				if (sendwin < 0) {
2074 					fprintf(stderr, "invalid sendwin = %d\n", sendwin);
2075 					fflush(stderr);
2076 					exit(1);
2077 				}
2078 			}
2079 			if (srvrwin == -1) {
2080 				srvrwin = sendwin;
2081 			}
2082 			break;
2083 		case 's':
2084 			sinkmode = 0;	/* sink/source data */
2085 #if defined(linux)
2086 			if (strchr(argv[0], 'z'))
2087 				zerocopy = 1;
2088 			if (strchr(argv[0], 'd'))
2089 				directio = 1;
2090 #endif
2091 			break;
2092 		case 'p':
2093 			reqval = 1;
2094 			cp1 = getoptvalp(argv, 2, reqval, &skiparg);
2095 			if ((cp2 = strchr(cp1, ':'))) {
2096 				tmpport = atoi(cp1);
2097 				if ((tmpport < 1024) || (tmpport > 65535)) {
2098 					fprintf(stderr,
2099 						"invalid source port = %d\n",
2100 						tmpport);
2101 					fflush(stderr);
2102 					exit(1);
2103 				}
2104 				srcport = tmpport;
2105 				cp1 = cp2 + 1;
2106 			}
2107 			tmpport = atoi(cp1);
2108 			if ((tmpport < 1024) || (tmpport > 65535)) {
2109 				fprintf(stderr, "invalid port = %d\n", tmpport);
2110 				fflush(stderr);
2111 				exit(1);
2112 			}
2113 			port = tmpport;
2114 			break;
2115 		case 'P':
2116 			reqval = 1;
2117 			cp1 = getoptvalp(argv, 2, reqval, &skiparg);
2118 			if ((cp2 = strchr(cp1, ':'))) {
2119 				tmpport = atoi(cp1);
2120 				if ((tmpport < 1024) || (tmpport > 65535)) {
2121 					fprintf(stderr,
2122 						"invalid source "
2123 						"control port = %d\n", tmpport);
2124 					fflush(stderr);
2125 					exit(1);
2126 				}
2127 				srcctlport = tmpport;
2128 				cp1 = cp2 + 1;
2129 			}
2130 			tmpport = atoi(cp1);
2131 			if ((tmpport < 1024) || (tmpport > 65535)) {
2132 				fprintf(stderr,
2133 					"invalid ctlport = %d\n", tmpport);
2134 				fflush(stderr);
2135 				exit(1);
2136 			}
2137 			ctlport = tmpport;
2138 			if ((cp2 = strchr(argv[0], '/'))) {
2139 				if (strchr(cp2, ':')) {
2140 					fprintf(stderr,
2141 						"can't specify source control "
2142 						"port with third party\n");
2143 					fflush(stderr);
2144 					exit(1);
2145 				}
2146 				tmpport = atoi(cp2 + 1);
2147 				if ((tmpport < 1024) || (tmpport > 65535)) {
2148 					fprintf(stderr,
2149 						"invalid third party "
2150 						"ctlport = %d\n", tmpport);
2151 					fflush(stderr);
2152 					exit(1);
2153 				}
2154 				ctlport3 = tmpport;
2155 			}
2156 			break;
2157 		case 'u':
2158 			udp = 1;
2159 			if (!buflenopt) buflen = DEFAULTUDPBUFLEN;
2160 			if (argv[0][2] == 'u') {
2161 				haverateopt = 1;
2162 				rate = MAXRATE;
2163 			}
2164 			break;
2165 		case 'j':
2166 			reqval = 0;
2167 			cp1 = getoptvalp(argv, 2, reqval, &skiparg);
2168 			if (strchr(cp1, 'm'))
2169 				do_jitter |= JITTER_MIN;
2170 			if (strchr(cp1, 'a'))
2171 				do_jitter |= JITTER_AVG;
2172 			if (strchr(cp1, 'x'))
2173 				do_jitter |= JITTER_MAX;
2174 			if (do_jitter == 0)
2175 				do_jitter = JITTER_MAX;
2176 			if (strchr(cp1, 'o'))
2177 				do_jitter |= JITTER_IGNORE_OOO;
2178 			udp = 1;
2179 			if (!buflenopt) buflen = DEFAULTUDPBUFLEN;
2180 			break;
2181 		case 'o':
2182 			reqval = 0;
2183 			cp1 = getoptvalp(argv, 2, reqval, &skiparg);
2184 			if (strchr(cp1, 'm'))
2185 				do_owd |= OWD_MIN;
2186 			if (strchr(cp1, 'a'))
2187 				do_owd |= OWD_AVG;
2188 			if (strchr(cp1, 'x'))
2189 				do_owd |= OWD_MAX;
2190 			if (do_owd == 0)
2191 				do_owd = OWD_AVG;
2192 			break;
2193 		case 'v':
2194 			brief = 0;
2195 			if (argv[0][2] == 'v')
2196 				verbose = 1;
2197 			break;
2198 		case 'N':
2199 			reqval = 1;
2200 			cp1 = getoptvalp(argv, 2, reqval, &skiparg);
2201 			nstream = atoi(cp1);
2202 			if (strchr(cp1, 'm'))
2203 				multilink = 1;
2204 			if (nstream < 1) {
2205 				fprintf(stderr, "invalid nstream = %d\n", nstream);
2206 				fflush(stderr);
2207 				exit(1);
2208 			}
2209 			if (nstream > MAXSTREAM) {
2210 				fprintf(stderr, "nstream = %d > MAXSTREAM, set to %d\n",
2211 				    nstream, MAXSTREAM);
2212 				nstream = MAXSTREAM;
2213 			}
2214 			if (nstream > 1) {
2215 				b_flag = 1;
2216 				send_retrans = 0;
2217 				read_retrans = 0;
2218 				send_cwnd = 0;
2219 				read_cwnd = 0;
2220 			}
2221 			break;
2222 		case 'R':
2223 			reqval = 1;
2224 			haverateopt = 1;
2225 			cp1 = getoptvalp(argv, 2, reqval, &skiparg);
2226 			if (*cp1 == 'i') {
2227 				cp1++;
2228 				if (*cp1 == 's') {
2229 					cp1++;
2230 #if defined(linux)
2231 					iratesss = 1;
2232 #else
2233 					fprintf(stderr, "smoothed slow start not supported for non-Linux\n");
2234 					fflush(stderr);
2235 #endif
2236 				}
2237 				sscanf(cp1, "%lf", &rate_opt);
2238 				irate = 1;
2239 			}
2240 			else if (*cp1 == 'a') {
2241 				cp1++;
2242 				sscanf(cp1, "%lf", &rate_opt);
2243 				irate = 0;
2244 			}
2245 			else if (*cp1 == 'u') {
2246 				cp1++;
2247 				rate_opt = 0.0;
2248 				irate = 0;
2249 			}
2250 			else {
2251 				sscanf(cp1, "%lf", &rate_opt);
2252 			}
2253 			if ((cp2 = strchr(cp1, '/'))) {
2254 				*cp2++ = '\0';
2255 				maxburst = atoi(cp2);
2256 				if (maxburst <= 0) {
2257 					fprintf(stderr,
2258 						"invalid maxburst = %d\n",
2259 						maxburst);
2260 					fflush(stderr);
2261 					exit(1);
2262 				}
2263 			}
2264 			if (*cp1)
2265 				ch = *(cp1 + strlen(cp1) - 1);
2266 			else
2267 				ch = '\0';
2268 			if ((ch == 'm') || (ch == 'M'))
2269 				rate_opt *= 1000;
2270 			else if ((ch == 'g') || (ch == 'G'))
2271 				rate_opt *= 1000000;
2272 			else if (ch == 'p') {
2273 				rate_pps = 1;
2274 				if (strlen(cp1) >= 2) {
2275 					ch = *(cp1 + strlen(cp1) - 2);
2276 					if ((ch == 'k') || (ch == 'K'))
2277 						rate_opt *= 1000;
2278 					if ((ch == 'm') || (ch == 'M'))
2279 						rate_opt *= 1000000;
2280 				}
2281 			}
2282 			rate = rate_opt;
2283 			if (rate == 0)
2284 				rate = MAXRATE;
2285 			break;
2286 		case 'T':
2287 			reqval = 0;
2288 			cp1 = getoptvalp(argv, 2, reqval, &skiparg);
2289 			sscanf(cp1, "%lf", &timeout);
2290 			if (timeout < 0) {
2291 				fprintf(stderr, "invalid timeout = %f\n", timeout);
2292 				fflush(stderr);
2293 				exit(1);
2294 			}
2295 			else if (timeout == 0.0)
2296 				timeout = DEFAULT_TIMEOUT;
2297 			if (*cp1)
2298 				ch = *(cp1 + strlen(cp1) - 1);
2299 			else
2300 				ch = '\0';
2301 			if ((ch == 'm') || (ch == 'M'))
2302 				timeout *= 60.0;
2303 			else if ((ch == 'h') || (ch == 'H'))
2304 				timeout *= 3600.0;
2305 			else if ((ch == 'd') || (ch == 'D'))
2306 				timeout *= 86400.0;
2307 			itimer.it_value.tv_sec = timeout;
2308 			itimer.it_value.tv_usec =
2309 				(timeout - itimer.it_value.tv_sec)*1000000;
2310 			if (timeout && !nbuf)
2311 				nbuf = INT_MAX;
2312 			break;
2313 		case 'i':
2314 			reqval = 0;
2315 			cp1 = getoptvalp(argv, 2, reqval, &skiparg);
2316 			sscanf(cp1, "%lf", &interval);
2317 			if (interval < 0.0) {
2318 				fprintf(stderr, "invalid interval = %f\n", interval);
2319 				fflush(stderr);
2320 				exit(1);
2321 			}
2322 			else if (interval == 0.0)
2323 				interval = 1.0;
2324 			if (*cp1)
2325 				ch = *(cp1 + strlen(cp1) - 1);
2326 			else
2327 				ch = '\0';
2328 			if ((ch == 'm') || (ch == 'M'))
2329 				interval *= 60.0;
2330 			else if ((ch == 'h') || (ch == 'H'))
2331 				interval *= 3600.0;
2332 			break;
2333 		case 'I':
2334 			reqval = 1;
2335 			ident[0] = '-';
2336 			strncpy(&ident[1],
2337 				getoptvalp(argv, 2, reqval, &skiparg), 40);
2338 			ident[41] = '\0';
2339 			break;
2340 		case 'F':
2341 			reverse = 1;
2342 			break;
2343 		case 'b':
2344 			reqval = 0;
2345 			cp1 = getoptvalp(argv, 2, reqval, &skiparg);
2346 			if (*cp1) {
2347 				if (isalpha((int)(*cp1)))
2348 					brief = 1;
2349 				else
2350 					brief = atoi(cp1);
2351 				if (strchr(cp1, 'r'))
2352 					brief |= BRIEF_RETRANS_STREAMS;
2353 				if (strchr(cp1, 'c')) {
2354 #if defined(linux)
2355 					brief |= BRIEF_CWND_STREAMS;
2356 #else
2357 					fprintf(stderr, "\"-bc\" option not supported for non-Linux\n");
2358 					fflush(stderr);
2359 #endif
2360 				}
2361 			}
2362 			else
2363 				brief = 1;
2364 			break;
2365 		case 'S':
2366 			if (strchr(&argv[0][2], 'P'))
2367 				pass_ctlport = 1;
2368 			trans = 0;
2369 			clientserver = 1;
2370 			brief = 0;
2371 			verbose = 1;
2372 			break;
2373 		case '1':
2374 			oneshot = 1;
2375 			trans = 0;
2376 			clientserver = 1;
2377 			brief = 0;
2378 			verbose = 1;
2379 			break;
2380 		case 'V':
2381 			fprintf(stdout, "nuttcp-%d.%d.%d%s\n", vers_major,
2382 					vers_minor, vers_delta,
2383 					beta ? BETA_STR : "");
2384 			exit(0);
2385 		case 'f':
2386 			if (strcmp(&argv[0][2], "xmitstats") == 0)
2387 				format |= XMITSTATS;
2388 			else if (strcmp(&argv[0][2], "debuginterval") == 0)
2389 				format |= DEBUGINTERVAL;
2390 			else if (strcmp(&argv[0][2], "runningtotal") == 0)
2391 				format |= RUNNINGTOTAL;
2392 			else if (strcmp(&argv[0][2], "-percentloss") == 0)
2393 				format |= NOPERCENTLOSS;
2394 			else if (strcmp(&argv[0][2], "-drops") == 0)
2395 				format |= NODROPS;
2396 			else if (strcmp(&argv[0][2], "-retrans") == 0) {
2397 				format |= NORETRANS;
2398 				format |= NOCWND;
2399 			}
2400 			else if (strcmp(&argv[0][2], "debugretrans") == 0)
2401 				format |= DEBUGRETRANS;
2402 			else if (strcmp(&argv[0][2], "-cwnd") == 0)
2403 				format |= NOCWND;
2404 			else if (strcmp(&argv[0][2], "debugpoll") == 0)
2405 				format |= DEBUGPOLL;
2406 			else if (strcmp(&argv[0][2], "debugmtu") == 0)
2407 				format |= DEBUGMTU;
2408 			else if (strcmp(&argv[0][2], "debugjitter") == 0)
2409 				format |= DEBUGJITTER;
2410 #if defined(linux)
2411 			else if (strcmp(&argv[0][2], "debugirate") == 0)
2412 				format |= DEBUGIRATE;
2413 #endif
2414 			else if (strcmp(&argv[0][2], "parse") == 0)
2415 				format |= PARSE;
2416 			else if (strcmp(&argv[0][2], "-beta") == 0)
2417 				format |= NOBETAMSG;
2418 			/* below is for compatibility with 6.0.x beta */
2419 			else if (strcmp(&argv[0][2], "rtt") == 0)
2420 				format |= WANTRTT;
2421 			else if (strcmp(&argv[0][2], "-rtt") == 0)
2422 				format &= ~WANTRTT;
2423 			else {
2424 				if (argv[0][2]) {
2425 					fprintf(stderr, "invalid format option \"%s\"\n", &argv[0][2]);
2426 					fflush(stderr);
2427 					exit(1);
2428 				}
2429 				else {
2430 					fprintf(stderr, "invalid null format option\n");
2431 					fprintf(stderr, "perhaps the \"-F\" flip option was intended\n");
2432 					fflush(stderr);
2433 					exit(1);
2434 				}
2435 			}
2436 			break;
2437 		case 'x':
2438 			reqval = 1;
2439 			if (argv[0][2] == 't') {
2440 				traceroute = 1;
2441 				brief = 1;
2442 			}
2443 #ifdef HAVE_SETPRIO
2444 			else if (argv[0][2] == 'P') {
2445 				priority = atoi(getoptvalp(argv, 3, reqval,
2446 						&skiparg));
2447 			}
2448 #endif
2449 #ifdef HAVE_SETAFFINITY
2450 			else if (argv[0][2] == 'c') {
2451 				reqval = 1;
2452 				if (argv[0][3] == 's') {
2453 					cp1 = getoptvalp(argv, 4, reqval,
2454 							 &skiparg);
2455 					srvr_affinity = atoi(cp1);
2456 					if (srvr_affinity < 0) {
2457 						fprintf(stderr,
2458 							"invalid srvr_affinity "
2459 							"= %d\n",
2460 							srvr_affinity);
2461 						fflush(stderr);
2462 						exit(1);
2463 					}
2464 				}
2465 				else {
2466 					cp1 = getoptvalp(argv, 3, reqval,
2467 							 &skiparg);
2468 					affinity = atoi(cp1);
2469 					if ((affinity < 0) ||
2470 					    (affinity >= CPU_SETSIZE)) {
2471 						fprintf(stderr,
2472 							"invalid affinity "
2473 							"= %d\n", affinity);
2474 						fflush(stderr);
2475 						exit(1);
2476 					}
2477 					if ((cp2 = strchr(cp1, '/'))) {
2478 						srvr_affinity = atoi(cp2 + 1);
2479 						if (srvr_affinity < 0) {
2480 							fprintf(stderr,
2481 								"invalid "
2482 								"srvr_affinity "
2483 								"= %d\n",
2484 								srvr_affinity);
2485 							fflush(stderr);
2486 							exit(1);
2487 						}
2488 					}
2489 				}
2490 			}
2491 #endif
2492 			else {
2493 				if (argv[0][2]) {
2494 					fprintf(stderr, "invalid x option \"%s\"\n", &argv[0][2]);
2495 					fflush(stderr);
2496 					exit(1);
2497 				}
2498 				else {
2499 					fprintf(stderr, "invalid null x option\n");
2500 					fflush(stderr);
2501 					exit(1);
2502 				}
2503 			}
2504 			break;
2505 		case '3':
2506 			thirdparty = 1;
2507 			break;
2508 		case 'm':
2509 			reqval = 0;
2510 			if (argv[0][2] == 'a') {
2511 				ssm = 0;
2512 				cp1 = getoptvalp(argv, 3, reqval, &skiparg);
2513 			}
2514 			else if (argv[0][2] == 's') {
2515 #ifdef MCAST_JOIN_SOURCE_GROUP
2516 				ssm = 1;
2517 				cp1 = getoptvalp(argv, 3, reqval, &skiparg);
2518 #else
2519 				fprintf(stderr,
2520 					"This system does not support SSM\n");
2521 				fflush(stderr);
2522 				exit(1);
2523 #endif
2524 			}
2525 			else {
2526 				cp1 = getoptvalp(argv, 2, reqval, &skiparg);
2527 			}
2528 			if (*cp1)
2529 				mc_param = atoi(cp1);
2530 			else
2531 				mc_param = 1;
2532 			if ((mc_param < 1) || (mc_param > 255)) {
2533 				fprintf(stderr, "invalid multicast ttl = %d\n", mc_param);
2534 				fflush(stderr);
2535 				exit(1);
2536 			}
2537 			multicast = mc_param;
2538 			break;
2539 		case 'g':
2540 			reqval = 1;
2541 			mc_addr = getoptvalp(argv, 2, reqval, &skiparg);
2542 			break;
2543 		case 'M':
2544 			reqval = 1;
2545 			datamss = atoi(getoptvalp(argv, 2, reqval, &skiparg));
2546 			if (datamss < 0) {
2547 				fprintf(stderr, "invalid datamss = %d\n", datamss);
2548 				fflush(stderr);
2549 				exit(1);
2550 			}
2551 			break;
2552 		case 'c':
2553 			reqval = 1;
2554 			cp1 = getoptvalp(argv, 2, reqval, &skiparg);
2555 			tos = strtol(cp1, NULL, 0);
2556 			if (*cp1)
2557 				ch = *(cp1 + strlen(cp1) - 1);
2558 			else
2559 				ch = '\0';
2560 			if ((ch == 'p') || (ch == 'P')) {
2561 				/* Precedence */
2562 				if (tos > 7) {
2563 					fprintf(stderr, "invalid precedence = %d\n", tos);
2564 					fflush(stderr);
2565 					exit(1);
2566 				}
2567 				tos <<= 5;
2568 			}
2569 			else if ((ch != 't') && (ch != 'T')) {
2570 				/* DSCP */
2571 				if (tos > 63) {
2572 					fprintf(stderr, "invalid dscp = %d\n", tos);
2573 					fflush(stderr);
2574 					exit(1);
2575 				}
2576 				tos <<= 2;
2577 			}
2578 			if (tos > 255) {
2579 				fprintf(stderr, "invalid tos = %d\n", tos);
2580 				fflush(stderr);
2581 				exit(1);
2582 			}
2583 			break;
2584 		case 'a':
2585 			retry_server = 1;
2586 			break;
2587 		case '-':
2588 			if (strcmp(&argv[0][2], "nofork") == 0) {
2589 				nofork=1;
2590 			}
2591 			else if (strcmp(&argv[0][2], "no3rdparty") == 0) {
2592 				no3rd=1;
2593 			}
2594 			else if (strcmp(&argv[0][2],
2595 				 "idle-data-timeout") == 0) {
2596 				if ((cp1 = strchr(argv[1], '/'))) {
2597 					if (strchr(cp1 + 1, '/')) {
2598 						if (sscanf(argv[1],
2599 							"%lf/%lf/%lf",
2600 							&idle_data_min,
2601 							&default_idle_data,
2602 							&idle_data_max) != 3) {
2603 							fprintf(stderr, "error scanning idle-data-timeout parameter = %s\n", argv[1]);
2604 							fflush(stderr);
2605 							exit(1);
2606 						}
2607 						if (idle_data_min <= 0.0) {
2608 							fprintf(stderr, "invalid value for idle-data-timeout minimum = %f\n", idle_data_min);
2609 							fflush(stderr);
2610 							exit(1);
2611 						}
2612 						if (default_idle_data <= 0.0) {
2613 							fprintf(stderr, "invalid value for idle-data-timeout default = %f\n", default_idle_data);
2614 							fflush(stderr);
2615 							exit(1);
2616 						}
2617 						if (idle_data_max <= 0.0) {
2618 							fprintf(stderr, "invalid value for idle-data-timeout maximum = %f\n", idle_data_max);
2619 							fflush(stderr);
2620 							exit(1);
2621 						}
2622 						if (idle_data_max <
2623 							idle_data_min) {
2624 							fprintf(stderr, "error: idle-data-timeout maximum of %f < minimum of %f\n", idle_data_max, idle_data_min);
2625 							fflush(stderr);
2626 							exit(1);
2627 						}
2628 					}
2629 					else {
2630 						fprintf(stderr, "invalid idle-data-timeout parameter = %s\n", argv[1]);
2631 						fflush(stderr);
2632 						exit(1);
2633 					}
2634 				}
2635 				else {
2636 					sscanf(argv[1], "%lf", &idle_data_min);
2637 					if (idle_data_min <= 0.0) {
2638 						fprintf(stderr, "invalid value for idle-data-timeout = %f\n", idle_data_min);
2639 						fflush(stderr);
2640 						exit(1);
2641 					}
2642 					idle_data_max = idle_data_min;
2643 					default_idle_data = idle_data_min;
2644 				}
2645 				argv++;
2646 				argc--;
2647 			}
2648 			else if (strcmp(&argv[0][2], "single-threaded") == 0) {
2649 				single_threaded=1;
2650 			}
2651 			else if (strcmp(&argv[0][2], "packet-burst") == 0) {
2652 				maxburst = atoi(argv[1]);
2653 				if (maxburst <= 0) {
2654 					fprintf(stderr,
2655 						"invalid maxburst = %d\n",
2656 						maxburst);
2657 					fflush(stderr);
2658 					exit(1);
2659 				}
2660 				argv++;
2661 				argc--;
2662 			}
2663 #ifdef IPV6_V6ONLY
2664 			else if (strcmp(&argv[0][2], "disable-v4-mapped") == 0) {
2665 				v4mapped=0;
2666 			}
2667 			else if (strcmp(&argv[0][2], "enable-v4-mapped") == 0) {
2668 				v4mapped=1;
2669 			}
2670 #endif
2671 			else {
2672 				goto usage;
2673 			}
2674 			break;
2675 		case 'h':
2676 		default:
2677 			goto usage;
2678 		}
2679 		argv++;
2680 		argc--;
2681 		if (skiparg) {
2682 			argv++;
2683 			argc--;
2684 		}
2685 	}
2686 
2687 	if (argc > 2) goto usage;
2688 	if (trans && (argc < 1)) goto usage;
2689 	if (clientserver && (argc != 0)) goto usage;
2690 
2691 	if (!clientserver && !trans && (argc < 1)) {
2692 		fprintf(stderr,
2693 			"nuttcp: Warning: Using obsolete \"classic\" mode:\n");
2694 		fprintf(stderr,
2695 			"                 Automatically switching to "
2696 					  "oneshot server mode "
2697 					  "(\"nuttcp -1\")\n");
2698 		oneshot = 1;
2699 		trans = 0;
2700 		clientserver = 1;
2701 		brief = 0;
2702 		verbose = 1;
2703 	}
2704 
2705 	host3 = NULL;
2706 	if (argc == 2) {
2707 		host3 = argv[1];
2708 		if (strlen(host3) > HOSTNAMELEN) {
2709 			fprintf(stderr, "3rd party host '%s' too long\n", host3);
2710 			fflush(stderr);
2711 			exit(1);
2712 		}
2713 		cp1 = host3;
2714 		while (*cp1) {
2715 			if (!isalnum((int)(*cp1)) && (*cp1 != '-') && (*cp1 != '.')
2716 					   && (*cp1 != ':') && (*cp1 != '/')
2717 					   && (*cp1 != '+') && (*cp1 != '=')) {
2718 				fprintf(stderr, "invalid 3rd party host '%s'\n", host3);
2719 				fflush(stderr);
2720 				exit(1);
2721 			}
2722 			cp1++;
2723 		}
2724 	}
2725 
2726 	if (multicast) {
2727 		udp = 1;
2728 		if (!buflenopt) buflen = DEFAULT_MC_UDPBUFLEN;
2729 		nstream = 1;
2730 	}
2731 
2732 	if (mc_addr && !multicast) {
2733 		fprintf(stderr, "can't use \"-g\" option for non-multicast\n");
2734 		fflush(stderr);
2735 		exit(1);
2736 	}
2737 	if (mc_addr && !*mc_addr) {
2738 		fprintf(stderr, "no multicast IP address specified for "
2739 				"\"-g\" option\n");
2740 		fflush(stderr);
2741 		exit(1);
2742 	}
2743 
2744 #ifdef AF_INET6
2745 	if (!inet_pton(AF_INET6, HI_MC6, &hi_mc6)) {
2746 		err("inet_pton");
2747 	}
2748 	if (!inet_pton(AF_INET6, HI_MC6_ASM, &hi_mc6_asm)) {
2749 		err("inet_pton");
2750 	}
2751 #endif
2752 
2753 	if (udp && !haverateopt)
2754 		rate = DEFAULT_UDP_RATE;
2755 
2756 	bzero((char *)&frominet, sizeof(frominet));
2757 	bzero((char *)&clientaddr, sizeof(clientaddr));
2758 
2759 #ifdef AF_INET6
2760 	bzero((char *)&clientaddr6, sizeof(clientaddr6));
2761 	clientscope6 = 0;
2762 #endif
2763 
2764 	if (!nbuf) {
2765 		if (timeout == 0.0) {
2766 			if (sinkmode) {
2767 				timeout = DEFAULT_TIMEOUT;
2768 				itimer.it_value.tv_sec = timeout;
2769 				itimer.it_value.tv_usec =
2770 					(timeout - itimer.it_value.tv_sec)
2771 						*1000000;
2772 			}
2773 			nbuf = INT_MAX;
2774 		}
2775 	}
2776 
2777 	if (srvrwin == -1) {
2778 		srvrwin = sendwin;
2779 	}
2780 
2781 	if ((argc == 0) && !explicitaf) {
2782 		domain = PF_INET;
2783 		af = AF_INET;
2784 	}
2785 
2786 	if (multilink) {
2787 		if (nstream == 1) {
2788 			fprintf(stderr, "Warning: multilink mode not meaningful for a single stream\n");
2789 			fflush(stderr);
2790 		}
2791 	}
2792 
2793 	if (argc >= 1) {
2794 		host = argv[0];
2795 		if ((cp1 = strchr(host, '+'))) {
2796 			*cp1++ = '\0';
2797 			if (*cp1)
2798 				stride = cp1;
2799 		}
2800 		if (multilink) {
2801 			if (stride) {
2802 				fprintf(stderr, "don't use both multilink and address stride\n");
2803 				fflush(stderr);
2804 				exit(1);
2805 			}
2806 			if ((cp1 = strchr(host, '/')) && strchr(cp1 + 1, '/')) {
2807 				fprintf(stderr, "multilink mode not compatible with multiple hosts %s\n", host);
2808 				fflush(stderr);
2809 				exit(1);
2810 			}
2811 		}
2812 		hostaddr = NULL;
2813 		implicit_hostaddr = 0;
2814 		if ((cp1 = strchr(host, '='))) {
2815 			*cp1++ = '\0';
2816 			if (strchr(cp1, '/')) {
2817 				fprintf(stderr, "host=addr format not supported for multiple control/data paths\n");
2818 				fflush(stderr);
2819 				exit(1);
2820 			}
2821 			if (*cp1) {
2822 				if (*cp1 == '=') {
2823 					implicit_hostaddr = 1;
2824 					cp1++;
2825 				}
2826 				hostaddr = cp1;
2827 				if (!implicit_hostaddr)
2828 					host = hostaddr;
2829 			}
2830 		}
2831 		stream_idx = 0;
2832 		res[0] = NULL;
2833 		cp1 = host;
2834 		if (host[strlen(host) - 1] == '/') {
2835 			fprintf(stderr, "bad hostname or address: trailing '/' not allowed: %s\n", host);
2836 			fflush(stderr);
2837 			exit(1);
2838 		}
2839 		if (strchr(host, '/') && !trans && !reverse) {
2840 			fprintf(stderr, "multiple control/data paths not supported for receive\n");
2841 			fflush(stderr);
2842 			exit(1);
2843 		}
2844 		if (strchr(host, '/') && trans && reverse) {
2845 			fprintf(stderr, "multiple control/data paths not supported for flipped transmit\n");
2846 			fflush(stderr);
2847 			exit(1);
2848 		}
2849 		if (host[0] == '/') {
2850 			host++;
2851 			cp1++;
2852 			stream_idx = 1;
2853 		}
2854 		else if ((cp2 = strchr(host, '/'))) {
2855 			host = cp2 + 1;
2856 		}
2857 
2858 		while (stream_idx <= nstream) {
2859 			bzero(&hints, sizeof(hints));
2860 			res[stream_idx] = NULL;
2861 			if (explicitaf) hints.ai_family = af;
2862 			if (udp)
2863 				hints.ai_socktype = SOCK_DGRAM;
2864 			else
2865 				hints.ai_socktype = SOCK_STREAM;
2866 			if ((cp2 = strchr(cp1, '/'))) {
2867 				if (stream_idx == nstream) {
2868 					fprintf(stderr, "bad hostname or address: too many data paths for nstream=%d: %s\n", nstream, argv[0]);
2869 					fflush(stderr);
2870 					exit(1);
2871 				}
2872 				*cp2 = '\0';
2873 			}
2874 			if (!(multilink && (stream_idx > 1)) &&
2875 			    (error_num = getaddrinfo(cp1, NULL, &hints,
2876 						     &res[stream_idx]))) {
2877 				if (implicit_hostaddr && hostaddr) {
2878 					if (res[stream_idx]) {
2879 						freeaddrinfo(res[stream_idx]);
2880 						res[stream_idx] = NULL;
2881 					}
2882 					error_num =
2883 						getaddrinfo(hostaddr, NULL,
2884 							    &hints,
2885 							    &res[stream_idx]);
2886 				}
2887 				if (error_num) {
2888 					if (cp2)
2889 						*cp2++ = '/';
2890 					if (hostaddr) {
2891 						if (implicit_hostaddr)
2892 							*(hostaddr - 2) = '=';
2893 						else
2894 							*(hostaddr - 1) = '=';
2895 					}
2896 					fprintf(stderr, "bad hostname or address: %s: %s\n", gai_strerror(error_num), argv[0]);
2897 					fflush(stderr);
2898 					exit(1);
2899 				}
2900 				if (implicit_hostaddr && hostaddr &&
2901 				    (stream_idx == 1)) {
2902 					if (stride)
2903 						*(stride - 1) = '+';
2904 					cp3 = hostaddr;
2905 					while (*cp3) {
2906 						*(cp3 - 1) = *cp3;
2907 						cp3++;
2908 					}
2909 					*(cp3 - 1) = '\0';
2910 					hostaddr--;
2911 					implicit_hostaddr = 0;
2912 					if (stride) {
2913 						stride--;
2914 						*(stride - 1) = '\0';
2915 					}
2916 				}
2917 			}
2918 			else if (multilink && (stream_idx > 1)) {
2919 				if (res[stream_idx - 1]->ai_next)
2920 					res[stream_idx] =
2921 						res[stream_idx - 1]->ai_next;
2922 				else
2923 					res[stream_idx] = res[1];
2924 			}
2925 			else if (!(multilink && (stream_idx > 1)) &&
2926 				 implicit_hostaddr && hostaddr) {
2927 				if (stride) {
2928 					strcat(host, "+");
2929 					strncat(host, stride, ADDRSTRLEN);
2930 					*(hostaddr - 2) = '\0';
2931 					stride = hostaddr - 1;
2932 				}
2933 				hostaddr = NULL;
2934 			}
2935 			af = res[stream_idx]->ai_family;
2936 /*
2937  * At the moment PF_ matches AF_ but are maintained seperate and the socket
2938  * call is supposed to be PF_
2939  *
2940  * For now we set domain from the address family we looked up, but if these
2941  * ever get changed to not match some code will have to go here to find the
2942  * domain appropriate for the family
2943  */
2944 			domain = af;
2945 			stream_idx++;
2946 			if (cp2) {
2947 				*cp2++ = '/';
2948 				cp1 = cp2;
2949 			}
2950 			else
2951 				cp1 = host;
2952 		}
2953 		if (!res[0]) {
2954 			if ((cp1 = strchr(host, '/')))
2955 				*cp1 = '\0';
2956 			if ((error_num = getaddrinfo(host, NULL, &hints, &res[0]))) {
2957 				if (cp1)
2958 					*cp1++ = '/';
2959 				fprintf(stderr, "bad hostname or address: %s: %s\n", gai_strerror(error_num), argv[0]);
2960 				fflush(stderr);
2961 				exit(1);
2962 			}
2963 			af = res[0]->ai_family;
2964 			/* see previous comment about domain */
2965 			domain = af;
2966 			if (cp1)
2967 				*cp1 = '/';
2968 		}
2969 		if (hostaddr) {
2970 			host = argv[0];
2971 			if (implicit_hostaddr)
2972 				*(hostaddr - 2) = '=';
2973 			else
2974 				*(hostaddr - 1) = '=';
2975 		}
2976 	}
2977 
2978 	ipad_stride.ip32 = 0;
2979 	if (stride) {
2980 		if (strlen(stride) >= ADDRSTRLEN) {
2981 			fprintf(stderr, "address stride '%s' too long\n", stride);
2982 			fflush(stderr);
2983 			exit(1);
2984 		}
2985 		if (nstream == 1) {
2986 			fprintf(stderr, "Warning: stride %s not meaningful for a single stream\n", stride);
2987 			fflush(stderr);
2988 		}
2989 		if (udp) {
2990 			fprintf(stderr, "stride %s not valid for UDP\n",
2991 				stride);
2992 			fflush(stderr);
2993 			exit(1);
2994 		}
2995 		if ((cp1 = strchr(argv[0], '/')) && strchr(cp1 + 1, '/')) {
2996 			fprintf(stderr, "stride %s not compatible with multiple hosts %s\n", stride, argv[0]);
2997 			fflush(stderr);
2998 			exit(1);
2999 		}
3000 		if (af == AF_INET) {
3001 			if (strchr(stride, '.')) {
3002 				error_num = inet_pton(AF_INET, stride,
3003 						ipad_stride.buf);
3004 				if (error_num == 0) {
3005 					fprintf(stderr,
3006 						"stride %s not in correct presentation format\n",
3007 						stride);
3008 					fflush(stderr);
3009 					exit(1);
3010 				}
3011 				else if (error_num < 0)
3012 					err("inet_pton: stride");
3013 			}
3014 			else {
3015 				ipad_stride.ip32 = atoi(stride);
3016 				ipad_stride.ip32 = htonl(ipad_stride.ip32);
3017 			}
3018 		}
3019 		else {
3020 			fprintf(stderr, "stride %s not valid for IPv6\n",
3021 				stride);
3022 			fflush(stderr);
3023 			exit(1);
3024 		}
3025 		*(stride - 1) = '+';
3026 	}
3027 
3028 	if (host3 && !strchr(host3, '=') && !strchr(host3, '/')) {
3029 		cp1 = strchr(host3, '+');
3030 		if (cp1) {
3031 			if (strlen(cp1 + 1) >= ADDRSTRLEN) {
3032 				fprintf(stderr, "3rd party address stride '%s' too long\n", cp1 + 1);
3033 				fflush(stderr);
3034 				exit(1);
3035 			}
3036 			*cp1 = '\0';
3037 		}
3038 		if (inet_pton(af, host3, &dummy) != 1) {
3039 			bzero(&hints, sizeof(hints));
3040 			hints.ai_family = af;
3041 			if (udp)
3042 				hints.ai_socktype = SOCK_DGRAM;
3043 			else
3044 				hints.ai_socktype = SOCK_STREAM;
3045 			host3res = NULL;
3046 			error_num = getaddrinfo(host3, NULL, &hints, &host3res);
3047 			if (error_num == 0) {
3048 				nameinfo_flags = NI_NUMERICHOST;
3049 				error_num = getnameinfo(host3res->ai_addr,
3050 							host3res->ai_addrlen,
3051 							host3addr, ADDRSTRLEN,
3052 							NULL, 0,
3053 							nameinfo_flags);
3054 			}
3055 			if (host3res) {
3056 				freeaddrinfo(host3res);
3057 				host3res = NULL;
3058 			}
3059 			if (error_num == 0) {
3060 				strncpy(host3buf, host3, HOSTNAMELEN);
3061 				strcat(host3buf, "==");
3062 				strncat(host3buf, host3addr, ADDRSTRLEN);
3063 				if (cp1) {
3064 					strcat(host3buf, "+");
3065 					strncat(host3buf, cp1 + 1, ADDRSTRLEN);
3066 				}
3067 				host3 = host3buf;
3068 			}
3069 		}
3070 		if (cp1)
3071 			*cp1 = '+';
3072 	}
3073 
3074 	if (!port) {
3075 		if (af == AF_INET) {
3076 			if ((sp = getservbyname( "nuttcp-data", "tcp" )))
3077 				port = ntohs(sp->s_port);
3078 			else
3079 				port = DEFAULT_PORT;
3080 		}
3081 #ifdef AF_INET6
3082 		else if (af == AF_INET6) {
3083 			if ((sp = getservbyname( "nuttcp6-data", "tcp" )))
3084 				port = ntohs(sp->s_port);
3085 			else {
3086 				if ((sp = getservbyname( "nuttcp-data", "tcp" )))
3087 					port = ntohs(sp->s_port);
3088 				else
3089 					port = DEFAULT_PORT;
3090 			}
3091 		}
3092 #endif
3093 		else {
3094 			err("unsupported AF");
3095 		}
3096 	}
3097 
3098 	if (!ctlport) {
3099 		if (af == AF_INET) {
3100 			if ((sp = getservbyname( "nuttcp", "tcp" )))
3101 				ctlport = ntohs(sp->s_port);
3102 			else
3103 				ctlport = DEFAULT_CTLPORT;
3104 		}
3105 #ifdef AF_INET6
3106 		else if (af == AF_INET6) {
3107 			if ((sp = getservbyname( "nuttcp6", "tcp" )))
3108 				ctlport = ntohs(sp->s_port);
3109 			else {
3110 				if ((sp = getservbyname( "nuttcp", "tcp" )))
3111 					ctlport = ntohs(sp->s_port);
3112 				else
3113 					ctlport = DEFAULT_CTLPORT;
3114 			}
3115 		}
3116 #endif
3117 		else {
3118 			err("unsupported AF");
3119 		}
3120 	}
3121 
3122 	if ((port < 1024) || ((port + nstream - 1) > 65535)) {
3123 		fprintf(stderr, "invalid port/nstream = %d/%d\n", port, nstream);
3124 		fflush(stderr);
3125 		exit(1);
3126 	}
3127 
3128 	if ((ctlport >= port) && (ctlport <= (port + nstream - 1))) {
3129 		fprintf(stderr, "ctlport = %d overlaps port/nstream = %d/%d\n", ctlport, port, nstream);
3130 		fflush(stderr);
3131 		exit(1);
3132 	}
3133 
3134 	if (timeout && (interval >= timeout)) {
3135 		fprintf(stderr, "ignoring interval=%f which is greater than or equal timeout=%f\n", interval, timeout);
3136 		fflush(stderr);
3137 		interval = 0;
3138 	}
3139 
3140 	if (iratesss) {
3141 		if (udp) {
3142 			fprintf(stderr, "ignoring smoothed slow start option for udp transfer\n");
3143 			fflush(stderr);
3144 			iratesss = 0;
3145 		}
3146 		if (maxburst > 1) {
3147 			fprintf(stderr, "ignoring maxburst option with smoothed slow start option\n");
3148 			fflush(stderr);
3149 			maxburst = 1;
3150 		}
3151 		if (nstream > 1) {
3152 			fprintf(stderr, "ignoring smoothed slow start option for multiple streams\n");
3153 			fflush(stderr);
3154 			iratesss = 0;
3155 		}
3156 		if (format & NORETRANS) {
3157 			fprintf(stderr, "can't do smoothed slow start if no retransmission info\n");
3158 			fflush(stderr);
3159 			iratesss = 0;
3160 		}
3161 		if (!(format & NORETRANS) && (format & NOCWND)) {
3162 			fprintf(stderr, "can't do smoothed slow start if no congestion window info\n");
3163 			fflush(stderr);
3164 			iratesss = 0;
3165 		}
3166 	}
3167 
3168 	if (clientserver) {
3169 		if (trans) {
3170 			fprintf(stderr, "server mode only allowed for receiver\n");
3171 			goto usage;
3172 		}
3173 		udp = 0;
3174 		start_idx = 0;
3175 		ident[0] = '\0';
3176 		if (af == AF_INET) {
3177 		  union peer46 {
3178 			struct sockaddr_in peer4;
3179 #ifdef AF_INET6
3180 			struct sockaddr_in6 peer6;
3181 #endif
3182 		  } peer;
3183 		  socklen_t peerlen = sizeof(peer);
3184 		  if (getpeername(0, (struct sockaddr *)&peer, &peerlen) == 0) {
3185 #ifndef AF_INET6
3186 			if (peer.peer4.sin_family == AF_INET)
3187 #else
3188 			if ((peer.peer4.sin_family == AF_INET) ||
3189 			    (peer.peer6.sin6_family == AF_INET6))
3190 #endif
3191 			{
3192 #ifdef AF_INET6
3193 				if (!explicitaf &&
3194 				    (peer.peer6.sin6_family == AF_INET6)) {
3195 					af = AF_INET6;
3196 					domain = af;
3197 					clientaddr6 = peer.peer6.sin6_addr;
3198 					clientscope6 = peer.peer6.sin6_scope_id;
3199 					client_ipaddr.ss.ss_family = AF_INET6;
3200 					client_ipaddr.sin6.sin6_addr =
3201 						clientaddr6;
3202 				}
3203 				else {
3204 					clientaddr = peer.peer4.sin_addr;
3205 					client_ipaddr.ss.ss_family = AF_INET;
3206 					client_ipaddr.sin.sin_addr = clientaddr;
3207 				}
3208 #else
3209 				clientaddr = peer.peer4.sin_addr;
3210 				client_ipaddr.ss.ss_family = AF_INET;
3211 				client_ipaddr.sin.sin_addr = clientaddr;
3212 #endif
3213 				inetd = 1;
3214 				oneshot = 1;
3215 				start_idx = 1;
3216 			}
3217 		  }
3218 		}
3219 #ifdef AF_INET6
3220 		else if (af == AF_INET6) {
3221 		  struct sockaddr_in6 peer;
3222 		  socklen_t peerlen = sizeof(peer);
3223 		  if (getpeername(0, (struct sockaddr *)&peer, &peerlen) == 0) {
3224 			if ((peer.sin6_family == AF_INET) ||
3225 			    (peer.sin6_family == AF_INET6)) {
3226 				clientaddr6 = peer.sin6_addr;
3227 				clientscope6 = peer.sin6_scope_id;
3228 				client_ipaddr.ss.ss_family = AF_INET6;
3229 				client_ipaddr.sin6.sin6_addr = clientaddr6;
3230 				inetd = 1;
3231 				oneshot = 1;
3232 				start_idx = 1;
3233 			}
3234 		  }
3235 		}
3236 #endif
3237 		else {
3238 			err("unsupported AF");
3239 		}
3240 	}
3241 
3242 	if (clientserver && !inetd && !oneshot && !sinkmode) {
3243 		fprintf(stderr, "option \"-s\" invalid with \"-S\" server mode\n");
3244 		fprintf(stderr, "option \"-s\" can be used with \"-1\" oneshot server mode\n");
3245 		fflush(stderr);
3246 		exit(1);
3247 	}
3248 
3249 #ifdef HAVE_SETPRIO
3250 	if (priority) {
3251 		if (setpriority(PRIO_PROCESS, 0, priority) != 0)
3252 			err("couldn't change priority");
3253 	}
3254 #endif
3255 
3256 #ifdef HAVE_SETAFFINITY
3257 	if ((affinity >= 0) && !host3) {
3258 		if ((ncores = sysconf(_SC_NPROCESSORS_CONF)) <= 0)
3259 			err("sysconf: couldn't get _SC_NPROCESSORS_CONF");
3260 		CPU_ZERO(&cpu_set);
3261 		CPU_SET(affinity, &cpu_set);
3262 		if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set) != 0)
3263 			err("couldn't change CPU affinity");
3264 	}
3265 #endif
3266 
3267 	if (argc >= 1) {
3268 		start_idx = 0;
3269 		client = 1;
3270 		clientserver = 1;
3271 	}
3272 
3273 	if (clientserver && !client && srcctlport) {
3274 		fprintf(stderr, "can't specify source control port in server mode\n");
3275 		fflush(stderr);
3276 		exit(1);
3277 	}
3278 
3279 	if (!host3 && clientserver && client && (ssm < 0)) {
3280 		if (af == AF_INET) {
3281 			ssm = 0;
3282 		}
3283 #ifdef AF_INET6
3284 		else if (af == AF_INET6) {
3285 #ifdef MCAST_JOIN_SOURCE_GROUP
3286 			ssm = 1;
3287 #else
3288 			ssm = 0;
3289 #endif
3290 		}
3291 #endif
3292 	}
3293 
3294 	mc_af = af;
3295 	if (!host3 && clientserver && client && mc_addr) {
3296 		bzero(&hints, sizeof(hints));
3297 		if (explicitaf)
3298 			hints.ai_family = af;
3299 		if (udp)
3300 			hints.ai_socktype = SOCK_DGRAM;
3301 		else
3302 			hints.ai_socktype = SOCK_STREAM;
3303 		mcres = NULL;
3304 		error_num = getaddrinfo(mc_addr, NULL, &hints, &mcres);
3305 		if (error_num) {
3306 			fprintf(stderr, "getaddrinfo: "
3307 					"bad multicast IP address: %s: %s\n",
3308 				mc_addr, gai_strerror(error_num));
3309 			fflush(stderr);
3310 			exit(1);
3311 		}
3312 		nameinfo_flags = NI_NUMERICHOST;
3313 		error_num = getnameinfo(mcres->ai_addr, mcres->ai_addrlen,
3314 					mcgaddr, ADDRSTRLEN, NULL, 0,
3315 					nameinfo_flags);
3316 		if (error_num) {
3317 			fprintf(stderr, "getnameinfo: "
3318 					"bad multicast IP address: %s: %s\n",
3319 				mc_addr, gai_strerror(error_num));
3320 			fflush(stderr);
3321 			exit(1);
3322 		}
3323 		mc_addr = mcgaddr;
3324 		if (mcres->ai_family == AF_INET) {
3325 			struct sockaddr_in *group;
3326 			struct in_addr ipv4_mcaddr;
3327 
3328 			group = (struct sockaddr_in *)mcres->ai_addr;
3329 			bcopy((char *)&(group->sin_addr), (char *)&ipv4_mcaddr,
3330 			      sizeof(struct in_addr));
3331 			if (ssm) {
3332 				if (((htonl(ipv4_mcaddr.s_addr) & 0xFF000000) !=
3333 				     (HI_MC_SSM << 24))) {
3334 					fprintf(stderr, "bad SSM multicast "
3335 							"IP address: %s: "
3336 							"use 232.x.y.z\n",
3337 						mcgaddr);
3338 					fflush(stderr);
3339 					exit(1);
3340 				}
3341 			}
3342 			else {
3343 				if (((htonl(ipv4_mcaddr.s_addr) & 0xFF000000) !=
3344 				     (HI_MC << 24))) {
3345 					fprintf(stderr, "bad ASM multicast "
3346 							"IP address: %s: "
3347 							"use 231.x.y.z\n",
3348 						mcgaddr);
3349 					fflush(stderr);
3350 					exit(1);
3351 				}
3352 			}
3353 		}
3354 #ifdef AF_INET6
3355 		if (mcres->ai_family == AF_INET6) {
3356 			struct sockaddr_in6 *group;
3357 
3358 			group = (struct sockaddr_in6 *)mcres->ai_addr;
3359 			if (ssm) {
3360 				if ((bcmp((char *)&(group->sin6_addr),
3361 					  (char *)&hi_mc6,
3362 					  HI_MC6_LEN - 1) != 0) ||
3363 				    (group->sin6_addr.s6_addr[HI_MC6_LEN - 1]
3364 						< 0x80)) {
3365 					fprintf(stderr,
3366 						"bad SSM multicast IP address: "
3367 						"%s: use ff3e::[8-f]xxx:yyyy\n",
3368 						mcgaddr);
3369 					fflush(stderr);
3370 					exit(1);
3371 				}
3372 			}
3373 			else {
3374 				if ((bcmp((char *)&(group->sin6_addr),
3375 					  (char *)&hi_mc6_asm,
3376 					  HI_MC6_ASM_LEN) != 0)) {
3377 					fprintf(stderr,
3378 						"bad ASM multicast IP address: "
3379 						"%s: use ff2e::wwww:xxxx:"
3380 							      "yyyy:zzzz\n",
3381 						mcgaddr);
3382 					fflush(stderr);
3383 					exit(1);
3384 				}
3385 			}
3386 		}
3387 #endif
3388 		mc_af = mcres->ai_family;
3389 	}
3390 
3391 	if (irate < 0) {
3392 		if (do_jitter)
3393 			irate = 1;
3394 		else
3395 			irate = 0;
3396 	}
3397 	if (do_jitter && (rate == MAXRATE)) {
3398 		fprintf(stderr, "jitter option not supported for "
3399 				"unlimited rate\n");
3400 		fflush(stderr);
3401 		exit(1);
3402 	}
3403 	if (do_jitter && !irate) {
3404 		fprintf(stderr, "jitter option requires"
3405 				" \"-Ri\" instantaneous rate limit option\n");
3406 		fflush(stderr);
3407 		exit(1);
3408 	}
3409 	if (interval && !clientserver) {
3410 		fprintf(stderr, "interval option only supported for client/server mode\n");
3411 		fflush(stderr);
3412 		exit(1);
3413 	}
3414 	if (reverse && !clientserver) {
3415 		fprintf(stderr, "flip option only supported for client/server mode\n");
3416 		fflush(stderr);
3417 		exit(1);
3418 	}
3419 	if (reverse && udp) {
3420 		fprintf(stderr, "flip option not supported for UDP\n");
3421 		fflush(stderr);
3422 		exit(1);
3423 	}
3424 	if (client && !sinkmode && udp) {
3425 		fprintf(stderr, "Warning: UDP transfers unreliable for non-sinkmode - use at own risk\n");
3426 		fflush(stderr);
3427 	}
3428 	if (traceroute) {
3429 		nstream = 1;
3430 		if (!clientserver) {
3431 			fprintf(stderr, "traceroute option only supported for client/server mode\n");
3432 			fflush(stderr);
3433 			exit(1);
3434 		}
3435 	}
3436 	if (host3) {
3437 		if (!clientserver) {
3438 			fprintf(stderr, "3rd party nuttcp only supported for client/server mode\n");
3439 			fflush(stderr);
3440 			exit(1);
3441 		}
3442 	}
3443 
3444 	if (udp && (buflen < 5)) {
3445 	    fprintf(stderr, "UDP buflen = %d < 5, set to 5\n", buflen);
3446 	    buflen = 5;		/* send more than the sentinel size */
3447 	}
3448 
3449 	if (udp && (buflen > MAXUDPBUFLEN)) {
3450 	    fprintf(stderr, "UDP buflen = %d > MAXUDPBUFLEN, set to %d\n",
3451 		buflen, MAXUDPBUFLEN);
3452 	    buflen = MAXUDPBUFLEN;
3453 	}
3454 
3455 	if (nbuf_bytes && !host3 && !traceroute) {
3456 		nbuf /= buflen;
3457 	}
3458 
3459 	if ((rate != MAXRATE) && rate_pps && !host3 && !traceroute) {
3460 		uint64_t llrate = rate;
3461 
3462 		llrate *= ((double)buflen * 8 / 1000);
3463 		rate = llrate;
3464 	}
3465 
3466 	if (udp && interval) {
3467 		if (buflen >= 32)
3468 			udplossinfo = 1;
3469 		else
3470 			fprintf(stderr, "Unable to print interval loss information if UDP buflen < 32\n");
3471 	}
3472 
3473 	if (udp && (do_jitter & JITTER_IGNORE_OOO)) {
3474 		if (buflen >= 32)
3475 			udplossinfo = 1;
3476 		else
3477 			fprintf(stderr, "Unable to check out of order when calculating jitter if UDP buflen < 32\n");
3478 	}
3479 
3480 	if (!udp && trans) {
3481 		if (buflen >= 32) {
3482 			retransinfo = 1;
3483 #if defined(linux)
3484 			cwndinfo = 1;
3485 #endif
3486 			b_flag = 1;
3487 		}
3488 		else
3489 			fprintf(stderr, "Unable to print retransmission information if TCP buflen < 32\n");
3490 	}
3491 
3492 	if (udp && do_owd && (buflen < 16)) {
3493 		fprintf(stderr, "Unable to calculate one-way delay if UDP buflen < 16\n");
3494 	}
3495 
3496 	ivers = vers_major*10000 + vers_minor*100 + vers_delta;
3497 
3498 	mallocsize = buflen;
3499 	if (mallocsize < MINMALLOC) mallocsize = MINMALLOC;
3500 #if defined(linux)
3501 	if (directio) {
3502 		error_num = posix_memalign((void **)&buf, sysconf(_SC_PAGESIZE),
3503 					   mallocsize);
3504 		if (error_num) {
3505 			errno = error_num;
3506 			err("posix_memalign");
3507 		}
3508 	}
3509 	else
3510 #endif
3511 	if ((buf = (char *)malloc(mallocsize)) == (char *)NULL)
3512 		err("malloc");
3513 
3514 	pattern( buf, buflen );
3515 
3516 #ifdef SIGPIPE
3517 	signal(SIGPIPE, sigpipe);
3518 #endif
3519 
3520 	signal(SIGINT, sigint);
3521 
3522 	if (clientserver && client && !thirdparty &&
3523 	    beta && !(format & NOBETAMSG) && (do_jitter || do_owd)) {
3524 		fprintf(stderr, "nuttcp-%d.%d.%d: ",
3525 				vers_major, vers_minor, vers_delta);
3526 		fprintf(stderr, "Using beta vers: %s interface/output "
3527 				"subject to change\n", BETA_FEATURES);
3528 		fprintf(stderr, "              (to suppress this message "
3529 				"use \"-f-beta\")\n\n");
3530 		fflush(stderr);
3531 	}
3532 
3533 doit:
3534 	if (!udp && trans && (format & DEBUGRETRANS)) {
3535 		sretrans = get_retrans(-1, &tcpinf);
3536 		fprintf(stdout, "initial system retrans = %d\n", sretrans);
3537 	}
3538 	nretrans[0] = 0;
3539 	cwnd[0] = 0;
3540 
3541 	for ( stream_idx = 1; stream_idx <= nstream; stream_idx++ ) {
3542 		fd[stream_idx] = -1;
3543 		nretrans[stream_idx] = 0;
3544 		cwnd[stream_idx] = 0;
3545 	}
3546 
3547 	for ( stream_idx = start_idx; stream_idx <= nstream; stream_idx++ ) {
3548 		if (clientserver && (stream_idx == 1)) {
3549 			retransinfo = 0;
3550 			cwndinfo = 0;
3551 			if (nstream == 1) {
3552 				send_retrans = 1;
3553 				read_retrans = 1;
3554 				send_cwnd = 1;
3555 				read_cwnd = 1;
3556 			}
3557 			do_retrans = 0;
3558 			do_cwnd = 0;
3559 			got_0retrans = 0;
3560 			if (client) {
3561 				if (udp && !host3 && !traceroute) {
3562 					ctlconnmss = 0;
3563 					optlen = sizeof(ctlconnmss);
3564 					if (getsockopt(fd[0], IPPROTO_TCP, TCP_MAXSEG,  (void *)&ctlconnmss, &optlen) < 0)
3565 						err("get ctlconn maximum segment size didn't work");
3566 					if (!ctlconnmss) {
3567 						ctlconnmss = NON_JUMBO_ETHER_MSS;
3568 						if (format & DEBUGMTU) {
3569 							fprintf(stderr, "nuttcp%s%s: Warning: Control connection MSS reported as 0, using %d\n", trans?"-t":"-r", ident, ctlconnmss);
3570 							fflush(stderr);
3571 						}
3572 					}
3573 					else if (format & DEBUGMTU)
3574 						fprintf(stderr, "ctlconnmss = %d\n", ctlconnmss);
3575 					if (buflenopt) {
3576 						if (buflen >
3577 						    ctlconnmss +
3578 						      TCP_UDP_HDRLEN_DELTA +
3579 						      TCP_TIMESTAMPS_OPTLEN) {
3580 							if (format & PARSE)
3581 								fprintf(stderr, "nuttcp%s%s: Warning=\"IP_frags_or_no_data_reception_since_buflen=%d_>_ctlconnmss=%d\"\n", trans?"-t":"-r", ident, buflen, ctlconnmss);
3582 							else
3583 								fprintf(stderr, "nuttcp%s%s: Warning: IP frags or no data reception since buflen=%d > ctlconnmss=%d\n", trans?"-t":"-r", ident, buflen, ctlconnmss);
3584 							fflush(stderr);
3585 						}
3586 					}
3587 					else {
3588 						while (buflen > ctlconnmss) {
3589 							buflen >>= 1;
3590 							if (nbuf_bytes)
3591 								nbuf <<= 1;
3592 							if ((rate != MAXRATE) &&
3593 							    rate_pps)
3594 								rate >>= 1;
3595 						}
3596 					}
3597 					if (format & DEBUGMTU)
3598 						fprintf(stderr, "buflen = %d\n", buflen);
3599 				}
3600 				if (!(ctlconn = fdopen(fd[0], "w")))
3601 					err("fdopen: ctlconn for writing");
3602 				if (!sinkmode) {
3603 					if (trans)
3604 						savestdin=dup(0);
3605 					else {
3606 						savestdout=dup(1);
3607 						close(1);
3608 						dup(2);
3609 					}
3610 				}
3611 				close(0);
3612 				dup(fd[0]);
3613 				if (srvr_helo) {
3614 					fprintf(ctlconn,
3615 						HELO_FMT, vers_major,
3616 						vers_minor, vers_delta);
3617 					fflush(ctlconn);
3618 					if (!fgets(buf, mallocsize, stdin)) {
3619 						if ((errno == ECONNRESET) &&
3620 						    (num_connect_tries <
3621 							  MAX_CONNECT_TRIES) &&
3622 						    retry_server) {
3623 							/* retry control
3624 							 * connection to server
3625 							 * for certain possibly
3626 							 * transient errors */
3627 							fclose(ctlconn);
3628 							goto doit;
3629 						}
3630 						mes("error from server");
3631 						fprintf(stderr, "server aborted connection\n");
3632 						fflush(stderr);
3633 						exit(1);
3634 					}
3635 					if (sscanf(buf, HELO_FMT,
3636 						   &rvers_major,
3637 						   &rvers_minor,
3638 						   &rvers_delta) < 3) {
3639 						rvers_major = 0;
3640 						rvers_minor = 0;
3641 						rvers_delta = 0;
3642 						srvr_helo = 0;
3643 						while (fgets(buf, mallocsize,
3644 							     stdin)) {
3645 							if (strncmp(buf, "KO", 2) == 0)
3646 								break;
3647 						}
3648 						fclose(ctlconn);
3649 						goto doit;
3650 					}
3651 					irvers = rvers_major*10000
3652 							+ rvers_minor*100
3653 							+ rvers_delta;
3654 				}
3655 				if (host3 && nbuf_bytes && (irvers < 50501))
3656 					nbuf /= buflen;
3657 				if (host3 && (rate != MAXRATE) && rate_pps &&
3658 					     (irvers < 50501)) {
3659 					uint64_t llrate = rate;
3660 
3661 					llrate *= ((double)buflen * 8 / 1000);
3662 					rate = llrate;
3663 				}
3664 				if (host3 && !buflenopt && (irvers >= 50302))
3665 					buflen = 0;
3666 				fprintf(ctlconn, "buflen = %d, nbuf = %llu, win = %d, nstream = %d, rate = %lu, port = %hu, trans = %d, braindead = %d", buflen, nbuf, srvrwin, nstream, rate, port, trans, braindead);
3667 				if (irvers >= 30200)
3668 					fprintf(ctlconn, ", timeout = %f", timeout);
3669 				else {
3670 					timeout_sec = timeout;
3671 					if (itimer.it_value.tv_usec)
3672 						timeout_sec++;
3673 					fprintf(ctlconn, ", timeout = %ld", timeout_sec);
3674 					if (!trans && itimer.it_value.tv_usec &&
3675 					    (brief <= 0)) {
3676 						fprintf(stdout, "nuttcp-r%s: transmit timeout value rounded up to %ld second%s for old server\n",
3677 							ident, timeout_sec,
3678 							(timeout_sec == 1)?"":"s");
3679 					}
3680 				}
3681 				fprintf(ctlconn, ", udp = %d, vers = %d.%d.%d", udp, vers_major, vers_minor, vers_delta);
3682 				if (irvers >= 30302)
3683 					fprintf(ctlconn, ", interval = %f", interval);
3684 				else {
3685 					if (interval) {
3686 						fprintf(stdout, "nuttcp%s%s: interval option not supported by server version %d.%d.%d, need >= 3.3.2\n",
3687 							trans?"-t":"-r",
3688 							ident, rvers_major,
3689 							rvers_minor,
3690 							rvers_delta);
3691 						fflush(stdout);
3692 						interval = 0.0;
3693 						abortconn = 1;
3694 					}
3695 				}
3696 				if (irvers >= 30401)
3697 					fprintf(ctlconn, ", reverse = %d", reverse);
3698 				else {
3699 					if (reverse) {
3700 						fprintf(stdout, "nuttcp%s%s: flip option not supported by server version %d.%d.%d, need >= 3.4.1\n",
3701 							trans?"-t":"-r",
3702 							ident, rvers_major,
3703 							rvers_minor,
3704 							rvers_delta);
3705 						fflush(stdout);
3706 						reverse = 0;
3707 						abortconn = 1;
3708 					}
3709 				}
3710 				if (irvers >= 30501)
3711 					fprintf(ctlconn, ", format = %d", format);
3712 				else {
3713 					if (format) {
3714 						fprintf(stdout, "nuttcp%s%s: format option not supported by server version %d.%d.%d, need >= 3.5.1\n",
3715 							trans?"-t":"-r",
3716 							ident, rvers_major,
3717 							rvers_minor,
3718 							rvers_delta);
3719 						fflush(stdout);
3720 						format = 0;
3721 					}
3722 				}
3723 				if (irvers >= 30601) {
3724 					fprintf(ctlconn, ", traceroute = %d", traceroute);
3725 					if (traceroute)
3726 						skip_data = 1;
3727 					fprintf(ctlconn, ", irate = %d", irate);
3728 				}
3729 				else {
3730 					if (traceroute) {
3731 						fprintf(stdout, "nuttcp%s%s: traceroute option not supported by server version %d.%d.%d, need >= 3.6.1\n",
3732 							trans?"-t":"-r",
3733 							ident, rvers_major,
3734 							rvers_minor,
3735 							rvers_delta);
3736 						fflush(stdout);
3737 						traceroute = 0;
3738 						abortconn = 1;
3739 					}
3740 					if (irate && !trans) {
3741 						fprintf(stdout, "nuttcp%s%s: instantaneous rate option not supported by server version %d.%d.%d, need >= 3.6.1\n",
3742 							trans?"-t":"-r",
3743 							ident, rvers_major,
3744 							rvers_minor,
3745 							rvers_delta);
3746 						fflush(stdout);
3747 						irate = 0;
3748 					}
3749 				}
3750 				if (srvrwin && udp && (irvers < 30602)) {
3751 					fprintf(stdout, "nuttcp%s%s: server version %d.%d.%d ignores UDP window parameter, need >= 3.6.2\n",
3752 						trans?"-t":"-r",
3753 						ident, rvers_major,
3754 						rvers_minor,
3755 						rvers_delta);
3756 					fflush(stdout);
3757 				}
3758 				if ((irvers < 40101) && (format & PARSE)) {
3759 					fprintf(stdout, "nuttcp%s%s: \"-fparse\" option not supported by server version %d.%d.%d, need >= 4.1.1\n",
3760 						trans?"-t":"-r",
3761 						ident, rvers_major,
3762 						rvers_minor,
3763 						rvers_delta);
3764 					fflush(stdout);
3765 					format &= ~PARSE;
3766 					abortconn = 1;
3767 				}
3768 				if (irvers >= 50001) {
3769 					cp1 = NULL;
3770 					if (host3 && (irvers < 70101) &&
3771 					    (cp1 = strchr(host3, '=')))
3772 						*cp1 = '\0';
3773 					fprintf(ctlconn, ", thirdparty = %.*s", HOST3BUFLEN, host3 ? host3 : "_NULL_");
3774 					if (host3) {
3775 						skip_data = 1;
3776 						fprintf(ctlconn, " , brief3 = %d", brief);
3777 					}
3778 					if (cp1)
3779 						*cp1 = '=';
3780 				}
3781 				else {
3782 					if (host3) {
3783 						fprintf(stdout, "nuttcp%s%s: 3rd party nuttcp not supported by server version %d.%d.%d, need >= 5.0.1\n",
3784 							trans?"-t":"-r",
3785 							ident, rvers_major,
3786 							rvers_minor,
3787 							rvers_delta);
3788 						fflush(stdout);
3789 						host3 = NULL;
3790 						abortconn = 1;
3791 					}
3792 				}
3793 				if (host3 && !abortconn) {
3794 					if (irvers >= 60205) {
3795 						fprintf(ctlconn,
3796 							" , ctlport3 = %hu",
3797 							ctlport3);
3798 					}
3799 					else {
3800 						if (ctlport3) {
3801 							fprintf(stdout, "nuttcp%s%s: ctlport3 option not supported by server version %d.%d.%d, need >= 6.2.5\n",
3802 								trans?"-t":"-r",
3803 								ident,
3804 								rvers_major,
3805 								rvers_minor,
3806 								rvers_delta);
3807 							fflush(stdout);
3808 							ctlport3 = 0;
3809 							abortconn = 1;
3810 						}
3811 					}
3812 				}
3813 				if (irvers >= 50101) {
3814 					fprintf(ctlconn, " , multicast = %d", multicast);
3815 				}
3816 				else {
3817 					if (multicast) {
3818 						fprintf(stdout, "nuttcp%s%s: multicast not supported by server version %d.%d.%d, need >= 5.1.1\n",
3819 							trans?"-t":"-r",
3820 							ident, rvers_major,
3821 							rvers_minor,
3822 							rvers_delta);
3823 						fflush(stdout);
3824 						multicast = 0;
3825 						abortconn = 1;
3826 					}
3827 				}
3828 				if (irvers >= 60201) {
3829 					fprintf(ctlconn, " , ssm = %d", ssm);
3830 				}
3831 				else {
3832 					if (multicast && (ssm == 1)) {
3833 						fprintf(stdout, "nuttcp%s%s: ssm not supported by server version %d.%d.%d, need >= 6.2.1\n",
3834 							trans?"-t":"-r",
3835 							ident, rvers_major,
3836 							rvers_minor,
3837 							rvers_delta);
3838 						fflush(stdout);
3839 						ssm = 0;
3840 						abortconn = 1;
3841 					}
3842 				}
3843 				if (irvers >= 50201) {
3844 					fprintf(ctlconn, " , datamss = %d", datamss);
3845 				}
3846 				else {
3847 					if (datamss && !trans) {
3848 						fprintf(stdout, "nuttcp%s%s: mss option not supported by server version %d.%d.%d, need >= 5.2.1\n",
3849 							trans?"-t":"-r",
3850 							ident, rvers_major,
3851 							rvers_minor,
3852 							rvers_delta);
3853 						fflush(stdout);
3854 						datamss = 0;
3855 						abortconn = 1;
3856 					}
3857 				}
3858 				if (irvers >= 50301) {
3859 					fprintf(ctlconn, " , tos = %X", tos);
3860 				}
3861 				else {
3862 					if (tos && !trans) {
3863 						fprintf(stdout, "nuttcp%s%s: tos option not supported by server version %d.%d.%d, need >= 5.3.1\n",
3864 							trans?"-t":"-r",
3865 							ident, rvers_major,
3866 							rvers_minor,
3867 							rvers_delta);
3868 						fflush(stdout);
3869 						tos = 0;
3870 						abortconn = 1;
3871 					}
3872 				}
3873 				if (irvers >= 50501) {
3874 					fprintf(ctlconn, " , nbuf_bytes = %d", nbuf_bytes);
3875 					fprintf(ctlconn, " , rate_pps = %d", rate_pps);
3876 					fprintf(ctlconn, " , nodelay = %d", nodelay);
3877 				}
3878 				else {
3879 					if (host3 && udp && nbuf_bytes) {
3880 						fprintf(stdout, "nuttcp%s%s: Warning: \"-n\" option in bytes for third party not supported\n",
3881 							trans?"-t":"-r", ident);
3882 						fprintf(stdout, "          Warning: by server version %d.%d.%d, need >= 5.5.1\n",
3883 							rvers_major,
3884 							rvers_minor,
3885 							rvers_delta);
3886 						fprintf(stdout, "          Warning: third party request may not transfer\n");
3887 						fprintf(stdout, "          Warning: desired number of bytes in some UDP cases\n");
3888 						fflush(stdout);
3889 						nbuf_bytes = 0;
3890 					}
3891 					if (host3 && udp && rate_pps) {
3892 						fprintf(stdout, "nuttcp%s%s: Warning: \"-R\" option in pps for third party not supported\n",
3893 							trans?"-t":"-r", ident);
3894 						fprintf(stdout, "          Warning: by server version %d.%d.%d, need >= 5.5.1\n",
3895 							rvers_major,
3896 							rvers_minor,
3897 							rvers_delta);
3898 						fprintf(stdout, "          Warning: third party request may not produce\n");
3899 						fprintf(stdout, "          Warning: desired pps rate in some UDP cases\n");
3900 						fflush(stdout);
3901 						rate_pps = 0;
3902 					}
3903 					if (nodelay && !trans) {
3904 						fprintf(stdout, "nuttcp%s%s: TCP_NODELAY opt not supported by server version %d.%d.%d, need >= 5.5.1\n",
3905 							trans?"-t":"-r",
3906 							ident, rvers_major,
3907 							rvers_minor,
3908 							rvers_delta);
3909 						fflush(stdout);
3910 						nodelay = 0;
3911 						abortconn = 1;
3912 					}
3913 				}
3914 				if (irvers >= 60206) {
3915 					if (host3) {
3916 						fprintf(ctlconn,
3917 							" , affinity = %d",
3918 							affinity);
3919 						fprintf(ctlconn,
3920 							" , srvr_affinity = %d",
3921 							srvr_affinity);
3922 					}
3923 					else {
3924 						fprintf(ctlconn,
3925 							" , affinity = %d",
3926 							srvr_affinity);
3927 					}
3928 				}
3929 				else {
3930 					if (srvr_affinity >= 0) {
3931 						fprintf(stdout, "nuttcp%s%s: affinity option not supported by server version %d.%d.%d, need >= 6.2.6\n",
3932 							trans?"-t":"-r",
3933 							ident, rvers_major,
3934 							rvers_minor,
3935 							rvers_delta);
3936 						fflush(stdout);
3937 						srvr_affinity = -1;
3938 						abortconn = 1;
3939 					}
3940 				}
3941 				if (irvers >= 60207) {
3942 					fprintf(ctlconn, " , maxburst = %d",
3943 						maxburst);
3944 				}
3945 				else {
3946 					if ((maxburst > 1) &&
3947 					    (!trans || host3)) {
3948 						fprintf(stdout, "nuttcp%s%s: packet burst not supported by server version %d.%d.%d, need >= 6.2.7\n",
3949 							trans?"-t":"-r",
3950 							ident, rvers_major,
3951 							rvers_minor,
3952 							rvers_delta);
3953 						fflush(stdout);
3954 						maxburst = 1;
3955 						abortconn = 1;
3956 					}
3957 				}
3958 				if (irvers >= 70001) {
3959 					fprintf(ctlconn, " , do_jitter = %d", do_jitter);
3960 				}
3961 				else {
3962 					if (do_jitter && trans) {
3963 						fprintf(stdout, "nuttcp%s%s: jitter not supported by server version %d.%d.%d, need >= 7.0.1\n",
3964 							trans?"-t":"-r",
3965 							ident, rvers_major,
3966 							rvers_minor,
3967 							rvers_delta);
3968 						fflush(stdout);
3969 						do_jitter = 0;
3970 						abortconn = 1;
3971 					}
3972 					if ((do_jitter & JITTER_IGNORE_OOO) &&
3973 					    !trans && !(udp && interval)) {
3974 						udplossinfo = 0;
3975 						fprintf(stdout, "nuttcp%s%s: Unable to check out of order when calculating jitter\n",
3976 							trans?"-t":"-r", ident);
3977 						fprintf(stdout, "          due to using older server version %d.%d.%d, need >= 7.0.1\n",
3978 							rvers_major,
3979 							rvers_minor,
3980 							rvers_delta);
3981 						fflush(stdout);
3982 					}
3983 				}
3984 				if (irvers >= 70001) {
3985 					fprintf(ctlconn, " , do_owd = %d", do_owd);
3986 				}
3987 				else {
3988 					if (do_owd) {
3989 						fprintf(stdout, "nuttcp%s%s: owd not supported by server version %d.%d.%d, need >= 7.0.1\n",
3990 							trans?"-t":"-r",
3991 							ident, rvers_major,
3992 							rvers_minor,
3993 							rvers_delta);
3994 						fflush(stdout);
3995 						do_owd = 0;
3996 						abortconn = 1;
3997 					}
3998 				}
3999 				if (irvers >= 70101) {
4000 					fprintf(ctlconn, " , stride = %d", ipad_stride.ip32);
4001 				}
4002 				else {
4003 					if (ipad_stride.ip32) {
4004 						fprintf(stdout, "nuttcp%s%s: stride not supported by server version %d.%d.%d, need >= 7.1.1\n",
4005 							trans?"-t":"-r",
4006 							ident, rvers_major,
4007 							rvers_minor,
4008 							rvers_delta);
4009 						fflush(stdout);
4010 						ipad_stride.ip32 = 0;
4011 						abortconn = 1;
4012 					}
4013 				}
4014 				if (irvers >= 70101) {
4015 					fprintf(ctlconn, " , multilink = %d", multilink);
4016 				}
4017 				else {
4018 					if (multilink) {
4019 						fprintf(stdout, "nuttcp%s%s: multilink not supported by server version %d.%d.%d, need >= 7.1.1\n",
4020 							trans?"-t":"-r",
4021 							ident, rvers_major,
4022 							rvers_minor,
4023 							rvers_delta);
4024 						fflush(stdout);
4025 						multilink = 0;
4026 						abortconn = 1;
4027 					}
4028 				}
4029 				if (irvers >= 70201) {
4030 					fprintf(ctlconn, ", group = %.*s", ADDRSTRLEN, mc_addr ? mc_addr : "_NULL_");
4031 				}
4032 				else {
4033 					if (mc_addr) {
4034 						fprintf(stdout, "nuttcp%s%s: multicast group option not supported by server version %d.%d.%d, need >= 7.2.1\n",
4035 							trans?"-t":"-r",
4036 							ident, rvers_major,
4037 							rvers_minor,
4038 							rvers_delta);
4039 						fflush(stdout);
4040 						mc_addr = NULL;
4041 						abortconn = 1;
4042 					}
4043 				}
4044 				if (irvers >= 70301) {
4045 					fprintf(ctlconn, " , srcport = %hu", srcport);
4046 				}
4047 				else {
4048 					if (srcport &&
4049 					   ((!trans && !reverse) ||
4050 					   (trans && reverse) ||
4051 					   host3)) {
4052 						fprintf(stdout, "nuttcp%s%s: source port option not supported by server version %d.%d.%d, need >= 7.3.1\n",
4053 							trans?"-t":"-r",
4054 							ident, rvers_major,
4055 							rvers_minor,
4056 							rvers_delta);
4057 						fflush(stdout);
4058 						srcport = 0;
4059 						abortconn = 1;
4060 					}
4061 				}
4062 				if (irvers >= 80101) {
4063 					fprintf(ctlconn, ", iratesss = %d", iratesss);
4064 				}
4065 				else {
4066 					if (iratesss && !trans) {
4067 						fprintf(stdout, "nuttcp%s%s: smoothed slow start option not supported by server version %d.%d.%d, need >= 8.1.1\n",
4068 							trans?"-t":"-r",
4069 							ident, rvers_major,
4070 							rvers_minor,
4071 							rvers_delta);
4072 						fflush(stdout);
4073 						iratesss = 0;
4074 					}
4075 				}
4076 				if ((irvers >= 80201) && host3) {
4077 					if (explicitaf) {
4078 						if (af == AF_INET)
4079 							fprintf(ctlconn,
4080 								", af3 = 4");
4081 						if (af == AF_INET6)
4082 							fprintf(ctlconn,
4083 								", af3 = 6");
4084 					}
4085 					else {
4086 						fprintf(ctlconn, ", af3 = 0");
4087 					}
4088 				}
4089 				else {
4090 					if (host3 && explicitaf) {
4091 						fprintf(stdout, "nuttcp%s%s: third party \"-4/-6\" not supported by server version %d.%d.%d, need >= 8.2.1\n",
4092 							trans?"-t":"-r",
4093 							ident, rvers_major,
4094 							rvers_minor,
4095 							rvers_delta);
4096 						fflush(stdout);
4097 					}
4098 				}
4099 				fprintf(ctlconn, "\n");
4100 				fflush(ctlconn);
4101 				if (abortconn) {
4102 					brief = 1;
4103 					if ((!trans && !reverse) ||
4104 					    (trans && reverse))
4105 						skip_data = 1;
4106 				}
4107 				if (!fgets(buf, mallocsize, stdin)) {
4108 					mes("error from server");
4109 					fprintf(stderr, "server aborted connection\n");
4110 					fflush(stderr);
4111 					exit(1);
4112 				}
4113 				if (irvers < 30403)
4114 					udplossinfo = 0;
4115 				if (irvers >= 50401) {
4116 					two_bod = 1;
4117 					handle_urg = 1;
4118 				}
4119 				if (udp || (buflen < 32) || (irvers < 60001)) {
4120 					if (trans)
4121 						send_retrans = 0;
4122 					else
4123 						read_retrans = 0;
4124 				}
4125 				if (udp || (buflen < 32) || (irvers < 80001)) {
4126 					if (trans)
4127 						send_cwnd = 0;
4128 					else
4129 						read_cwnd = 0;
4130 				}
4131 				if (strncmp(buf, "OK", 2) != 0) {
4132 					mes("error from server");
4133 					fprintf(stderr, "server ");
4134 					while (fgets(buf, mallocsize, stdin)) {
4135 						if (strncmp(buf, "KO", 2) == 0)
4136 							break;
4137 						fputs(buf, stderr);
4138 					}
4139 					fflush(stderr);
4140 					exit(1);
4141 				}
4142 				if (sscanf(buf, "OK v%d.%d.%d\n", &rvers_major, &rvers_minor, &rvers_delta) < 3) {
4143 					rvers_major = 0;
4144 					rvers_minor = 0;
4145 					rvers_delta = 0;
4146 				}
4147 				irvers = rvers_major*10000
4148 						+ rvers_minor*100
4149 						+ rvers_delta;
4150 				usleep(10000);
4151 			}
4152 			else {
4153 				if (inetd) {
4154 					ctlconn = stdin;
4155 				}
4156 				else {
4157 					if (!(ctlconn = fdopen(fd[0], "r")))
4158 						err("fdopen: ctlconn for reading");
4159 				}
4160 				fflush(stdout);
4161 				if (!inetd) {
4162 					/* manually started server */
4163 					/* send stdout to client   */
4164 					savestdout=dup(1);
4165 					close(1);
4166 					dup(fd[0]);
4167 					if (!nofork) {
4168 					    /* send stderr to client */
4169 					    close(2);
4170 					    dup(1);
4171 					}
4172 				}
4173 				if (!fgets(buf, mallocsize, ctlconn)) {
4174 					fputs("KO\n", stdout);
4175 					mes("no nuttcp HELO message");
4176 					fputs("KO\n", stdout);
4177 					goto cleanup;
4178 				}
4179 				if (sscanf(buf, HELO_FMT, &rvers_major,
4180 					   &rvers_minor, &rvers_delta) == 3) {
4181 					fprintf(stdout, HELO_FMT, vers_major,
4182 						vers_minor, vers_delta);
4183 					fflush(stdout);
4184 					if (!fgets(buf, mallocsize, ctlconn)) {
4185 						fputs("KO\n", stdout);
4186 						mes("no nuttcp parameters");
4187 						fputs("KO\n", stdout);
4188 						goto cleanup;
4189 					}
4190 				}
4191 				irvers = rvers_major*10000
4192 						+ rvers_minor*100
4193 						+ rvers_delta;
4194 				if (sscanf(buf, "buflen = %d, nbuf = %llu, win = %d, nstream = %d, rate = %lu, port = %hu, trans = %d, braindead = %d, timeout = %lf, udp = %d, vers = %d.%d.%d", &nbuflen, &nbuf, &sendwin, &nstream, &rate, &port, &trans, &braindead, &timeout, &udp, &rvers_major, &rvers_minor, &rvers_delta) < 13) {
4195 					trans = !trans;
4196 					fputs("KO\n", stdout);
4197 					mes("error scanning parameters");
4198 					fprintf(stdout, "may be using older client version than server\n");
4199 					fputs(buf, stdout);
4200 					fputs("KO\n", stdout);
4201 					goto cleanup;
4202 				}
4203 				irvers = rvers_major*10000
4204 						+ rvers_minor*100
4205 						+ rvers_delta;
4206 				if (irvers >= 30302)
4207 					sscanf(strstr(buf, ", interval =") + 13,
4208 						"%lf", &interval);
4209 				else
4210 					interval = 0.0;
4211 				if (irvers >= 30401)
4212 					sscanf(strstr(buf, ", reverse =") + 12,
4213 						"%d", &reverse);
4214 				else
4215 					reverse = 0;
4216 				if (irvers >= 30501)
4217 					sscanf(strstr(buf, ", format =") + 11,
4218 						"%d", &format);
4219 				else
4220 					format = 0;
4221 				if (irvers >= 30601) {
4222 					sscanf(strstr(buf, ", traceroute =") + 15,
4223 						"%d", &traceroute);
4224 					if (traceroute) {
4225 						skip_data = 1;
4226 						brief = 1;
4227 					}
4228 					sscanf(strstr(buf, ", irate =") + 10,
4229 						"%d", &irate);
4230 				}
4231 				else {
4232 					traceroute = 0;
4233 					irate = 0;
4234 				}
4235 				if (irvers >= 50001) {
4236 					sprintf(fmt, "%%%ds", HOST3BUFLEN);
4237 					sscanf(strstr(buf, ", thirdparty =") + 15,
4238 						fmt, host3buf);
4239 					host3buf[HOST3BUFLEN] = '\0';
4240 					if (strcmp(host3buf, "_NULL_") == 0)
4241 						host3 = NULL;
4242 					else
4243 						host3 = host3buf;
4244 					if (host3) {
4245 						if (no3rd) {
4246 							fputs("KO\n", stdout);
4247 							fprintf(stdout, "doesn't allow 3rd party nuttcp\n");
4248 							fputs("KO\n", stdout);
4249 							goto cleanup;
4250 						}
4251 						cp1 = host3;
4252 						while (*cp1) {
4253 							if (!isalnum((int)(*cp1))
4254 							     && (*cp1 != '-')
4255 							     && (*cp1 != '.')
4256 							     && (*cp1 != ':')
4257 							     && (*cp1 != '/')
4258 							     && (*cp1 != '+')
4259 							     && (*cp1 != '=')) {
4260 								fputs("KO\n", stdout);
4261 								mes("invalid 3rd party host");
4262 								fprintf(stdout, "3rd party host = '%s'\n", host3);
4263 								fputs("KO\n", stdout);
4264 								goto cleanup;
4265 							}
4266 							cp1++;
4267 						}
4268 						skip_data = 1;
4269 						brief = 1;
4270 						sscanf(strstr(buf, ", brief3 =") + 11,
4271 							"%d", &brief3);
4272 					}
4273 				}
4274 				else {
4275 					host3 = NULL;
4276 				}
4277 				if (host3 && (irvers >= 60205)) {
4278 					sscanf(strstr(buf, ", ctlport3 =") + 13,
4279 						"%hu", &ctlport3);
4280 				}
4281 				else {
4282 					ctlport3 = 0;
4283 				}
4284 				if (irvers >= 50101) {
4285 					sscanf(strstr(buf, ", multicast =") + 14,
4286 						"%d", &mc_param);
4287 				}
4288 				else {
4289 					mc_param = 0;
4290 				}
4291 				if (irvers >= 60201) {
4292 					sscanf(strstr(buf, ", ssm =") + 8,
4293 						"%d", &ssm);
4294 				}
4295 				else {
4296 					ssm = 0;
4297 				}
4298 #ifndef MCAST_JOIN_SOURCE_GROUP
4299 				if (mc_param && (ssm == 1)) {
4300 					fputs("KO\n", stdout);
4301 					fprintf(stdout, "server does not support ssm\n");
4302 					fputs("KO\n", stdout);
4303 					goto cleanup;
4304 				}
4305 #endif
4306 				if (irvers >= 50201) {
4307 					sscanf(strstr(buf, ", datamss =") + 12,
4308 						"%d", &datamss);
4309 				}
4310 				else {
4311 					datamss = 0;
4312 				}
4313 				if (irvers >= 50301) {
4314 					sscanf(strstr(buf, ", tos =") + 8,
4315 						"%X", &tos);
4316 				}
4317 				else {
4318 					tos = 0;
4319 				}
4320 				if (irvers >= 50501) {
4321 					sscanf(strstr(buf, ", nbuf_bytes =")
4322 							+ 15,
4323 						"%d", &nbuf_bytes);
4324 					sscanf(strstr(buf, ", rate_pps =") + 13,
4325 						"%d", &rate_pps);
4326 					sscanf(strstr(buf, ", nodelay =") + 12,
4327 						"%d", &nodelay);
4328 				}
4329 				else {
4330 					nbuf_bytes = 0;
4331 					rate_pps = 0;
4332 					nodelay = 0;
4333 				}
4334 				if (irvers >= 60206) {
4335 					if (host3) {
4336 						sscanf(strstr(buf,
4337 							   ", affinity =") + 13,
4338 						       "%d", &affinity);
4339 						sscanf(strstr(buf,
4340 							   ", srvr_affinity =")
4341 								+ 18,
4342 						       "%d", &srvr_affinity);
4343 					}
4344 					else {
4345 						sscanf(strstr(buf,
4346 							   ", affinity =") + 13,
4347 						       "%d", &srvr_affinity);
4348 					}
4349 				}
4350 				else {
4351 					srvr_affinity = -1;
4352 				}
4353 				if (irvers >= 60207) {
4354 					sscanf(strstr(buf, ", maxburst =") + 13,
4355 					       "%d", &maxburst);
4356 				}
4357 				else {
4358 					maxburst = 1;
4359 				}
4360 				if (irvers >= 70001) {
4361 					sscanf(strstr(buf, ", do_jitter =") + 14,
4362 					       "%d", &do_jitter);
4363 				}
4364 				else {
4365 					do_jitter = 0;
4366 				}
4367 				if (irvers >= 70001) {
4368 					sscanf(strstr(buf, ", do_owd =") + 11,
4369 					       "%d", &do_owd);
4370 				}
4371 				else {
4372 					do_owd = 0;
4373 				}
4374 				if (irvers >= 70101) {
4375 					sscanf(strstr(buf, ", stride =") + 11,
4376 					       "%d", &ipad_stride.ip32);
4377 				}
4378 				else {
4379 					ipad_stride.ip32 = 0;
4380 				}
4381 				if (irvers >= 70101) {
4382 					sscanf(strstr(buf,
4383 						      ", multilink =") + 14,
4384 						      "%d", &multilink);
4385 				}
4386 				else {
4387 					multilink = 0;
4388 				}
4389 				if (irvers >= 70201) {
4390 					sprintf(fmt, "%%%ds", ADDRSTRLEN);
4391 					sscanf(strstr(buf, ", group =") + 10,
4392 					       fmt, mcgaddr);
4393 					mcgaddr[ADDRSTRLEN - 1] = '\0';
4394 					if (strcmp(mcgaddr, "_NULL_") == 0)
4395 						mc_addr = NULL;
4396 					else
4397 						mc_addr = mcgaddr;
4398 					if (mc_addr) {
4399 						cp1 = mc_addr;
4400 						while (*cp1) {
4401 							if (!isxdigit((int)(*cp1))
4402 							     && (*cp1 != '.')
4403 							     && (*cp1 != ':')) {
4404 								fputs("KO\n", stdout);
4405 								mes("invalid multicast group");
4406 								fprintf(stdout, "multicast group = '%s'\n", mc_addr);
4407 								fputs("KO\n", stdout);
4408 								goto cleanup;
4409 							}
4410 							cp1++;
4411 						}
4412 					}
4413 				}
4414 				else {
4415 					mc_addr = NULL;
4416 				}
4417 				if (irvers >= 70301) {
4418 					sscanf(strstr(buf,
4419 						      ", srcport =") + 12,
4420 						      "%hu", &srcport);
4421 				}
4422 				else {
4423 					srcport = 0;
4424 				}
4425 				if (irvers >= 80101) {
4426 					sscanf(strstr(buf, ", iratesss =") + 13,
4427 						"%d", &iratesss);
4428 				}
4429 				else {
4430 					iratesss = 0;
4431 				}
4432 				if ((irvers >= 80201) && host3) {
4433 					sscanf(strstr(buf, ", af3 =") + 8,
4434 						"%d", &af3);
4435 				}
4436 				else {
4437 					af3 = 0;
4438 				}
4439 #if !defined(linux)
4440 				iratesss = 0;
4441 #endif
4442 				trans = !trans;
4443 				if (inetd && !sinkmode) {
4444 					fputs("KO\n", stdout);
4445 					mes("option \"-s\" invalid with inetd server");
4446 					fputs("KO\n", stdout);
4447 					goto cleanup;
4448 				}
4449 				if (!traceroute && !host3 &&
4450 				    (nbuflen != buflen)) {
4451 					if (nbuflen < 1) {
4452 						fputs("KO\n", stdout);
4453 						mes("invalid buflen");
4454 						fprintf(stdout, "buflen = %d\n", nbuflen);
4455 						fputs("KO\n", stdout);
4456 						goto cleanup;
4457 					}
4458 					free(buf);
4459 					mallocsize = nbuflen;
4460 					if (mallocsize < MINMALLOC) mallocsize = MINMALLOC;
4461 #if defined(linux)
4462 					if (directio) {
4463 						error_num = posix_memalign(
4464 							(void **)&buf,
4465 							sysconf(_SC_PAGESIZE),
4466 							mallocsize);
4467 						if (error_num) {
4468 							errno = error_num;
4469 							err("posix_memalign");
4470 						}
4471 					}
4472 					else
4473 #endif
4474 					if ((buf = (char *)malloc(mallocsize)) == (char *)NULL)
4475 						err("malloc");
4476 					pattern( buf, nbuflen );
4477 				}
4478 				buflen = nbuflen;
4479 				if (nbuf < 1) {
4480 					fputs("KO\n", stdout);
4481 					mes("invalid nbuf");
4482 					fprintf(stdout, "nbuf = %llu\n", nbuf);
4483 					fputs("KO\n", stdout);
4484 					goto cleanup;
4485 				}
4486 				rcvwin = sendwin;
4487 				if (sendwin < 0) {
4488 					fputs("KO\n", stdout);
4489 					mes("invalid win");
4490 					fprintf(stdout, "win = %d\n", sendwin);
4491 					fputs("KO\n", stdout);
4492 					goto cleanup;
4493 				}
4494 				if ((nstream < 1) || (nstream > MAXSTREAM)) {
4495 					fputs("KO\n", stdout);
4496 					mes("invalid nstream");
4497 					fprintf(stdout, "nstream = %d\n", nstream);
4498 					fputs("KO\n", stdout);
4499 					goto cleanup;
4500 				}
4501 				if (nstream > 1) {
4502 					b_flag = 1;
4503 					send_retrans = 0;
4504 					read_retrans = 0;
4505 					send_cwnd = 0;
4506 					read_cwnd = 0;
4507 				}
4508 				if (rate == 0)
4509 					rate = MAXRATE;
4510 				if (timeout < 0) {
4511 					fputs("KO\n", stdout);
4512 					mes("invalid timeout");
4513 					fprintf(stdout, "timeout = %f\n", timeout);
4514 					fputs("KO\n", stdout);
4515 					goto cleanup;
4516 				}
4517 				itimer.it_value.tv_sec = timeout;
4518 				itimer.it_value.tv_usec =
4519 					(timeout - itimer.it_value.tv_sec)
4520 						*1000000;
4521 				if ((port < 1024) || ((port + nstream - 1) > 65535)) {
4522 					fputs("KO\n", stdout);
4523 					mes("invalid port/nstream");
4524 					fprintf(stdout, "port/nstream = %hu/%d\n", port, nstream);
4525 					fputs("KO\n", stdout);
4526 					goto cleanup;
4527 				}
4528 				if (srcport && (srcport < 1024)) {
4529 					fputs("KO\n", stdout);
4530 					mes("invalid srcport");
4531 					fprintf(stdout, "srcport = %hu\n", srcport);
4532 					fputs("KO\n", stdout);
4533 					goto cleanup;
4534 				}
4535 				if ((ctlport >= port) && (ctlport <= (port + nstream - 1))) {
4536 					fputs("KO\n", stdout);
4537 					mes("ctlport overlaps port/nstream");
4538 					fprintf(stdout, "ctlport = %hu, port/nstream = %hu/%d\n", ctlport, port, nstream);
4539 					fputs("KO\n", stdout);
4540 					goto cleanup;
4541 				}
4542 				if (iratesss) {
4543 					if (udp) {
4544 						fputs("KO\n", stdout);
4545 						mes("iratesss not allowed for udp");
4546 						fputs("KO\n", stdout);
4547 						goto cleanup;
4548 					}
4549 					if (maxburst > 1) {
4550 						fputs("KO\n", stdout);
4551 						mes("maxburst > 1 not allowed with iratesss");
4552 						fprintf(stdout, "maxburst = %d\n", maxburst);
4553 						fputs("KO\n", stdout);
4554 						goto cleanup;
4555 					}
4556 					if (nstream > 1) {
4557 						fputs("KO\n", stdout);
4558 						mes("nstream > 1 not allowed with iratesss");
4559 						fprintf(stdout, "nstream = %d\n", nstream);
4560 						fputs("KO\n", stdout);
4561 						goto cleanup;
4562 					}
4563 				}
4564 				if (host3 && ctlport3 && (ctlport3 < 1024)) {
4565 					fputs("KO\n", stdout);
4566 					mes("invalid ctlport3");
4567 					fprintf(stdout, "ctlport3 = %hu\n",
4568 						ctlport3);
4569 					fputs("KO\n", stdout);
4570 					goto cleanup;
4571 				}
4572 				if (interval < 0) {
4573 					fputs("KO\n", stdout);
4574 					mes("invalid interval");
4575 					fprintf(stdout, "interval = %f\n", interval);
4576 					fputs("KO\n", stdout);
4577 					goto cleanup;
4578 				}
4579 				if (mc_param) {
4580 					if ((mc_param < 1) ||
4581 					    (mc_param > 255)) {
4582 						fputs("KO\n", stdout);
4583 						mes("invalid multicast ttl");
4584 						fprintf(stdout, "multicast ttl = %d\n", mc_param);
4585 						fputs("KO\n", stdout);
4586 						goto cleanup;
4587 					}
4588 					udp = 1;
4589 					nstream = 1;
4590 					if (rate == MAXRATE)
4591 						rate = DEFAULT_UDP_RATE;
4592 				}
4593 				multicast = mc_param;
4594 				if ((!host3 && ((ssm < 0) || (ssm > 1))) ||
4595 				    (host3 && ((ssm < -1) || (ssm > 1)))) {
4596 					fputs("KO\n", stdout);
4597 					mes("invalid ssm value");
4598 					fprintf(stdout, "ssm = %d\n", ssm);
4599 					fputs("KO\n", stdout);
4600 					goto cleanup;
4601 				}
4602 				if (datamss < 0) {
4603 					fputs("KO\n", stdout);
4604 					mes("invalid datamss");
4605 					fprintf(stdout, "datamss = %d\n", datamss);
4606 					fputs("KO\n", stdout);
4607 					goto cleanup;
4608 				}
4609 				if (tos > 255) {
4610 					fputs("KO\n", stdout);
4611 					mes("invalid tos");
4612 					fprintf(stdout, "tos = %d\n", tos);
4613 					fputs("KO\n", stdout);
4614 					goto cleanup;
4615 				}
4616 				if (nbuf_bytes < 0) {
4617 					fputs("KO\n", stdout);
4618 					mes("invalid nbuf_bytes");
4619 					fprintf(stdout, "nbuf_bytes = %d\n",
4620 						nbuf_bytes);
4621 					fputs("KO\n", stdout);
4622 					goto cleanup;
4623 				}
4624 				if (rate_pps < 0) {
4625 					fputs("KO\n", stdout);
4626 					mes("invalid rate_pps");
4627 					fprintf(stdout, "rate_pps = %d\n",
4628 						rate_pps);
4629 					fputs("KO\n", stdout);
4630 					goto cleanup;
4631 				}
4632 				if (nodelay < 0) {
4633 					fputs("KO\n", stdout);
4634 					mes("invalid nodelay");
4635 					fprintf(stdout, "nodelay = %d\n",
4636 						nodelay);
4637 					fputs("KO\n", stdout);
4638 					goto cleanup;
4639 				}
4640 				if ((srvr_affinity >= 0) && !host3) {
4641 #ifdef HAVE_SETAFFINITY
4642 					CPU_ZERO(&cpu_set);
4643 					CPU_SET(srvr_affinity, &cpu_set);
4644 					if (sched_setaffinity(0,
4645 							      sizeof(cpu_set_t),
4646 							      &cpu_set) != 0) {
4647 						fputs("KO\n", stdout);
4648 						mes("couldn't change server "
4649 						    "CPU affinity");
4650 						fprintf(stdout,
4651 							"srvr_affinity = %d\n",
4652 							srvr_affinity);
4653 						fputs("KO\n", stdout);
4654 						goto cleanup;
4655 					}
4656 #else
4657 					fputs("KO\n", stdout);
4658 					mes("server doesn't support setting "
4659 					    "CPU affinity");
4660 					fprintf(stdout,
4661 						"srvr_affinity = %d\n",
4662 						srvr_affinity);
4663 					fputs("KO\n", stdout);
4664 					goto cleanup;
4665 #endif
4666 				}
4667 				if (maxburst < 1) {
4668 					fputs("KO\n", stdout);
4669 					mes("invalid maxburst");
4670 					fprintf(stdout, "maxburst = %d\n",
4671 						maxburst);
4672 					fputs("KO\n", stdout);
4673 					goto cleanup;
4674 				}
4675 				if (do_jitter < 0) {
4676 					fputs("KO\n", stdout);
4677 					mes("invalid do_jitter");
4678 					fprintf(stdout, "do_jitter = %d\n",
4679 						do_jitter);
4680 					fputs("KO\n", stdout);
4681 					goto cleanup;
4682 				}
4683 				if (do_jitter && !udp) {
4684 					fputs("KO\n", stdout);
4685 					fprintf(stdout,
4686 						"jitter option"
4687 						" not supported for TCP\n");
4688 					fputs("KO\n", stdout);
4689 					goto cleanup;
4690 				}
4691 				if (do_jitter && (!rate || (rate == MAXRATE))) {
4692 					fputs("KO\n", stdout);
4693 					fprintf(stdout,
4694 						"jitter option not supported"
4695 						" for unlimited rate\n");
4696 					fputs("KO\n", stdout);
4697 					goto cleanup;
4698 				}
4699 				if (do_jitter && !irate) {
4700 					fputs("KO\n", stdout);
4701 					fprintf(stdout,
4702 						"jitter option requires"
4703 						" instantaneous rate limit\n");
4704 					fputs("KO\n", stdout);
4705 					goto cleanup;
4706 				}
4707 				if (do_owd < 0) {
4708 					fputs("KO\n", stdout);
4709 					mes("invalid do_owd");
4710 					fprintf(stdout, "do_owd = %d\n",
4711 						do_owd);
4712 					fputs("KO\n", stdout);
4713 					goto cleanup;
4714 				}
4715 				if (mc_addr) {
4716 					error_num = inet_pton(AF_INET, mc_addr,
4717 							      &dummy);
4718 #ifdef AF_INET6
4719 					if (error_num != 1)
4720 						error_num = inet_pton(AF_INET6,
4721 								      mc_addr,
4722 								      &dummy);
4723 #endif
4724 					if (error_num != 1) {
4725 						fputs("KO\n", stdout);
4726 						mes("invalid multicast group");
4727 						fprintf(stdout, "multicast group = '%s'\n",
4728 							mc_addr);
4729 						fputs("KO\n", stdout);
4730 						goto cleanup;
4731 					}
4732 				}
4733 				/* used to send server "OK" here -
4734 				 * now delay sending of server OK until
4735 				 * after successful server bind() -
4736 				 * catches data port collision */
4737 				if (udp && (interval ||
4738 					    (do_jitter & JITTER_IGNORE_OOO)) &&
4739 				    (buflen >= 32) && (irvers >= 30403))
4740 					udplossinfo = 1;
4741 				if (irvers >= 50401) {
4742 					two_bod = 1;
4743 					handle_urg = 1;
4744 				}
4745 				if (udp || (buflen < 32) || (irvers < 60001)) {
4746 					if (trans)
4747 						send_retrans = 0;
4748 					else
4749 						read_retrans = 0;
4750 				}
4751 				if (udp || (buflen < 32) || (irvers < 80001)) {
4752 					if (trans)
4753 						send_cwnd = 0;
4754 					else
4755 						read_cwnd = 0;
4756 				}
4757 			}
4758 		}
4759 
4760 		if (clientserver && client && (stream_idx == 1)) {
4761 			reading_srvr_info = 1;
4762 			pollfds[0].fd = fileno(ctlconn);
4763 			pollfds[0].events = POLLIN | POLLPRI;
4764 			pollfds[0].revents = 0;
4765 			flags = fcntl(0, F_GETFL, 0);
4766 			if (flags < 0)
4767 				err("fcntl 1");
4768 			flags |= O_NONBLOCK;
4769 			if (fcntl(0, F_SETFL, flags) < 0)
4770 				err("fcntl 2");
4771 			itimer.it_value.tv_sec = SRVR_INFO_TIMEOUT;
4772 			itimer.it_value.tv_usec = 0;
4773 			itimer.it_interval.tv_sec = 0;
4774 			itimer.it_interval.tv_usec = 0;
4775 			setitimer(ITIMER_REAL, &itimer, 0);
4776 		}
4777 		if (clientserver && client && (stream_idx == 1) &&
4778 		    ((pollst = poll(pollfds, 1, 0)) > 0) &&
4779 		    (pollfds[0].revents & (POLLIN | POLLPRI)) && !got_done) {
4780 			/* check for server output (mainly for server error) */
4781 			while (fgets(intervalbuf, sizeof(intervalbuf), stdin)) {
4782 				setitimer(ITIMER_REAL, &itimer, 0);
4783 				if (strncmp(intervalbuf, "DONE", 4) == 0) {
4784 					if (format & DEBUGPOLL) {
4785 						fprintf(stdout, "got DONE\n");
4786 						fflush(stdout);
4787 					}
4788 					got_done = 1;
4789 					intr = 1;
4790 					break;
4791 				}
4792 				else if (strncmp(intervalbuf,
4793 						 "nuttcp-", 7) == 0) {
4794 					if ((brief <= 0) ||
4795 					    strstr(intervalbuf, "Warning") ||
4796 					    strstr(intervalbuf, "Error") ||
4797 					    strstr(intervalbuf, "Debug")) {
4798 						if (*ident) {
4799 							fputs("nuttcp", stdout);
4800 							fputs(trans ?
4801 								"-r" : "-t",
4802 							      stdout);
4803 							fputs(ident, stdout);
4804 							fputs(intervalbuf + 8,
4805 							      stdout);
4806 						}
4807 						else
4808 							fputs(intervalbuf,
4809 							      stdout);
4810 						fflush(stdout);
4811 					}
4812 					if (strstr(intervalbuf, "Error"))
4813 						exit(1);
4814 				}
4815 				else {
4816 					if (*ident)
4817 						fprintf(stdout, "%s: ",
4818 							ident + 1);
4819 					fputs(intervalbuf, stdout);
4820 					fflush(stdout);
4821 				}
4822 			}
4823 		}
4824 		if (clientserver && client && (stream_idx == 1)) {
4825 			reading_srvr_info = 0;
4826 			flags = fcntl(0, F_GETFL, 0);
4827 			if (flags < 0)
4828 				err("fcntl 1");
4829 			flags &= ~O_NONBLOCK;
4830 			if (fcntl(0, F_SETFL, flags) < 0)
4831 				err("fcntl 2");
4832 			itimer.it_value.tv_sec = 0;
4833 			itimer.it_value.tv_usec = 0;
4834 			setitimer(ITIMER_REAL, &itimer, 0);
4835 		}
4836 
4837 		if (!client) {
4838 		    if (af == AF_INET) {
4839 			inet_ntop(af, &clientaddr.s_addr, hostbuf, sizeof(hostbuf));
4840 		    }
4841 #ifdef AF_INET6
4842 		    else if (af == AF_INET6) {
4843 			inet_ntop(af, clientaddr6.s6_addr, hostbuf, sizeof(hostbuf));
4844 		    }
4845 #endif
4846 		    host = hostbuf;
4847 		}
4848 
4849 		if (multilink && !client &&
4850 		    ((trans && !reverse) || (!trans && reverse)) &&
4851 		    !udp && (stream_idx == 1)) {
4852 			nameinfo_flags = NI_NAMEREQD;
4853 			if (getnameinfo((struct sockaddr *)&client_ipaddr,
4854 						sizeof(struct in6_addr),
4855 						clientbuf, NI_MAXHOST,
4856 						NULL, 0,
4857 						nameinfo_flags) == 0) {
4858 				bzero(&hints, sizeof(hints));
4859 				res[0] = NULL;
4860 				res[1] = NULL;
4861 				hints.ai_family = af;
4862 				if (udp)
4863 					hints.ai_socktype = SOCK_DGRAM;
4864 				else
4865 					hints.ai_socktype = SOCK_STREAM;
4866 				if (getaddrinfo(clientbuf, NULL, &hints,
4867 						&res[1]) == 0) {
4868 					for ( i = 2; i <= nstream; i++ ) {
4869 						if (res[i - 1]->ai_next)
4870 							res[i] =
4871 							    res[i - 1]->ai_next;
4872 						else
4873 							res[i] = res[1];
4874 					}
4875 				}
4876 				else {
4877 					if (res[1]) {
4878 						freeaddrinfo(res[1]);
4879 						res[1] = NULL;
4880 					}
4881 					multilink = 0;
4882 				}
4883 			}
4884 			else
4885 				multilink = 0;
4886 		}
4887 
4888 		if ((stream_idx > 0) && skip_data) {
4889 			if (clientserver && !client && (stream_idx == 1)) {
4890 				/* send server "OK" message */
4891 				fprintf(stdout, "OK v%d.%d.%d\n", vers_major,
4892 						vers_minor, vers_delta);
4893 				fflush(stdout);
4894 			}
4895 			break;
4896 		}
4897 
4898 		bzero((char *)&sinme[stream_idx], sizeof(sinme[stream_idx]));
4899 		bzero((char *)&sinhim[stream_idx], sizeof(sinhim[stream_idx]));
4900 
4901 #ifdef AF_INET6
4902 		bzero((char *)&sinme6[stream_idx], sizeof(sinme6[stream_idx]));
4903 		bzero((char *)&sinhim6[stream_idx], sizeof(sinhim6[stream_idx]));
4904 #endif
4905 
4906 		if (((trans && !reverse) && (stream_idx > 0)) ||
4907 		    ((!trans && reverse) && (stream_idx > 0)) ||
4908 		    (client && (stream_idx == 0))) {
4909 			/* xmitr initiates connections (unless reversed) */
4910 			if (client) {
4911 				if (af == AF_INET) {
4912 				    sinhim[stream_idx].sin_family = af;
4913 				    if (ipad_stride.ip32 && (stream_idx > 1)) {
4914 					sinhim[stream_idx].sin_addr.s_addr =
4915 					  sinhim[stream_idx - 1].sin_addr.s_addr
4916 						+ ipad_stride.ip32;
4917 				    }
4918 				    else {
4919 					bcopy((char *)&(((struct sockaddr_in *)res[stream_idx]->ai_addr)->sin_addr),
4920 					      (char *)&sinhim[stream_idx].sin_addr.s_addr,
4921 					      sizeof(sinhim[stream_idx].sin_addr.s_addr));
4922 				    }
4923 				}
4924 #ifdef AF_INET6
4925 				else if (af == AF_INET6) {
4926 				    sinhim6[stream_idx].sin6_family = af;
4927 				    bcopy((char *)&(((struct sockaddr_in6 *)res[stream_idx]->ai_addr)->sin6_addr),
4928 					  (char *)&sinhim6[stream_idx].sin6_addr.s6_addr,
4929 					  sizeof(sinhim6[stream_idx].sin6_addr.s6_addr));
4930 				    sinhim6[stream_idx].sin6_scope_id = ((struct sockaddr_in6 *)res[stream_idx]->ai_addr)->sin6_scope_id;
4931 				}
4932 #endif
4933 				else {
4934 					err("unsupported AF");
4935 				}
4936 			}
4937 			else {
4938 				sinhim[stream_idx].sin_family = af;
4939 				if (ipad_stride.ip32 && (stream_idx > 1)) {
4940 					sinhim[stream_idx].sin_addr.s_addr =
4941 					  sinhim[stream_idx - 1].sin_addr.s_addr
4942 						+ ipad_stride.ip32;
4943 				}
4944 				else {
4945 					if (multilink && (stream_idx > 0))
4946 						sinhim[stream_idx].sin_addr =
4947 							((struct sockaddr_in *)res[stream_idx]->ai_addr)->sin_addr;
4948 					else
4949 						sinhim[stream_idx].sin_addr =
4950 							clientaddr;
4951 				}
4952 #ifdef AF_INET6
4953 				sinhim6[stream_idx].sin6_family = af;
4954 				if (multilink && (stream_idx > 0))
4955 					sinhim6[stream_idx].sin6_addr =
4956 						((struct sockaddr_in6 *)res[stream_idx]->ai_addr)->sin6_addr;
4957 				else
4958 					sinhim6[stream_idx].sin6_addr =
4959 						clientaddr6;
4960 				sinhim6[stream_idx].sin6_scope_id = clientscope6;
4961 #endif
4962 			}
4963 			if (stream_idx == 0) {
4964 				sinhim[stream_idx].sin_port = htons(ctlport);
4965 				sinme[stream_idx].sin_port = htons(srcctlport); /* default is free choice */
4966 #ifdef AF_INET6
4967 				sinhim6[stream_idx].sin6_port = htons(ctlport);
4968 				sinme6[stream_idx].sin6_port = htons(srcctlport); /* default is free choice */
4969 #endif
4970 			}
4971 			else {
4972 				sinhim[stream_idx].sin_port = htons(port + stream_idx - 1);
4973 				sinme[stream_idx].sin_port = htons(srcport); /* default is free choice */
4974 #ifdef AF_INET6
4975 				sinhim6[stream_idx].sin6_port = htons(port + stream_idx - 1);
4976 				sinme6[stream_idx].sin6_port = htons(srcport); /* default is free choice */
4977 #endif
4978 			}
4979 		}
4980 		else {
4981 			/* rcvr listens for connections (unless reversed) */
4982 			if (stream_idx == 0) {
4983 				sinme[stream_idx].sin_port =   htons(ctlport);
4984 				sinhim[stream_idx].sin_port = htons(srcctlport); /* default is free choice */
4985 #ifdef AF_INET6
4986 				sinme6[stream_idx].sin6_port = htons(ctlport);
4987 				sinhim6[stream_idx].sin6_port = htons(srcctlport); /* default is free choice */
4988 #endif
4989 			}
4990 			else {
4991 				sinme[stream_idx].sin_port =   htons(port + stream_idx - 1);
4992 				sinhim[stream_idx].sin_port = htons(srcport); /* default is free choice */
4993 #ifdef AF_INET6
4994 				sinme6[stream_idx].sin6_port = htons(port + stream_idx - 1);
4995 				sinhim6[stream_idx].sin6_port = htons(srcport); /* default is free choice */
4996 #endif
4997 			}
4998 		}
4999 		sinme[stream_idx].sin_family = af;
5000 #ifdef AF_INET6
5001 		sinme6[stream_idx].sin6_family = af;
5002 #endif
5003 
5004 		if ((fd[stream_idx] = socket(domain, (udp && (stream_idx != 0))?SOCK_DGRAM:SOCK_STREAM, 0)) < 0) {
5005 			if (clientserver && !client && (stream_idx == 1)) {
5006 				save_errno = errno;
5007 				fputs("KO\n", stdout);
5008 				mes("Error: socket() on data stream failed");
5009 				fputs("Error: ", stdout);
5010 				fputs(strerror(save_errno), stdout);
5011 				fputs("\n", stdout);
5012 				fputs("KO\n", stdout);
5013 				goto cleanup;
5014 			}
5015 			err("socket");
5016 		}
5017 
5018 		if (setsockopt(fd[stream_idx], SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(one)) < 0) {
5019 			if (clientserver && !client && (stream_idx == 1)) {
5020 				save_errno = errno;
5021 				fputs("KO\n", stdout);
5022 				mes("Error: setsockopt()"
5023 				    " to so_reuseaddr failed");
5024 				fputs("Error: ", stdout);
5025 				fputs(strerror(save_errno), stdout);
5026 				fputs("\n", stdout);
5027 				fputs("KO\n", stdout);
5028 				goto cleanup;
5029 			}
5030 			err("setsockopt: so_reuseaddr");
5031 		}
5032 
5033 #ifdef IPV6_V6ONLY
5034 		if ((af == AF_INET6) && explicitaf && !v4mapped) {
5035 			if (setsockopt(fd[stream_idx], IPPROTO_IPV6, IPV6_V6ONLY, (void *)&one, sizeof(int)) < 0) {
5036 				if (clientserver && !client &&
5037 				    (stream_idx == 1)) {
5038 					save_errno = errno;
5039 					fputs("KO\n", stdout);
5040 					mes("Error: setsockopt()"
5041 					    " to ipv6_only failed");
5042 					fputs("Error: ", stdout);
5043 					fputs(strerror(save_errno), stdout);
5044 					fputs("\n", stdout);
5045 					fputs("KO\n", stdout);
5046 					goto cleanup;
5047 				}
5048 				err("setsockopt: ipv6_only");
5049 			}
5050 		}
5051 #endif
5052 
5053 		if (af == AF_INET) {
5054 		    if (bind(fd[stream_idx], (struct sockaddr *)&sinme[stream_idx], sizeof(sinme[stream_idx])) < 0) {
5055 			if (clientserver && !client && (stream_idx == 1)) {
5056 				save_errno = errno;
5057 				fputs("KO\n", stdout);
5058 				mes("Error: bind() on data stream failed");
5059 				fputs("Error: ", stdout);
5060 				fputs(strerror(save_errno), stdout);
5061 				fputs("\n", stdout);
5062 				if (((!trans && !reverse)
5063 					|| (trans && reverse)) &&
5064 				    (errno == EADDRINUSE) &&
5065 				    (port == IPERF_PORT))
5066 					fputs("Info: Possible collision"
5067 					      " with iperf server\n", stdout);
5068 				fputs("KO\n", stdout);
5069 				goto cleanup;
5070 			}
5071 			if (clientserver && client && (stream_idx == 1) &&
5072 			    ((!trans && !reverse) || (trans && reverse)) &&
5073 			    (errno == EADDRINUSE) && (port == IPERF_PORT)) {
5074 				errmes("bind");
5075 				fputs("Info: Possible collision"
5076 				      " with iperf server\n", stderr);
5077 				fflush(stderr);
5078 				exit(1);
5079 			}
5080 			err("bind");
5081 		    }
5082 		}
5083 #ifdef AF_INET6
5084 		else if (af == AF_INET6) {
5085 		    if (bind(fd[stream_idx], (struct sockaddr *)&sinme6[stream_idx], sizeof(sinme6[stream_idx])) < 0) {
5086 			if (clientserver && !client && (stream_idx == 1)) {
5087 				save_errno = errno;
5088 				fputs("KO\n", stdout);
5089 				mes("Error: bind() on data stream failed");
5090 				fputs("Error: ", stdout);
5091 				fputs(strerror(save_errno), stdout);
5092 				fputs("\n", stdout);
5093 				fputs("KO\n", stdout);
5094 				goto cleanup;
5095 			}
5096 			err("bind");
5097 		    }
5098 		}
5099 #endif
5100 		else {
5101 		    if (clientserver && !client && (stream_idx == 1)) {
5102 			save_errno = errno;
5103 			fputs("KO\n", stdout);
5104 			mes("Error: unsupported AF on data stream");
5105 			fputs("Error: ", stdout);
5106 			fputs(strerror(save_errno), stdout);
5107 			fputs("\n", stdout);
5108 			fputs("KO\n", stdout);
5109 			goto cleanup;
5110 		    }
5111 		    err("unsupported AF");
5112 		}
5113 
5114 		if (clientserver && !client && (stream_idx == 1)) {
5115 			/* finally OK to send server "OK" message */
5116 			fprintf(stdout, "OK v%d.%d.%d\n", vers_major,
5117 					vers_minor, vers_delta);
5118 			fflush(stdout);
5119 			if ((trans && !reverse) || (!trans && reverse))
5120 				usleep(50000);
5121 		}
5122 
5123 		if (clientserver && (stream_idx == 1)) {
5124 			if (!udp && trans) {
5125 				nretrans[0] = get_retrans(fd[0], &tcpinf);
5126 				if ((retransinfo > 0) || cwndinfo)
5127 					b_flag = 1;
5128 			}
5129 		}
5130 
5131 		if (stream_idx == nstream) {
5132 			if (brief <= 0)
5133 				mes("socket");
5134 #ifdef HAVE_SETPRIO
5135 			if (priority && (brief <= 0)) {
5136 				errno = 0;
5137 				priority = getpriority(PRIO_PROCESS, 0);
5138 				if (errno)
5139 					mes("couldn't get priority");
5140 				else {
5141 					if (format & PARSE)
5142 						fprintf(stdout,
5143 							"nuttcp%s%s: "
5144 							"priority=%d\n",
5145 							trans ? "-t" : "-r",
5146 							ident, priority);
5147 					else
5148 						fprintf(stdout,
5149 							"nuttcp%s%s: "
5150 							"priority = %d\n",
5151 							trans ? "-t" : "-r",
5152 							ident, priority);
5153 				}
5154 			}
5155 #endif
5156 #ifdef HAVE_SETAFFINITY
5157 			if ((affinity >= 0) && (brief <= 0) && !host3) {
5158 				int cpu_affinity;
5159 
5160 				errno = 0;
5161 				sched_getaffinity(0, sizeof(cpu_set_t),
5162 					 &cpu_set);
5163 				if (errno)
5164 					mes("couldn't get affinity");
5165 				else {
5166 					for ( cpu_affinity = 0;
5167 					      cpu_affinity < ncores;
5168 					      cpu_affinity++ ) {
5169 						if (CPU_ISSET(cpu_affinity,
5170 							      &cpu_set))
5171 							break;
5172 					}
5173 					if (format & PARSE)
5174 						fprintf(stdout,
5175 							"nuttcp%s%s: "
5176 							"cpu_affinity=%d\n",
5177 							trans ? "-t" : "-r",
5178 							ident, cpu_affinity);
5179 					else
5180 						fprintf(stdout,
5181 							"nuttcp%s%s: "
5182 							"affinity = CPU %d\n",
5183 							trans ? "-t" : "-r",
5184 							ident, cpu_affinity);
5185 				}
5186 			}
5187 #endif
5188 			if (trans) {
5189 			    if ((brief <= 0) && (format & PARSE)) {
5190 				fprintf(stdout, "nuttcp-t%s: buflen=%d ",
5191 					ident, buflen);
5192 				if (nbuf != INT_MAX)
5193 				    fprintf(stdout, "nbuf=%llu ", nbuf);
5194 				fprintf(stdout, "nstream=%d port=%d",
5195 				    nstream, port);
5196 				if (srcport)
5197 				    fprintf(stdout, " srcport=%d", srcport);
5198 				fprintf(stdout, " mode=%s host=%s",
5199 				    udp?"udp":"tcp",
5200 				    host);
5201 				if (multicast)
5202 				    fprintf(stdout, " multicast_ttl=%d",
5203 					    multicast);
5204 				if (udp) {
5205 					char tmphost[ADDRSTRLEN] = "\0";
5206 					if (af == AF_INET) {
5207 						fprintf(stdout, " af=inet");
5208 						inet_ntop(af, &sinhim[stream_idx].sin_addr.s_addr,
5209 							  tmphost, sizeof(tmphost));
5210 						if (client && (strcmp(host, tmphost) != 0))
5211 							fprintf(stdout, " ip=%s", tmphost);
5212 					}
5213 #ifdef AF_INET6
5214 					else if (af == AF_INET6) {
5215 						fprintf(stdout, " af=inet6");
5216 						inet_ntop(af, &sinhim6[stream_idx].sin6_addr.s6_addr,
5217 							  tmphost, sizeof(tmphost));
5218 						if (client && (strcmp(host, tmphost) != 0))
5219 							fprintf(stdout, " ip=%s", tmphost);
5220 					}
5221 #endif
5222 					else {
5223 						fprintf(stdout, " af=%d", af);
5224 					}
5225 				}
5226 				fprintf(stdout, "\n");
5227 				if (timeout)
5228 				    fprintf(stdout, "nuttcp-t%s: time_limit=%.2f\n",
5229 				    ident, timeout);
5230 				if ((rate != MAXRATE) || tos)
5231 				    fprintf(stdout, "nuttcp-t%s:", ident);
5232 				if (rate != MAXRATE) {
5233 				    fprintf(stdout, " rate_limit=%.3f rate_unit=Mbps rate_mode=%s",
5234 					(double)rate/1000,
5235 					irate ? "instantaneous" : "aggregate");
5236 				    if (iratesss)
5237 					fprintf(stdout, " smoothed_slow_start=on");
5238 				    if (maxburst > 1)
5239 					fprintf(stdout, " packet_burst=%d",
5240 						maxburst);
5241 				    if (udp) {
5242 					unsigned long long ppsrate =
5243 					    ((uint64_t)rate * 1000)/8/buflen;
5244 
5245 					fprintf(stdout, " pps_rate=%llu",
5246 					    ppsrate);
5247 				    }
5248 				}
5249 				if (tos)
5250 				    fprintf(stdout, " tos=0x%X", tos);
5251 				if ((rate != MAXRATE) || tos)
5252 				    fprintf(stdout, "\n");
5253 			    }
5254 			    else if (brief <= 0) {
5255 				fprintf(stdout, "nuttcp-t%s: buflen=%d, ",
5256 					ident, buflen);
5257 				if (nbuf != INT_MAX)
5258 				    fprintf(stdout, "nbuf=%llu, ", nbuf);
5259 				fprintf(stdout, "nstream=%d, port=%d",
5260 				    nstream, port);
5261 				if (srcport)
5262 				    fprintf(stdout, ", srcport=%d", srcport);
5263 				fprintf(stdout, " %s -> %s",
5264 				    udp?"udp":"tcp",
5265 				    host);
5266 				if (multicast)
5267 				    fprintf(stdout, " ttl=%d", multicast);
5268 				if (udp) {
5269 					char tmphost[ADDRSTRLEN] = "\0";
5270 					if (af == AF_INET) {
5271 						fprintf(stdout, " af=inet");
5272 						inet_ntop(af, &sinhim[stream_idx].sin_addr.s_addr,
5273 							  tmphost, sizeof(tmphost));
5274 						if (client && (strcmp(host, tmphost) != 0))
5275 							fprintf(stdout, " ip=%s", tmphost);
5276 					}
5277 #ifdef AF_INET6
5278 					else if (af == AF_INET6) {
5279 						fprintf(stdout, " af=inet6");
5280 						inet_ntop(af, &sinhim6[stream_idx].sin6_addr.s6_addr,
5281 							  tmphost, sizeof(tmphost));
5282 						if (client && (strcmp(host, tmphost) != 0))
5283 							fprintf(stdout, " ip=%s", tmphost);
5284 					}
5285 #endif
5286 					else {
5287 						fprintf(stdout, " af=%d", af);
5288 					}
5289 				}
5290 				fprintf(stdout, "\n");
5291 				if (timeout)
5292 				    fprintf(stdout, "nuttcp-t%s: time limit = %.2f second%s\n",
5293 					ident, timeout,
5294 					(timeout == 1.0)?"":"s");
5295 				if ((rate != MAXRATE) || tos)
5296 				    fprintf(stdout, "nuttcp-t%s:", ident);
5297 				if (rate != MAXRATE) {
5298 				    fprintf(stdout, " rate limit = %.3f Mbps (%s)",
5299 					(double)rate/1000,
5300 					irate ? "instantaneous" : "aggregate");
5301 				    if (iratesss)
5302 					fprintf(stdout, " with smoothed slow start");
5303 				    if (maxburst > 1)
5304 					fprintf(stdout, ", packet burst = %d",
5305 						maxburst);
5306 				    if (udp) {
5307 					unsigned long long ppsrate =
5308 					    ((uint64_t)rate * 1000)/8/buflen;
5309 
5310 					fprintf(stdout, ", %llu pps", ppsrate);
5311 				    }
5312 				    if (tos)
5313 					fprintf(stdout, ",");
5314 				}
5315 				if (tos)
5316 				    fprintf(stdout, " tos = 0x%X", tos);
5317 				if ((rate != MAXRATE) || tos)
5318 				    fprintf(stdout, "\n");
5319 			    }
5320 			}
5321 			else {
5322 			    if ((brief <= 0) && (format & PARSE)) {
5323 				fprintf(stdout, "nuttcp-r%s: buflen=%d ",
5324 					ident, buflen);
5325 				if (nbuf != INT_MAX)
5326 				    fprintf(stdout, "nbuf=%llu ", nbuf);
5327 				fprintf(stdout, "nstream=%d port=%d",
5328 				    nstream, port);
5329 				if (srcport)
5330 				    fprintf(stdout, " srcport=%d", srcport);
5331 				fprintf(stdout, " mode=%s", udp ? "udp":"tcp");
5332 				if (udp) {
5333 					if (af == AF_INET) {
5334 						fprintf(stdout, " af=inet");
5335 					}
5336 #ifdef AF_INET6
5337 					else if (af == AF_INET6) {
5338 						fprintf(stdout, " af=inet6");
5339 					}
5340 #endif
5341 					else {
5342 						fprintf(stdout, " af=%d", af);
5343 					}
5344 				}
5345 				fprintf(stdout, "\n");
5346 				if (tos)
5347 				    fprintf(stdout, "nuttcp-r%s: tos=0x%X\n",
5348 					ident, tos);
5349 				if (interval)
5350 				    fprintf(stdout, "nuttcp-r%s: reporting_interval=%.2f\n",
5351 					ident, interval);
5352 			    }
5353 			    else if (brief <= 0) {
5354 				fprintf(stdout, "nuttcp-r%s: buflen=%d, ",
5355 					ident, buflen);
5356 				if (nbuf != INT_MAX)
5357 				    fprintf(stdout, "nbuf=%llu, ", nbuf);
5358 				fprintf(stdout, "nstream=%d, port=%d",
5359 				    nstream, port);
5360 				if (srcport)
5361 				    fprintf(stdout, ", srcport=%d", srcport);
5362 				fprintf(stdout, " %s", udp ? "udp":"tcp");
5363 				if (udp) {
5364 					if (af == AF_INET) {
5365 						fprintf(stdout, " af=inet");
5366 					}
5367 #ifdef AF_INET6
5368 					else if (af == AF_INET6) {
5369 						fprintf(stdout, " af=inet6");
5370 					}
5371 #endif
5372 					else {
5373 						fprintf(stdout, " af=%d", af);
5374 					}
5375 				}
5376 				fprintf(stdout, "\n");
5377 				if (tos)
5378 				    fprintf(stdout, "nuttcp-r%s: tos = 0x%X\n",
5379 					ident, tos);
5380 				if (interval)
5381 				    fprintf(stdout, "nuttcp-r%s: interval reporting every %.2f second%s\n",
5382 					ident, interval,
5383 					(interval == 1.0)?"":"s");
5384 			    }
5385 			}
5386 		}
5387 
5388 		if (stream_idx > 0) {
5389 		    if (trans) {
5390 			/* Set the transmitter options */
5391 			if (sendwin) {
5392 				if (setsockopt(fd[stream_idx], SOL_SOCKET, SO_SNDBUF,
5393 					(void *)&sendwin, sizeof(sendwin)) < 0)
5394 					errmes("unable to setsockopt SO_SNDBUF");
5395 				if (braindead && (setsockopt(fd[stream_idx], SOL_SOCKET, SO_RCVBUF,
5396 					(void *)&rcvwin, sizeof(rcvwin)) < 0))
5397 					errmes("unable to setsockopt SO_RCVBUF");
5398 			}
5399 			if (tos) {
5400 				if (af == AF_INET) {
5401 					if (setsockopt(fd[stream_idx], IPPROTO_IP, IP_TOS,
5402 						(void *)&tos, sizeof(tos)) < 0)
5403 						err("setsockopt");
5404 				}
5405 #ifdef AF_INET6
5406 				else if (af == AF_INET6) {
5407 					if (setsockopt(fd[stream_idx], IPPROTO_IPV6, IPV6_TCLASS,
5408 						(void *)&tos, sizeof(tos)) < 0)
5409 						err("setsockopt");
5410 				}
5411 #endif
5412 				else {
5413 				    err("unsupported AF");
5414 				}
5415 			}
5416 			if (nodelay && !udp) {
5417 				struct protoent *p;
5418 				p = getprotobyname("tcp");
5419 				if (p && setsockopt(fd[stream_idx], p->p_proto, TCP_NODELAY,
5420 				    (void *)&one, sizeof(one)) < 0)
5421 					err("setsockopt: nodelay");
5422 				if ((stream_idx == nstream) && (brief <= 0))
5423 					mes("nodelay");
5424 			}
5425 		    }
5426 		    else {
5427 			/* Set the receiver options */
5428 			if (rcvwin) {
5429 				if (setsockopt(fd[stream_idx], SOL_SOCKET, SO_RCVBUF,
5430 					(void *)&rcvwin, sizeof(rcvwin)) < 0)
5431 					errmes("unable to setsockopt SO_RCVBUF");
5432 				if (braindead && (setsockopt(fd[stream_idx], SOL_SOCKET, SO_SNDBUF,
5433 					(void *)&sendwin, sizeof(sendwin)) < 0))
5434 					errmes("unable to setsockopt SO_SNDBUF");
5435 			}
5436 			if (tos) {
5437 				if (af == AF_INET) {
5438 					if (setsockopt(fd[stream_idx], IPPROTO_IP, IP_TOS,
5439 						(void *)&tos, sizeof(tos)) < 0)
5440 						err("setsockopt");
5441 				}
5442 #ifdef AF_INET6
5443 				else if (af == AF_INET6) {
5444 					if (setsockopt(fd[stream_idx], IPPROTO_IPV6, IPV6_TCLASS,
5445 						(void *)&tos, sizeof(tos)) < 0)
5446 						err("setsockopt");
5447 				}
5448 #endif
5449 				else {
5450 				    err("unsupported AF");
5451 				}
5452 			}
5453 		    }
5454 		}
5455 		if (!udp || (stream_idx == 0)) {
5456 		    if (((trans && !reverse) && (stream_idx > 0)) ||
5457 			((!trans && reverse) && (stream_idx > 0)) ||
5458 			(client && (stream_idx == 0))) {
5459 			/* The transmitter initiates the connection
5460 			 * (unless reversed by the flip option)
5461 			 */
5462 			if (options && (stream_idx > 0)) {
5463 				if (setsockopt(fd[stream_idx], SOL_SOCKET, options, (void *)&one, sizeof(one)) < 0)
5464 					errmes("unable to setsockopt options");
5465 			}
5466 			usleep(20000);
5467 			if (trans && (stream_idx > 0) && datamss) {
5468 #if defined(__CYGWIN__) || defined(_WIN32)
5469 				if (format & PARSE)
5470 					fprintf(stderr, "nuttcp%s%s: Warning=\"setting_maximum_segment_size_not_supported_on_windows\"\n",
5471 						trans?"-t":"-r", ident);
5472 				else
5473 					fprintf(stderr, "nuttcp%s%s: Warning: setting maximum segment size not supported on windows\n",
5474 						trans?"-t":"-r", ident);
5475 				fflush(stderr);
5476 #endif
5477 				optlen = sizeof(datamss);
5478 				if ((sockopterr = setsockopt(fd[stream_idx], IPPROTO_TCP, TCP_MAXSEG,  (void *)&datamss, optlen)) < 0)
5479 					if (errno != EINVAL)
5480 						err("unable to set maximum segment size");
5481 			}
5482 			if (clientserver && !client && (stream_idx == 1)) {
5483 				/* check if client went away */
5484 				pollfds[0].fd = fileno(ctlconn);
5485 				save_events = pollfds[0].events;
5486 				pollfds[0].events = POLLIN | POLLPRI;
5487 				pollfds[0].revents = 0;
5488 				if ((poll(pollfds, 1, 0) > 0) &&
5489 				    (pollfds[0].revents & (POLLIN | POLLPRI)))
5490 					goto cleanup;
5491 				pollfds[0].events = save_events;
5492 			}
5493 			num_connect_tries++;
5494 			if (stream_idx == 1)
5495 				get_timeofday(&timeconn1, (struct timezone *)0);
5496 			if (af == AF_INET) {
5497 				error_num = connect(fd[stream_idx], (struct sockaddr *)&sinhim[stream_idx], sizeof(sinhim[stream_idx]));
5498 			}
5499 #ifdef AF_INET6
5500 			else if (af == AF_INET6) {
5501 				error_num = connect(fd[stream_idx], (struct sockaddr *)&sinhim6[stream_idx], sizeof(sinhim6[stream_idx]));
5502 			}
5503 #endif
5504 			else {
5505 			    err("unsupported AF");
5506 			}
5507 			if (error_num < 0) {
5508 				if (clientserver && client && (stream_idx == 0)
5509 						 && ((errno == ECONNREFUSED) ||
5510 						     (errno == ECONNRESET))
5511 						 && (num_connect_tries <
5512 							MAX_CONNECT_TRIES)
5513 						 && retry_server) {
5514 					/* retry control connection to
5515 					 * server for certain possibly
5516 					 * transient errors */
5517 					usleep(SERVER_RETRY_USEC);
5518 					goto doit;
5519 				}
5520 				if (!trans && (stream_idx == 0))
5521 					err("connect");
5522 				if (stream_idx > 0) {
5523 					if (clientserver && !client) {
5524 						for ( i = 1; i <= stream_idx;
5525 							     i++ )
5526 							close(fd[i]);
5527 						goto cleanup;
5528 					}
5529 					err("connect");
5530 				}
5531 				if (stream_idx == 0) {
5532 					clientserver = 0;
5533 					if (thirdparty) {
5534 						perror("3rd party connect failed");
5535 						fprintf(stderr, "3rd party nuttcp only supported for client/server mode\n");
5536 						fflush(stderr);
5537 						exit(1);
5538 					}
5539 					if (interval) {
5540 						perror("connect failed");
5541 						fprintf(stderr, "interval option only supported for client/server mode\n");
5542 						fflush(stderr);
5543 						exit(1);
5544 					}
5545 					if (reverse) {
5546 						perror("connect failed");
5547 						fprintf(stderr, "flip option only supported for client/server mode\n");
5548 						fflush(stderr);
5549 						exit(1);
5550 					}
5551 					if (traceroute) {
5552 						perror("connect failed");
5553 						fprintf(stderr, "traceroute option only supported for client/server mode\n");
5554 						fflush(stderr);
5555 						exit(1);
5556 					}
5557 					if (host3) {
5558 						perror("connect failed");
5559 						fprintf(stderr, "3rd party nuttcp only supported for client/server mode\n");
5560 						fflush(stderr);
5561 						exit(1);
5562 					}
5563 					if (multicast) {
5564 						perror("connect failed");
5565 						fprintf(stderr, "multicast only supported for client/server mode\n");
5566 						fflush(stderr);
5567 						exit(1);
5568 					}
5569 					if (udp) {
5570 						perror("connect failed");
5571 						fprintf(stderr, "UDP transfers only supported for client/server mode\n");
5572 						fflush(stderr);
5573 						exit(1);
5574 					}
5575 					if (format & PARSE) {
5576 						fprintf(stderr, "nuttcp%s%s: Info=\"attempting_to_switch_to_deprecated_classic_mode\"\n",
5577 							trans?"-t":"-r", ident);
5578 						fprintf(stderr, "nuttcp%s%s: Info=\"will_use_less_reliable_transmitter_side_statistics\"\n",
5579 							trans?"-t":"-r", ident);
5580 					}
5581 					else {
5582 						fprintf(stderr, "nuttcp%s%s: Info: attempting to switch to deprecated \"classic\" mode\n",
5583 							trans?"-t":"-r", ident);
5584 						fprintf(stderr, "nuttcp%s%s: Info: will use less reliable transmitter side statistics\n",
5585 							trans?"-t":"-r", ident);
5586 					}
5587 					fflush(stderr);
5588 				}
5589 			}
5590 			if (stream_idx == 1) {
5591 				get_timeofday(&timeconn2, (struct timezone *)0);
5592 				tvsub( &timeconn, &timeconn2, &timeconn1 );
5593 				rtt = timeconn.tv_sec*1000 +
5594 						((double)timeconn.tv_usec)/1000;
5595 			}
5596 			if (sockopterr && trans &&
5597 			    (stream_idx > 0) && datamss) {
5598 				optlen = sizeof(datamss);
5599 				if ((sockopterr = setsockopt(fd[stream_idx], IPPROTO_TCP, TCP_MAXSEG,  (void *)&datamss, optlen)) < 0) {
5600 					if (errno != EINVAL)
5601 						err("unable to set maximum segment size");
5602 					else
5603 						err("setting maximum segment size not supported on this OS");
5604 				}
5605 			}
5606 			if (stream_idx == nstream) {
5607 				optlen = sizeof(datamss);
5608 				if (getsockopt(fd[stream_idx], IPPROTO_TCP, TCP_MAXSEG,  (void *)&datamss, &optlen) < 0)
5609 					err("get dataconn maximum segment size didn't work");
5610 				if (format & DEBUGMTU)
5611 					fprintf(stderr, "datamss = %d\n", datamss);
5612 			}
5613 			if ((stream_idx == nstream) && (brief <= 0)) {
5614 				char tmphost[ADDRSTRLEN] = "\0";
5615 				if (af == AF_INET) {
5616 				    inet_ntop(af, &sinhim[stream_idx].sin_addr.s_addr, tmphost, sizeof(tmphost));
5617 				}
5618 #ifdef AF_INET6
5619 				else if (af == AF_INET6) {
5620 				    if (!IN6_IS_ADDR_V4MAPPED(&sinhim6[stream_idx].sin6_addr)) {
5621 					inet_ntop(af, sinhim6[stream_idx].sin6_addr.s6_addr, tmphost, sizeof(tmphost));
5622 				    }
5623 				    else {
5624 					af = AF_INET;
5625 					bcopy(((char *)&sinhim6[stream_idx].sin6_addr) + 12,
5626 					      (char *)&sinhim[stream_idx].sin_addr,
5627 					      sizeof(struct in_addr));
5628 					sinhim[stream_idx].sin_family = AF_INET;
5629 					// port gets put in both structs, no translate or copy needed
5630 					inet_ntop(af, &sinhim[stream_idx].sin_addr.s_addr, tmphost, sizeof(tmphost));
5631 				    }
5632 				}
5633 #endif
5634 				else {
5635 				    err("unsupported AF");
5636 				}
5637 
5638 				if (format & PARSE) {
5639 					fprintf(stdout,
5640 						"nuttcp%s%s: connect=%s",
5641 						trans?"-t":"-r", ident,
5642 						tmphost);
5643 					if (trans && datamss) {
5644 						fprintf(stdout, " mss=%d",
5645 							datamss);
5646 					}
5647 					if (rtt)
5648 						fprintf(stdout, P_RTT_FMT, rtt);
5649 				}
5650 				else {
5651 					fprintf(stdout,
5652 						"nuttcp%s%s: connect to %s with",
5653 						trans?"-t":"-r", ident,
5654 						tmphost);
5655 					if (trans && datamss) {
5656 						fprintf(stdout, " mss=%d",
5657 							datamss);
5658 						if (rtt)
5659 							fprintf(stdout, ",");
5660 					}
5661 					if (rtt)
5662 						fprintf(stdout, RTT_FMT, rtt);
5663 				}
5664 				if (af == AF_INET) {
5665 					fprintf(stdout, " af=inet");
5666 				}
5667 #ifdef AF_INET6
5668 				else if (af == AF_INET6) {
5669 					fprintf(stdout, " af=inet6");
5670 				}
5671 #endif
5672 				else {
5673 					fprintf(stdout, " af=%d", af);
5674 				}
5675 				fprintf(stdout, "\n");
5676 			}
5677 		    }
5678 		    else {
5679 			/* The receiver listens for the connection
5680 			 * (unless reversed by the flip option)
5681 			 */
5682 			if (trans && (stream_idx > 0) && datamss) {
5683 #if defined(__CYGWIN__) || defined(_WIN32)
5684 				if (format & PARSE)
5685 					fprintf(stderr, "nuttcp%s%s: Warning=\"setting_maximum_segment_size_not_supported_on_windows\"\n",
5686 						trans?"-t":"-r", ident);
5687 				else
5688 					fprintf(stderr, "nuttcp%s%s: Warning: setting maximum segment size not supported on windows\n",
5689 						trans?"-t":"-r", ident);
5690 				fflush(stderr);
5691 #endif
5692 				optlen = sizeof(datamss);
5693 				if ((sockopterr = setsockopt(fd[stream_idx], IPPROTO_TCP, TCP_MAXSEG,  (void *)&datamss, optlen)) < 0)
5694 					if (errno != EINVAL)
5695 						err("unable to set maximum segment size");
5696 			}
5697 			listen(fd[stream_idx], LISTEN_BACKLOG);
5698 			if (clientserver && !client && (stream_idx == 0)
5699 					 && !inetd && !nofork && !forked) {
5700 				if ((pid = fork()) == (pid_t)-1)
5701 					err("can't fork");
5702 				if (pid != 0)
5703 					exit(0);
5704 				forked = 1;
5705 				if (sinkmode) {
5706 					close(0);
5707 					close(1);
5708 					close(2);
5709 					open("/dev/null", O_RDWR);
5710 					dup(0);
5711 					dup(0);
5712 				}
5713 				setsid();
5714 			}
5715 			if (options && (stream_idx > 0)) {
5716 				if (setsockopt(fd[stream_idx], SOL_SOCKET, options, (void *)&one, sizeof(one)) < 0)
5717 					errmes("unable to setsockopt options");
5718 			}
5719 			if (sockopterr && trans &&
5720 			    (stream_idx > 0) && datamss) {
5721 				optlen = sizeof(datamss);
5722 				if ((sockopterr = setsockopt(fd[stream_idx], IPPROTO_TCP, TCP_MAXSEG,  (void *)&datamss, optlen)) < 0)
5723 					if (errno != EINVAL)
5724 						err("unable to set maximum segment size");
5725 			}
5726 			if (clientserver && (stream_idx > 0)) {
5727 				sigact.sa_handler = ignore_alarm;
5728 				sigemptyset(&sigact.sa_mask);
5729 				sigact.sa_flags = 0;
5730 				sigaction(SIGALRM, &sigact, &savesigact);
5731 				alarm(ACCEPT_TIMEOUT);
5732 			}
5733 acceptnewconn:
5734 			fromlen = sizeof(frominet);
5735 			nfd=accept(fd[stream_idx], (struct sockaddr *)&frominet, &fromlen);
5736 			save_errno = errno;
5737 			if (clientserver && (stream_idx > 0)) {
5738 				alarm(0);
5739 				sigact.sa_handler = savesigact.sa_handler;
5740 				sigact.sa_mask = savesigact.sa_mask;
5741 				sigact.sa_flags = savesigact.sa_flags;
5742 				sigaction(SIGALRM, &sigact, 0);
5743 			}
5744 			if (nfd < 0) {
5745 				/* check for interrupted system call - on
5746 				 * server, close data streams, cleanup and
5747 				 * try again - all other errors just die
5748 				 */
5749 				if ((save_errno == EINTR) && clientserver
5750 							  && (stream_idx > 0)) {
5751 					if (client) {
5752 						/* if client, just give nice
5753 						 * error message and exit
5754 						 */
5755 						mes("Error: accept() timeout");
5756 						exit(1);
5757 					}
5758 					for ( i = 1; i <= stream_idx; i++ )
5759 						close(fd[i]);
5760 					goto cleanup;
5761 				}
5762 				err("accept");
5763 			}
5764 			if (clientserver && !client && (stream_idx == 0)
5765 					 && !inetd && !nofork
5766 					 && !single_threaded) {
5767 				/* multi-threaded manually started server */
5768 				if ((pid = fork()) == (pid_t)-1)
5769 					err("can't fork");
5770 				if (pid != 0) {
5771 					/* parent just waits for quick
5772 					 * child exit */
5773 					while ((wait_pid = wait(&pidstat))
5774 						    != pid) {
5775 						if (wait_pid == (pid_t)-1) {
5776 							if (errno == ECHILD)
5777 								break;
5778 							err("wait failed");
5779 						}
5780 					}
5781 					/* and then accept()s another client
5782 					 * connection */
5783 					close(nfd);
5784 					stream_idx = 0;
5785 					if (oneshot)
5786 						exit(0);
5787 					goto acceptnewconn;
5788 				}
5789 				/* child just makes a grandchild and then
5790 				 * immediately exits (avoid zombie processes) */
5791 				if ((pid = fork()) == (pid_t)-1)
5792 					err("can't fork");
5793 				if (pid != 0)
5794 					exit(0);
5795 				/* grandkid does all the work */
5796 				oneshot = 1;
5797 			}
5798 			af = frominet.ss_family;
5799 			close(fd[stream_idx]);
5800 			fd[stream_idx]=nfd;
5801 			if (sockopterr && trans &&
5802 			    (stream_idx > 0) && datamss) {
5803 				optlen = sizeof(datamss);
5804 				if ((sockopterr = setsockopt(fd[stream_idx], IPPROTO_TCP, TCP_MAXSEG,  (void *)&datamss, optlen)) < 0) {
5805 					if (errno != EINVAL)
5806 						err("unable to set maximum segment size");
5807 					else
5808 						err("setting maximum segment size not supported on this OS");
5809 				}
5810 			}
5811 			if (stream_idx == nstream) {
5812 				optlen = sizeof(datamss);
5813 				if (getsockopt(fd[stream_idx], IPPROTO_TCP, TCP_MAXSEG,  (void *)&datamss, &optlen) < 0)
5814 					err("get dataconn maximum segment size didn't work");
5815 				if (format & DEBUGMTU)
5816 					fprintf(stderr, "datamss = %d\n", datamss);
5817 			}
5818 			if (af == AF_INET) {
5819 			    struct sockaddr_in peer;
5820 			    socklen_t peerlen = sizeof(peer);
5821 			    if (getpeername(fd[stream_idx],
5822 					    (struct sockaddr *)&peer,
5823 					    &peerlen) < 0) {
5824 				err("getpeername");
5825 			    }
5826 			    if ((stream_idx == nstream) && (brief <= 0)) {
5827 				char tmphost[ADDRSTRLEN] = "\0";
5828 				inet_ntop(af, &peer.sin_addr.s_addr, tmphost, sizeof(tmphost));
5829 
5830 				if (format & PARSE) {
5831 					fprintf(stdout,
5832 						"nuttcp%s%s: accept=%s",
5833 						trans?"-t":"-r", ident,
5834 						tmphost);
5835 					if (trans && datamss) {
5836 						fprintf(stdout, " mss=%d",
5837 							datamss);
5838 					}
5839 				}
5840 				else {
5841 					fprintf(stdout,
5842 						"nuttcp%s%s: accept from %s with",
5843 						trans?"-t":"-r", ident,
5844 						tmphost);
5845 					if (trans && datamss) {
5846 						fprintf(stdout, " mss=%d,",
5847 							datamss);
5848 					}
5849 				}
5850 				if (af == AF_INET) {
5851 					fprintf(stdout, " af=inet");
5852 				}
5853 #ifdef AF_INET6
5854 				else if (af == AF_INET6) {
5855 					fprintf(stdout, " af=inet6");
5856 				}
5857 #endif
5858 				else {
5859 					fprintf(stdout, " af=%d", af);
5860 				}
5861 				fprintf(stdout, "\n");
5862 			    }
5863 			    if (stream_idx == 0) {
5864 				clientaddr = peer.sin_addr;
5865 				client_ipaddr.ss.ss_family = AF_INET;
5866 				client_ipaddr.sin.sin_addr = clientaddr;
5867 			    }
5868 			}
5869 #ifdef AF_INET6
5870 			else if (af == AF_INET6) {
5871 			    struct sockaddr_in6 peer6;
5872 			    struct sockaddr_in peer4;
5873 			    socklen_t peerlen = sizeof(peer6);
5874 			    if (getpeername(fd[stream_idx],
5875 					    (struct sockaddr *)&peer6,
5876 					    &peerlen) < 0) {
5877 				err("getpeername");
5878 			    }
5879 			    if ((stream_idx == nstream) && (brief <= 0)) {
5880 				char tmphost[ADDRSTRLEN] = "\0";
5881 				if (!IN6_IS_ADDR_V4MAPPED(&peer6.sin6_addr)) {
5882 					inet_ntop(af, peer6.sin6_addr.s6_addr, tmphost, sizeof(tmphost));
5883 				}
5884 				else {
5885 					af = AF_INET;
5886 					bcopy(((char *)&peer6.sin6_addr.s6_addr) + 12,
5887 					      (char *)&peer4.sin_addr.s_addr,
5888 					      sizeof(struct in_addr));
5889 					peer4.sin_family = AF_INET;
5890 					peer4.sin_port = peer6.sin6_port;
5891 					inet_ntop(af, &peer4.sin_addr.s_addr, tmphost, sizeof(tmphost));
5892 				}
5893 				if (format & PARSE) {
5894 				    fprintf(stdout,
5895 					    "nuttcp%s%s: accept=%s",
5896 					    trans?"-t":"-r", ident,
5897 					    tmphost);
5898 				    if (trans && datamss) {
5899 					fprintf(stdout, " mss=%d", datamss);
5900 				    }
5901 				}
5902 				else {
5903 				    fprintf(stdout,
5904 					    "nuttcp%s%s: accept from %s with",
5905 					    trans?"-t":"-r", ident,
5906 					    tmphost);
5907 				    if (trans && datamss) {
5908 					fprintf(stdout, " mss=%d,",
5909 						datamss);
5910 				    }
5911 				}
5912 				if (af == AF_INET) {
5913 					fprintf(stdout, " af=inet");
5914 				}
5915 #ifdef AF_INET6
5916 				else if (af == AF_INET6) {
5917 					fprintf(stdout, " af=inet6");
5918 				}
5919 #endif
5920 				else {
5921 					fprintf(stdout, " af=%d", af);
5922 				}
5923 				fprintf(stdout, "\n");
5924 			    }
5925 			    if (stream_idx == 0) {
5926 				if (af == AF_INET6) { // we didnt fix a mapped v4 ip
5927 					clientaddr6 = peer6.sin6_addr;
5928 					clientscope6 = peer6.sin6_scope_id;
5929 					client_ipaddr.ss.ss_family = AF_INET6;
5930 					client_ipaddr.sin6.sin6_addr = clientaddr6;
5931 				}
5932 				else { // mapped so af is AF_INET
5933 					clientaddr = peer4.sin_addr;
5934 					client_ipaddr.ss.ss_family = AF_INET;
5935 					client_ipaddr.sin.sin_addr = clientaddr;
5936 				}
5937 			    }
5938 			}
5939 #endif
5940 			else {
5941 			    err("unsupported AF");
5942 			}
5943 		    }
5944 		}
5945 		if (!udp && trans && (stream_idx >= 1) && (retransinfo > 0)) {
5946 			if ((stream_idx == 1) || (retransinfo == 1)) {
5947 				nretrans[stream_idx] =
5948 					get_retrans(fd[stream_idx], &tcpinf);
5949 				iretrans[stream_idx] = nretrans[stream_idx];
5950 #if defined(linux)
5951 				if (retransinfo == 1) {
5952 					cwnd[stream_idx] =
5953 						tcpinf.tcpinfo_snd_cwnd
5954 							*datamss/1024;
5955 					if (stream_idx == 1) {
5956 						init_pkt_cwnd =
5957 							tcpinf.tcpinfo_snd_cwnd;
5958 						sss_pkt_cwnd = init_pkt_cwnd;
5959 					}
5960 				}
5961 #endif
5962 			}
5963 		}
5964 		optlen = sizeof(sendwinval);
5965 		if (getsockopt(fd[stream_idx], SOL_SOCKET, SO_SNDBUF,  (void *)&sendwinval, &optlen) < 0)
5966 			err("get send window size didn't work");
5967 #if defined(linux)
5968 		sendwinval /= 2;
5969 #endif
5970 		if ((stream_idx > 0) && sendwin && (trans || braindead) &&
5971 		    (sendwinval < (0.98 * sendwin))) {
5972 			if (format & PARSE)
5973 				fprintf(stderr, "nuttcp%s%s: Warning=\"send_window_size_%d_<_requested_window_size_%d\"\n",
5974 					trans?"-t":"-r", ident,
5975 					sendwinval, sendwin);
5976 			else
5977 				fprintf(stderr, "nuttcp%s%s: Warning: send window size %d < requested window size %d\n",
5978 					trans?"-t":"-r", ident,
5979 					sendwinval, sendwin);
5980 			fflush(stderr);
5981 		}
5982 		optlen = sizeof(rcvwinval);
5983 		if (getsockopt(fd[stream_idx], SOL_SOCKET, SO_RCVBUF,  (void *)&rcvwinval, &optlen) < 0)
5984 			err("Get recv window size didn't work");
5985 #if defined(linux)
5986 		rcvwinval /= 2;
5987 #endif
5988 		if ((stream_idx > 0) && rcvwin && (!trans || braindead) &&
5989 		    (rcvwinval < (0.98 * rcvwin))) {
5990 			if (format & PARSE)
5991 				fprintf(stderr, "nuttcp%s%s: Warning=\"receive_window_size_%d_<_requested_window_size_%d\"\n",
5992 					trans?"-t":"-r", ident,
5993 					rcvwinval, rcvwin);
5994 			else
5995 				fprintf(stderr, "nuttcp%s%s: Warning: receive window size %d < requested window size %d\n",
5996 					trans?"-t":"-r", ident,
5997 					rcvwinval, rcvwin);
5998 			fflush(stderr);
5999 		}
6000 
6001 		if (firsttime) {
6002 			firsttime = 0;
6003 			origsendwin = sendwinval;
6004 			origrcvwin = rcvwinval;
6005 		}
6006 
6007 		if ((stream_idx == nstream) && (brief <= 0)) {
6008 #if defined(linux)
6009 			FILE *adv_ws;
6010 
6011 			sendwinval *= 2;
6012 			rcvwinval  *= 2;
6013 			if ((adv_ws = fopen(TCP_ADV_WIN_SCALE, "r"))) {
6014 				if (fscanf(adv_ws, "%d", &winadjust) <= 0)
6015 					winadjust = 2;
6016 				fclose(adv_ws);
6017 			}
6018 			else {
6019 				winadjust = 2;
6020 			}
6021 			if (winadjust < 0) {
6022 				sendwinavail = sendwinval >> -winadjust;
6023 				rcvwinavail  = rcvwinval  >> -winadjust;
6024 			}
6025 			else if (winadjust > 0) {
6026 				sendwinavail = sendwinval -
6027 						   (sendwinval >> winadjust);
6028 				rcvwinavail  = rcvwinval  -
6029 						   (rcvwinval  >> winadjust);
6030 			}
6031 #endif
6032 			if (format & PARSE)
6033 				fprintf(stdout, "nuttcp%s%s: send_window_size=%d receive_window_size=%d\n", trans?"-t":"-r", ident, sendwinval, rcvwinval);
6034 			else
6035 				fprintf(stdout, "nuttcp%s%s: send window size = %d, receive window size = %d\n", trans?"-t":"-r", ident, sendwinval, rcvwinval);
6036 #if defined(linux)
6037 			if (format & PARSE)
6038 				fprintf(stdout, "nuttcp%s%s: send_window_avail=%d receive_window_avail=%d\n", trans?"-t":"-r", ident, sendwinavail, rcvwinavail);
6039 			else
6040 				fprintf(stdout, "nuttcp%s%s: available send window = %d, available receive window = %d\n", trans?"-t":"-r", ident, sendwinavail, rcvwinavail);
6041 			if (!udp && trans && init_pkt_cwnd) {
6042 				if (format & PARSE)
6043 					fprintf(stdout, "nuttcp%s%s: initial_congestion_window_kb=%d initial_congestion_window_pkt=%d\n", trans?"-t":"-r", ident, init_pkt_cwnd*datamss/1024, init_pkt_cwnd);
6044 				else
6045 					fprintf(stdout, "nuttcp%s%s: initial congestion window = %d KB (%d packets)\n", trans?"-t":"-r", ident, init_pkt_cwnd*datamss/1024, init_pkt_cwnd);
6046 			}
6047 #endif
6048 		}
6049 	}
6050 
6051 	if (abortconn)
6052 		exit(1);
6053 
6054 	if (host3 && clientserver) {
6055 		char path[64];
6056 		char *cmd;
6057 
6058 		fflush(stdout);
6059 		fflush(stderr);
6060 		cmd = nut_cmd;
6061 
6062 		if (client) {
6063 			if ((pid = fork()) == (pid_t)-1)
6064 				err("can't fork");
6065 			if (pid == 0) {
6066 				if (interval) {
6067 					itimer.it_value.tv_sec = interval;
6068 				}
6069 				else if (timeout) {
6070 					itimer.it_value.tv_sec = timeout;
6071 				}
6072 				else {
6073 					if (rate != MAXRATE)
6074 						itimer.it_value.tv_sec =
6075 							(double)(2*nbuf*buflen)
6076 								/rate/125;
6077 					else
6078 						itimer.it_value.tv_sec =
6079 							(double)(nbuf*buflen)
6080 							    /LOW_RATE_HOST3/125;
6081 					if (itimer.it_value.tv_sec < 7200)
6082 						itimer.it_value.tv_sec = 7200;
6083 				}
6084 				itimer.it_value.tv_sec +=
6085 					idle_data_max < SRVR_INFO_TIMEOUT ?
6086 					    SRVR_INFO_TIMEOUT : idle_data_max;
6087 				itimer.it_value.tv_usec = 0;
6088 				itimer.it_interval.tv_sec = 0;
6089 				itimer.it_interval.tv_usec = 0;
6090 				setitimer(ITIMER_REAL, &itimer, 0);
6091 				while (fgets(linebuf, sizeof(linebuf),
6092 					     stdin) && !intr) {
6093 					setitimer(ITIMER_REAL, &itimer, 0);
6094 					if (strncmp(linebuf, "DONE", 4)
6095 							== 0)
6096 						exit(0);
6097 					if (*ident && (*linebuf != '\n'))
6098 						fprintf(stdout, "%s: ",
6099 							ident + 1);
6100 					fputs(linebuf, stdout);
6101 					fflush(stdout);
6102 				}
6103 				itimer.it_value.tv_sec = 0;
6104 				itimer.it_value.tv_usec = 0;
6105 				setitimer(ITIMER_REAL, &itimer, 0);
6106 				exit(0);
6107 			}
6108 			signal(SIGINT, SIG_IGN);
6109 			while ((wait_pid = wait(&pidstat)) != pid) {
6110 				if (wait_pid == (pid_t)-1) {
6111 					if (errno == ECHILD)
6112 						break;
6113 					err("wait failed");
6114 				}
6115 			}
6116 			exit(0);
6117 		}
6118 		else {
6119 			if ((pid = fork()) == (pid_t)-1)
6120 				err("can't fork");
6121 			if (pid != 0) {
6122 				sigact.sa_handler = &sigalarm;
6123 				sigemptyset(&sigact.sa_mask);
6124 				sigact.sa_flags = 0;
6125 				sigaction(SIGALRM, &sigact, 0);
6126 				alarm(10);
6127 				while ((wait_pid = wait(&pidstat))
6128 						!= pid) {
6129 					if (wait_pid == (pid_t)-1) {
6130 						if (errno == ECHILD)
6131 							break;
6132 						if (errno == EINTR) {
6133 							pollfds[0].fd =
6134 							    fileno(ctlconn);
6135 							pollfds[0].events =
6136 							    POLLIN | POLLPRI;
6137 							pollfds[0].revents = 0;
6138 							if ((poll(pollfds, 1, 0)
6139 									> 0)
6140 								&& (pollfds[0].revents &
6141 									(POLLIN | POLLPRI))) {
6142 								kill(pid,
6143 								     SIGINT);
6144 								sleep(1);
6145 								kill(pid,
6146 								     SIGINT);
6147 								continue;
6148 							}
6149 							sigact.sa_handler =
6150 								&sigalarm;
6151 							sigemptyset(&sigact.sa_mask);
6152 							sigact.sa_flags = 0;
6153 							sigaction(SIGALRM,
6154 								  &sigact, 0);
6155 							alarm(10);
6156 							continue;
6157 						}
6158 						err("wait failed");
6159 					}
6160 				}
6161 				fprintf(stdout, "DONE\n");
6162 				fflush(stdout);
6163 				goto cleanup;
6164 			}
6165 			close(2);
6166 			dup(1);
6167 			i = 0;
6168 			j = 0;
6169 			cmdargs[i++] = cmd;
6170 			cmdargs[i++] = "-3";
6171 			if (af3) {
6172 				if (af3 == 4)
6173 					cmdargs[i++] = "-4";
6174 				if (af3 == 6)
6175 					cmdargs[i++] = "-6";
6176 			}
6177 			if (ctlport3) {
6178 				sprintf(tmpargs[j], "-P%hu", ctlport3);
6179 				cmdargs[i++] = tmpargs[j++];
6180 			}
6181 			else {
6182 				if (pass_ctlport) {
6183 					sprintf(tmpargs[j], "-P%hu", ctlport);
6184 					cmdargs[i++] = tmpargs[j++];
6185 				}
6186 			}
6187 			if (affinity >= 0) {
6188 				sprintf(tmpargs[j], "-xc%d", affinity);
6189 				cmdargs[i++] = tmpargs[j++];
6190 			}
6191 			if (srvr_affinity >= 0) {
6192 				sprintf(tmpargs[j], "-xcs%d", srvr_affinity);
6193 				cmdargs[i++] = tmpargs[j++];
6194 			}
6195 			if (irvers < 50302) {
6196 				if ((udp && !multicast
6197 					 && (buflen != DEFAULTUDPBUFLEN)) ||
6198 				    (udp && multicast
6199 					 && (buflen != DEFAULT_MC_UDPBUFLEN)) ||
6200 				    (!udp && (buflen != 65536))) {
6201 					sprintf(tmpargs[j], "-l%d", buflen);
6202 					cmdargs[i++] = tmpargs[j++];
6203 				}
6204 			}
6205 			else if (buflen) {
6206 				sprintf(tmpargs[j], "-l%d", buflen);
6207 				cmdargs[i++] = tmpargs[j++];
6208 			}
6209 			if (nbuf != INT_MAX) {
6210 				if (nbuf_bytes)
6211 					sprintf(tmpargs[j], "-n%llub", nbuf);
6212 				else
6213 					sprintf(tmpargs[j], "-n%llu", nbuf);
6214 				cmdargs[i++] = tmpargs[j++];
6215 			}
6216 			if (brief3 != 1) {
6217 				sprintf(tmpargs[j], "-b%d", brief3);
6218 				cmdargs[i++] = tmpargs[j++];
6219 			}
6220 			if (sendwin) {
6221 				sprintf(tmpargs[j], "-w%d", sendwin/1024);
6222 				cmdargs[i++] = tmpargs[j++];
6223 			}
6224 			if (nstream != 1) {
6225 				sprintf(tmpargs[j], "-N%d%s", nstream,
6226 					multilink ? "m" : "");
6227 				cmdargs[i++] = tmpargs[j++];
6228 			}
6229 			if (rate != MAXRATE) {
6230 				if (maxburst > 1) {
6231 					if (rate_pps)
6232 						sprintf(tmpargs[j],
6233 							"-R%s%lup/%d",
6234 							irate ? "i" : "",
6235 							rate, maxburst);
6236 					else
6237 						sprintf(tmpargs[j],
6238 							"-R%s%lu/%d",
6239 							irate ? "i" : "",
6240 							rate, maxburst);
6241 				}
6242 				else {
6243 					if (rate_pps)
6244 						sprintf(tmpargs[j],
6245 							"-R%s%s%lup",
6246 							irate ? "i" : "",
6247 							iratesss ? "s" : "",
6248 							rate);
6249 					else
6250 						sprintf(tmpargs[j],
6251 							"-R%s%s%lu",
6252 							irate ? "i" : "",
6253 							iratesss ? "s" : "",
6254 							rate);
6255 				}
6256 				cmdargs[i++] = tmpargs[j++];
6257 			}
6258 			else {
6259 				if (udp && !multicast)
6260 					cmdargs[i++] = "-R0";
6261 			}
6262 			if (srcport) {
6263 				sprintf(tmpargs[j], "-p%hu:%hu", srcport, port);
6264 				cmdargs[i++] = tmpargs[j++];
6265 			}
6266 			else if (port != DEFAULT_PORT) {
6267 				sprintf(tmpargs[j], "-p%hu", port);
6268 				cmdargs[i++] = tmpargs[j++];
6269 			}
6270 			if (trans)
6271 				cmdargs[i++] = "-r";
6272 			if (braindead)
6273 				cmdargs[i++] = "-wb";
6274 			if (timeout && (timeout != DEFAULT_TIMEOUT)) {
6275 				sprintf(tmpargs[j], "-T%f", timeout);
6276 				cmdargs[i++] = tmpargs[j++];
6277 			}
6278 			if (udp) {
6279 				if (multicast) {
6280 					if (ssm == 1)
6281 						sprintf(tmpargs[j], "-ms%d",
6282 							multicast);
6283 					else if (ssm == 0)
6284 						sprintf(tmpargs[j], "-ma%d",
6285 							multicast);
6286 					else
6287 						sprintf(tmpargs[j], "-m%d",
6288 							multicast);
6289 					cmdargs[i++] = tmpargs[j++];
6290 					if (mc_addr) {
6291 						sprintf(tmpargs[j], "-g%s",
6292 							mc_addr);
6293 						cmdargs[i++] = tmpargs[j++];
6294 					}
6295 				}
6296 				else
6297 					cmdargs[i++] = "-u";
6298 			}
6299 			if (do_jitter) {
6300 				cmdargs[i++] = "-j";
6301 			}
6302 			if (do_owd) {
6303 				cmdargs[i++] = "-o";
6304 			}
6305 			if (interval) {
6306 				sprintf(tmpargs[j], "-i%f", interval);
6307 				cmdargs[i++] = tmpargs[j++];
6308 			}
6309 			if (reverse)
6310 				cmdargs[i++] = "-F";
6311 			if (format) {
6312 				if (format & XMITSTATS)
6313 					cmdargs[i++] = "-fxmitstats";
6314 				if (format & RUNNINGTOTAL)
6315 					cmdargs[i++] = "-frunningtotal";
6316 				if (format & NOPERCENTLOSS)
6317 					cmdargs[i++] = "-f-percentloss";
6318 				if (format & NODROPS)
6319 					cmdargs[i++] = "-f-drops";
6320 				if (format & NORETRANS)
6321 					cmdargs[i++] = "-f-retrans";
6322 				if (!(format & NORETRANS) && (format & NOCWND))
6323 					cmdargs[i++] = "-f-cwnd";
6324 				if (format & PARSE)
6325 					cmdargs[i++] = "-fparse";
6326 			}
6327 			else {
6328 				cmdargs[i++] = "-f-rtt";
6329 			}
6330 			if (traceroute)
6331 				cmdargs[i++] = "-xt";
6332 			if (datamss) {
6333 				sprintf(tmpargs[j], "-M%d", datamss);
6334 				cmdargs[i++] = tmpargs[j++];
6335 			}
6336 			if (tos) {
6337 				sprintf(tmpargs[j], "-c0x%Xt", tos);
6338 				cmdargs[i++] = tmpargs[j++];
6339 			}
6340 			if (nodelay)
6341 				cmdargs[i++] = "-D";
6342 			if (ipad_stride.ip32) {
6343 				sprintf(tmpargs[j], "%s+%d", host3,
6344 					ipad_stride.ip32);
6345 				cmdargs[i++] = tmpargs[j++];
6346 			}
6347 			else
6348 				cmdargs[i++] = host3;
6349 			cmdargs[i] = NULL;
6350 			execvp(cmd, cmdargs);
6351 			if (errno == ENOENT) {
6352 				strcpy(path, "/usr/local/sbin/");
6353 				strcat(path, cmd);
6354 				execv(path, cmdargs);
6355 			}
6356 			if (errno == ENOENT) {
6357 				strcpy(path, "/usr/local/bin/");
6358 				strcat(path, cmd);
6359 				execv(path, cmdargs);
6360 			}
6361 			if (errno == ENOENT) {
6362 				strcpy(path, "/usr/sbin/");
6363 				strcat(path, cmd);
6364 				execv(path, cmdargs);
6365 			}
6366 			if (errno == ENOENT) {
6367 				strcpy(path, "/sbin/");
6368 				strcat(path, cmd);
6369 				execv(path, cmdargs);
6370 			}
6371 			if (errno == ENOENT) {
6372 				strcpy(path, "/usr/etc/");
6373 				strcat(path, cmd);
6374 				execv(path, cmdargs);
6375 			}
6376 			if ((errno == ENOENT) && (getuid() != 0)
6377 					      && (geteuid() != 0)) {
6378 				strcpy(path, "./");
6379 				strcat(path, cmd);
6380 				execv(path, cmdargs);
6381 			}
6382 			perror("execvp failed");
6383 			fprintf(stderr, "failed to execute %s\n", cmd);
6384 			fflush(stdout);
6385 			fflush(stderr);
6386 			if (!inetd)
6387 				exit(0);
6388 			goto cleanup;
6389 		}
6390 	}
6391 
6392 	if (traceroute && clientserver) {
6393 		char path[64];
6394 		char *cmd;
6395 
6396 		fflush(stdout);
6397 		fflush(stderr);
6398 		if (multicast) {
6399 			cmd = "mtrace";
6400 #ifdef AF_INET6
6401 			if (af == AF_INET6)
6402 				cmd = "mtrace6";
6403 #endif
6404 		}
6405 		else {
6406 			cmd = "traceroute";
6407 #ifdef AF_INET6
6408 			if (af == AF_INET6)
6409 				cmd = "traceroute6";
6410 #endif
6411 		}
6412 		if (client) {
6413 			if ((pid = fork()) == (pid_t)-1)
6414 				err("can't fork");
6415 			if (pid != 0) {
6416 				while ((wait_pid = wait(&pidstat)) != pid) {
6417 					if (wait_pid == (pid_t)-1) {
6418 						if (errno == ECHILD)
6419 							break;
6420 						err("wait failed");
6421 					}
6422 				}
6423 				fflush(stdout);
6424 			}
6425 			else {
6426 				signal(SIGINT, SIG_DFL);
6427 				close(2);
6428 				dup(1);
6429 				i = 0;
6430 				cmdargs[i++] = cmd;
6431 				cmdargs[i++] = host;
6432 				cmdargs[i] = NULL;
6433 				execvp(cmd, cmdargs);
6434 				if (errno == ENOENT) {
6435 					strcpy(path, "/usr/local/sbin/");
6436 					strcat(path, cmd);
6437 					execv(path, cmdargs);
6438 				}
6439 				if (errno == ENOENT) {
6440 					strcpy(path, "/usr/local/bin/");
6441 					strcat(path, cmd);
6442 					execv(path, cmdargs);
6443 				}
6444 				if (errno == ENOENT) {
6445 					strcpy(path, "/usr/sbin/");
6446 					strcat(path, cmd);
6447 					execv(path, cmdargs);
6448 				}
6449 				if (errno == ENOENT) {
6450 					strcpy(path, "/sbin/");
6451 					strcat(path, cmd);
6452 					execv(path, cmdargs);
6453 				}
6454 				if (errno == ENOENT) {
6455 					strcpy(path, "/usr/etc/");
6456 					strcat(path, cmd);
6457 					execv(path, cmdargs);
6458 				}
6459 				perror("execvp failed");
6460 				fprintf(stderr, "failed to execute %s\n", cmd);
6461 				fflush(stdout);
6462 				fflush(stderr);
6463 				exit(0);
6464 			}
6465 		}
6466 		fprintf(stdout, "\n");
6467 		if (intr) {
6468 			intr = 0;
6469 			fprintf(stdout, "\n");
6470 			signal(SIGINT, sigint);
6471 		}
6472 		if (!skip_data) {
6473 			for ( stream_idx = 1; stream_idx <= nstream;
6474 					      stream_idx++ )
6475 				close(fd[stream_idx]);
6476 		}
6477 		if (client) {
6478 			if ((pid = fork()) == (pid_t)-1)
6479 				err("can't fork");
6480 			if (pid == 0) {
6481 				while (fgets(linebuf, sizeof(linebuf),
6482 					     stdin) && !intr) {
6483 					if (strncmp(linebuf, "DONE", 4)
6484 							== 0)
6485 						exit(0);
6486 					fputs(linebuf, stdout);
6487 					fflush(stdout);
6488 				}
6489 				exit(0);
6490 			}
6491 			signal(SIGINT, SIG_IGN);
6492 			while ((wait_pid = wait(&pidstat)) != pid) {
6493 				if (wait_pid == (pid_t)-1) {
6494 					if (errno == ECHILD)
6495 						break;
6496 					err("wait failed");
6497 				}
6498 			}
6499 			exit(0);
6500 		}
6501 		else {
6502 			if (!inetd) {
6503 				if ((pid = fork()) == (pid_t)-1)
6504 					err("can't fork");
6505 				if (pid != 0) {
6506 					while ((wait_pid = wait(&pidstat))
6507 							!= pid) {
6508 						if (wait_pid == (pid_t)-1) {
6509 							if (errno == ECHILD)
6510 								break;
6511 							err("wait failed");
6512 						}
6513 					}
6514 					fprintf(stdout, "DONE\n");
6515 					fflush(stdout);
6516 					goto cleanup;
6517 				}
6518 			}
6519 			close(2);
6520 			dup(1);
6521 			i = 0;
6522 			cmdargs[i++] = cmd;
6523 			cmdargs[i++] = host;
6524 			cmdargs[i] = NULL;
6525 			execvp(cmd, cmdargs);
6526 			if (errno == ENOENT) {
6527 				strcpy(path, "/usr/local/sbin/");
6528 				strcat(path, cmd);
6529 				execv(path, cmdargs);
6530 			}
6531 			if (errno == ENOENT) {
6532 				strcpy(path, "/usr/local/bin/");
6533 				strcat(path, cmd);
6534 				execv(path, cmdargs);
6535 			}
6536 			if (errno == ENOENT) {
6537 				strcpy(path, "/usr/sbin/");
6538 				strcat(path, cmd);
6539 				execv(path, cmdargs);
6540 			}
6541 			if (errno == ENOENT) {
6542 				strcpy(path, "/sbin/");
6543 				strcat(path, cmd);
6544 				execv(path, cmdargs);
6545 			}
6546 			if (errno == ENOENT) {
6547 				strcpy(path, "/usr/etc/");
6548 				strcat(path, cmd);
6549 				execv(path, cmdargs);
6550 			}
6551 			perror("execvp failed");
6552 			fprintf(stderr, "failed to execute %s\n", cmd);
6553 			fflush(stdout);
6554 			fflush(stderr);
6555 			if (!inetd)
6556 				exit(0);
6557 			goto cleanup;
6558 		}
6559 	}
6560 
6561 	if (multicast) {
6562 		struct sockaddr_in peer;
6563 		socklen_t peerlen = sizeof(peer);
6564 		struct sockaddr_in me;
6565 		socklen_t melen = sizeof(me);
6566 #ifdef AF_INET6
6567 		struct sockaddr_in6 peer6;
6568 		socklen_t peer6len = sizeof(peer6);
6569 		struct sockaddr_in6 me6;
6570 		socklen_t me6len = sizeof(me6);
6571 #endif
6572 		if (mc_addr && !client) {
6573 			bzero(&hints, sizeof(hints));
6574 			hints.ai_flags = AI_NUMERICHOST;
6575 			if (udp)
6576 				hints.ai_socktype = SOCK_DGRAM;
6577 			else
6578 				hints.ai_socktype = SOCK_STREAM;
6579 			mcres = NULL;
6580 			error_num = getaddrinfo(mc_addr, NULL, &hints, &mcres);
6581 			if (error_num) {
6582 				sprintf(tmpbuf, "getaddrinfo: "
6583 						"bad multicast IP address: "
6584 						"%s: %s",
6585 					mc_addr, gai_strerror(error_num));
6586 				errno = EINVAL;
6587 				err(tmpbuf);
6588 			}
6589 			if (mcres->ai_family == AF_INET) {
6590 				struct sockaddr_in *group;
6591 				struct in_addr ipv4_mcaddr;
6592 
6593 				group = (struct sockaddr_in *)mcres->ai_addr;
6594 				bcopy((char *)&(group->sin_addr),
6595 				      (char *)&ipv4_mcaddr,
6596 				      sizeof(struct in_addr));
6597 				if (ssm) {
6598 					if (((htonl(ipv4_mcaddr.s_addr)
6599 							& 0xFF000000) !=
6600 					     (HI_MC_SSM << 24))) {
6601 						sprintf(tmpbuf,
6602 							"bad SSM multicast "
6603 							"IP address: %s: "
6604 							"use 232.x.y.z",
6605 							mcgaddr);
6606 						errno = EINVAL;
6607 						err(tmpbuf);
6608 					}
6609 				}
6610 				else {
6611 					if (((htonl(ipv4_mcaddr.s_addr)
6612 							& 0xFF000000) !=
6613 					     (HI_MC << 24))) {
6614 						sprintf(tmpbuf,
6615 							"bad ASM multicast "
6616 							"IP address: %s: "
6617 							"use 231.x.y.z",
6618 							mcgaddr);
6619 						errno = EINVAL;
6620 						err(tmpbuf);
6621 					}
6622 				}
6623 			}
6624 #ifdef AF_INET6
6625 			if (mcres->ai_family == AF_INET6) {
6626 				struct sockaddr_in6 *group;
6627 
6628 				group = (struct sockaddr_in6 *)mcres->ai_addr;
6629 				if (ssm) {
6630 					if ((bcmp((char *)&(group->sin6_addr),
6631 						  (char *)&hi_mc6,
6632 						  HI_MC6_LEN - 1) != 0) ||
6633 					    (group->sin6_addr.s6_addr[HI_MC6_LEN - 1]
6634 							< 0x80)) {
6635 						sprintf(tmpbuf,
6636 							"bad SSM multicast "
6637 							"IP address: %s: use "
6638 							"ff3e::[8-f]xxx:yyyy",
6639 							mcgaddr);
6640 						errno = EINVAL;
6641 						err(tmpbuf);
6642 					}
6643 				}
6644 				else {
6645 					if ((bcmp((char *)&(group->sin6_addr),
6646 						  (char *)&hi_mc6_asm,
6647 						  HI_MC6_ASM_LEN) != 0)) {
6648 						sprintf(tmpbuf,
6649 							"bad ASM multicast "
6650 							"IP address: %s: use "
6651 							"ff2e::wwww:xxxx:"
6652 							      "yyyy:zzzz",
6653 							mcgaddr);
6654 						errno = EINVAL;
6655 						err(tmpbuf);
6656 					}
6657 				}
6658 			}
6659 #endif
6660 			mc_af = mcres->ai_family;
6661 		}
6662 
6663 		if (mc_af == AF_INET) {
6664 			if (getpeername(fd[0], (struct sockaddr *)&peer,
6665 					&peerlen) < 0) {
6666 				err("getpeername");
6667 			}
6668 			if (getsockname(fd[0], (struct sockaddr *)&me,
6669 					&melen) < 0) {
6670 				err("getsockname");
6671 			}
6672 		}
6673 #ifdef AF_INET6
6674 		else if (mc_af == AF_INET6) {
6675 			if (getpeername(fd[0], (struct sockaddr *)&peer6,
6676 					&peer6len) < 0) {
6677 				err("getpeername");
6678 			}
6679 			if (getsockname(fd[0], (struct sockaddr *)&me6,
6680 					&me6len) < 0) {
6681 				err("getsockname");
6682 			}
6683 		}
6684 #endif /* AF_INET6 */
6685 		else {
6686 			err("unsupported AF");
6687 		}
6688 
6689 		if (!trans) {
6690 		    if ((mc_af == AF_INET) && !ssm) { /* IPv4 ASM */
6691 			/* The multicast receiver must join the mc group */
6692 			if (mc_addr) {
6693 				struct sockaddr_in *user_group;
6694 
6695 				user_group =
6696 					(struct sockaddr_in *)mcres->ai_addr;
6697 				bcopy((char *)&(user_group->sin_addr.s_addr),
6698 				      (char *)&mc_group.imr_multiaddr.s_addr,
6699 				      sizeof(struct in_addr));
6700 			}
6701 			else if (client && (irvers >= 50505)) {
6702 				bcopy((char *)&me.sin_addr.s_addr,
6703 				      (char *)&mc_group.imr_multiaddr.s_addr,
6704 				      sizeof(struct in_addr));
6705 			}
6706 			else {
6707 				bcopy((char *)&peer.sin_addr.s_addr,
6708 				      (char *)&mc_group.imr_multiaddr.s_addr,
6709 				      sizeof(struct in_addr));
6710 			}
6711 			if (!mc_addr) {
6712 				mc_group.imr_multiaddr.s_addr &=
6713 					htonl(0xFFFFFF);
6714 				mc_group.imr_multiaddr.s_addr |=
6715 					htonl(HI_MC << 24);
6716 			}
6717 			if (setsockopt(fd[1], IPPROTO_IP, IP_ADD_MEMBERSHIP,
6718 				       (void *)&mc_group, sizeof(mc_group)) < 0)
6719 				err("setsockopt: IP_ADD_MEMBERSHIP");
6720 			if (brief <= 0) {
6721 				inet_ntop(mc_af, &peer.sin_addr.s_addr,
6722 					  multsrc, sizeof(multsrc));
6723 				inet_ntop(mc_af, &mc_group.imr_multiaddr,
6724 					  multaddr, sizeof(multaddr));
6725 
6726 				if (format & PARSE) {
6727 					fprintf(stdout,
6728 						"nuttcp%s%s: multicast_source=%s multicast_group=%s ssm=0\n",
6729 						trans?"-t":"-r", ident,
6730 						multsrc, multaddr);
6731 				}
6732 				else {
6733 					fprintf(stdout,
6734 						"nuttcp%s%s: receive from multicast source %s\n",
6735 						trans?"-t":"-r", ident,
6736 						multsrc);
6737 					fprintf(stdout,
6738 						"nuttcp%s%s: using asm on multicast group %s\n",
6739 						trans?"-t":"-r", ident,
6740 						multaddr);
6741 				}
6742 			}
6743 		    }
6744 #ifdef AF_INET6
6745 		    else if ((mc_af == AF_INET6) && !ssm) { /* IPv6 ASM */
6746 			/* The multicast receiver must join the mc group */
6747 			if (mc_addr) {
6748 				struct sockaddr_in6 *user_group;
6749 
6750 				user_group =
6751 					(struct sockaddr_in6 *)mcres->ai_addr;
6752 				bcopy((char *)&(user_group->sin6_addr),
6753 				      (char *)&mc6_group.ipv6mr_multiaddr,
6754 				      sizeof(struct in6_addr));
6755 			}
6756 			else if (client) {
6757 				bcopy((char *)&me6.sin6_addr,
6758 				      (char *)&mc6_group.ipv6mr_multiaddr,
6759 				      sizeof(struct in6_addr));
6760 			}
6761 			else {
6762 				bcopy((char *)&peer6.sin6_addr,
6763 				      (char *)&mc6_group.ipv6mr_multiaddr,
6764 				      sizeof(struct in6_addr));
6765 			}
6766 			if (!mc_addr) {
6767 				bcopy((char *)&hi_mc6_asm,
6768 				      (char *)&mc6_group.ipv6mr_multiaddr,
6769 				      HI_MC6_ASM_LEN);
6770 			}
6771 			if (setsockopt(fd[1], IPPROTO_IPV6, IPV6_JOIN_GROUP,
6772 				       (void *)&mc6_group,
6773 				       sizeof(mc6_group)) < 0)
6774 				err("setsockopt: IPV6_JOIN_GROUP");
6775 			if (brief <= 0) {
6776 				inet_ntop(mc_af, &peer6.sin6_addr,
6777 					  multsrc, sizeof(multsrc));
6778 				inet_ntop(mc_af, &mc6_group.ipv6mr_multiaddr,
6779 					  multaddr, sizeof(multaddr));
6780 
6781 				if (format & PARSE) {
6782 					fprintf(stdout,
6783 						"nuttcp%s%s: multicast_source=%s multicast_group=%s ssm=0\n",
6784 						trans?"-t":"-r", ident,
6785 						multsrc, multaddr);
6786 				}
6787 				else {
6788 					fprintf(stdout,
6789 						"nuttcp%s%s: receive from multicast source %s\n",
6790 						trans?"-t":"-r", ident,
6791 						multsrc);
6792 					fprintf(stdout,
6793 						"nuttcp%s%s: using asm on multicast group %s\n",
6794 						trans?"-t":"-r", ident,
6795 						multaddr);
6796 				}
6797 			}
6798 		    }
6799 #endif /* AF_INET6 */
6800 #ifdef MCAST_JOIN_SOURCE_GROUP
6801 		    else if ((mc_af == AF_INET) && ssm) { /* IPv4 SSM */
6802 			/* multicast receiver joins the mc source group */
6803 			union sockaddr_union group_ipaddr;
6804 			struct sockaddr_in *group;
6805 			struct sockaddr_in *source;
6806 
6807 			group = &group_ipaddr.sin;
6808 			source =
6809 			    (struct sockaddr_in *)&group_source_req.gsr_source;
6810 			group_source_req.gsr_interface = 0;  /* any interface */
6811 			if (mc_addr) {
6812 				struct sockaddr_in *user_group;
6813 
6814 				user_group =
6815 					(struct sockaddr_in *)mcres->ai_addr;
6816 				bcopy((char *)user_group, (char *)group,
6817 				      sizeof(struct sockaddr_in));
6818 			}
6819 			else if (client) {
6820 				bcopy((char *)&me, (char *)group,
6821 				      sizeof(struct sockaddr_in));
6822 			}
6823 			else {
6824 				bcopy((char *)&peer, (char *)group,
6825 				      sizeof(struct sockaddr_in));
6826 			}
6827 			bcopy((char *)&peer, (char *)source,
6828 			      sizeof(struct sockaddr_in));
6829 			if (!mc_addr) {
6830 				group->sin_addr.s_addr &= htonl(0xFFFFFF);
6831 				group->sin_addr.s_addr |=
6832 					htonl(HI_MC_SSM << 24);
6833 			}
6834 			group_source_req.gsr_group = group_ipaddr.ss;
6835 			if (setsockopt(fd[1], IPPROTO_IP,
6836 				       MCAST_JOIN_SOURCE_GROUP,
6837 				       &group_source_req,
6838 				       sizeof(group_source_req)) < 0)
6839 				err("setsockopt: MCAST_JOIN_SOURCE_GROUP");
6840 			if (brief <= 0) {
6841 				inet_ntop(mc_af, &source->sin_addr.s_addr,
6842 					  multsrc, sizeof(multsrc));
6843 				inet_ntop(mc_af, &group->sin_addr.s_addr,
6844 					  multaddr, sizeof(multaddr));
6845 				if (format & PARSE) {
6846 					fprintf(stdout,
6847 						"nuttcp%s%s: multicast_source=%s multicast_group=%s ssm=1\n",
6848 						trans?"-t":"-r", ident,
6849 						multsrc, multaddr);
6850 				}
6851 				else {
6852 					fprintf(stdout,
6853 						"nuttcp%s%s: receive from multicast source %s\n",
6854 						trans?"-t":"-r", ident,
6855 						multsrc);
6856 					fprintf(stdout,
6857 						"nuttcp%s%s: using ssm on multicast group %s\n",
6858 						trans?"-t":"-r", ident,
6859 						multaddr);
6860 				}
6861 			}
6862 		    }
6863 #ifdef AF_INET6
6864 		    else if ((mc_af == AF_INET6) && ssm) { /* IPv6 SSM */
6865 			/* multicast receiver joins the mc source group */
6866 			struct sockaddr_in6 *group;
6867 			struct sockaddr_in6 *source;
6868 
6869 			group =
6870 			    (struct sockaddr_in6 *)&group_source_req.gsr_group;
6871 			source =
6872 			    (struct sockaddr_in6 *)&group_source_req.gsr_source;
6873 			group_source_req.gsr_interface = 0;  /* any interface */
6874 			if (mc_addr) {
6875 				struct sockaddr_in6 *user_group;
6876 
6877 				user_group =
6878 					(struct sockaddr_in6 *)mcres->ai_addr;
6879 				bcopy((char *)user_group, (char *)group,
6880 				      sizeof(struct sockaddr_in6));
6881 			}
6882 			else if (client) {
6883 				bcopy((char *)&me6, (char *)group,
6884 				      sizeof(struct sockaddr_in6));
6885 			}
6886 			else {
6887 				bcopy((char *)&peer6, (char *)group,
6888 				      sizeof(struct sockaddr_in6));
6889 			}
6890 			bcopy((char *)&peer6, (char *)source,
6891 			      sizeof(struct sockaddr_in6));
6892 			if (!mc_addr) {
6893 				bcopy((char *)&hi_mc6,
6894 				      (char *)&group->sin6_addr,
6895 				      HI_MC6_LEN);
6896 			}
6897 			if (setsockopt(fd[1], IPPROTO_IPV6,
6898 				       MCAST_JOIN_SOURCE_GROUP,
6899 				       &group_source_req,
6900 				       sizeof(group_source_req)) < 0)
6901 				err("setsockopt: MCAST_JOIN_SOURCE_GROUP");
6902 			if (brief <= 0) {
6903 				inet_ntop(mc_af, &source->sin6_addr.s6_addr,
6904 					  multsrc, sizeof(multsrc));
6905 				inet_ntop(mc_af, &group->sin6_addr.s6_addr,
6906 					  multaddr, sizeof(multaddr));
6907 				if (format & PARSE) {
6908 					fprintf(stdout,
6909 						"nuttcp%s%s: multicast_source=%s multicast_group=%s ssm=1\n",
6910 						trans?"-t":"-r", ident,
6911 						multsrc, multaddr);
6912 				}
6913 				else {
6914 					fprintf(stdout,
6915 						"nuttcp%s%s: receive from multicast source %s\n",
6916 						trans?"-t":"-r", ident,
6917 						multsrc);
6918 					fprintf(stdout,
6919 						"nuttcp%s%s: using ssm on multicast group %s\n",
6920 						trans?"-t":"-r", ident,
6921 						multaddr);
6922 				}
6923 			}
6924 		    }
6925 #endif /* AF_INET6 */
6926 #endif /* MCAST_JOIN_SOURCE_GROUP */
6927 		    else {
6928 			err("unsupported AF");
6929 		    }
6930 		}
6931 		else { /* trans */
6932 		    if (mc_af == AF_INET) {
6933 			bcopy((char *)&sinhim[1].sin_addr.s_addr,
6934 			      (char *)&save_sinhim.sin_addr.s_addr,
6935 			      sizeof(struct in_addr));
6936 		    }
6937 #ifdef AF_INET6
6938 		    else if (mc_af == AF_INET6) {
6939 			bcopy((char *)&sinhim6[1], (char *)&save_sinhim6,
6940 			      sizeof(struct sockaddr_in6));
6941 		    }
6942 #endif
6943 		    if ((mc_af == AF_INET) && !ssm) { /* IPv4 ASM */
6944 			/* The multicast transmitter just sends to mc group */
6945 			if (mc_addr) {
6946 				struct sockaddr_in *user_group;
6947 
6948 				user_group =
6949 					(struct sockaddr_in *)mcres->ai_addr;
6950 				bcopy((char *)&(user_group->sin_addr.s_addr),
6951 				      (char *)&sinhim[1].sin_addr.s_addr,
6952 				      sizeof(struct in_addr));
6953 			}
6954 			else if (client || (irvers < 50505)) {
6955 				bcopy((char *)&me.sin_addr.s_addr,
6956 				      (char *)&sinhim[1].sin_addr.s_addr,
6957 				      sizeof(struct in_addr));
6958 			}
6959 			else {
6960 				bcopy((char *)&peer.sin_addr.s_addr,
6961 				      (char *)&sinhim[1].sin_addr.s_addr,
6962 				      sizeof(struct in_addr));
6963 			}
6964 			if (!mc_addr) {
6965 				sinhim[1].sin_addr.s_addr &= htonl(0xFFFFFF);
6966 				sinhim[1].sin_addr.s_addr |= htonl(HI_MC << 24);
6967 			}
6968 			if (setsockopt(fd[1], IPPROTO_IP, IP_MULTICAST_TTL,
6969 				       (void *)&multicast,
6970 				       sizeof(multicast)) < 0)
6971 				err("setsockopt: IP_MULTICAST_TTL");
6972 			if (brief <= 0) {
6973 				inet_ntop(mc_af, &me.sin_addr.s_addr,
6974 					  multsrc, sizeof(multsrc));
6975 				inet_ntop(mc_af, &sinhim[1].sin_addr.s_addr,
6976 					  multaddr, sizeof(multaddr));
6977 				if (format & PARSE) {
6978 					fprintf(stdout,
6979 						"nuttcp%s%s: multicast_source=%s multicast_group=%s ssm=0\n",
6980 						trans?"-t":"-r", ident,
6981 						multsrc, multaddr);
6982 				}
6983 				else {
6984 					fprintf(stdout,
6985 						"nuttcp%s%s: sending from multicast source %s\n",
6986 						trans?"-t":"-r", ident,
6987 						multsrc);
6988 					fprintf(stdout,
6989 						"nuttcp%s%s: using asm on multicast group %s\n",
6990 						trans?"-t":"-r", ident,
6991 						multaddr);
6992 				}
6993 			}
6994 		    }
6995 #ifdef AF_INET6
6996 		    else if ((mc_af == AF_INET6) && !ssm) { /* IPv6 ASM */
6997 			/* The multicast transmitter just sends to mc group */
6998 			if (mc_addr) {
6999 				struct sockaddr_in6 *user_group;
7000 
7001 				user_group =
7002 					(struct sockaddr_in6 *)mcres->ai_addr;
7003 				bcopy((char *)&(user_group->sin6_addr),
7004 				      (char *)&sinhim6[1].sin6_addr,
7005 				      sizeof(struct in6_addr));
7006 			}
7007 			else if (client) {
7008 				bcopy((char *)&me6.sin6_addr,
7009 				      (char *)&sinhim6[1].sin6_addr,
7010 				      sizeof(struct in6_addr));
7011 			}
7012 			else {
7013 				bcopy((char *)&peer6.sin6_addr,
7014 				      (char *)&sinhim6[1].sin6_addr,
7015 				      sizeof(struct in6_addr));
7016 			}
7017 			if (!mc_addr) {
7018 				bcopy((char *)&hi_mc6_asm,
7019 				      (char *)&sinhim6[1].sin6_addr,
7020 				      HI_MC6_ASM_LEN);
7021 			}
7022 			if (setsockopt(fd[1], IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
7023 				       (void *)&multicast,
7024 				       sizeof(multicast)) < 0)
7025 				err("setsockopt: IPV6_MULTICAST_HOPS");
7026 			if (brief <= 0) {
7027 				inet_ntop(mc_af, &me6.sin6_addr.s6_addr,
7028 					  multsrc, sizeof(multsrc));
7029 				inet_ntop(mc_af, &sinhim6[1].sin6_addr.s6_addr,
7030 					  multaddr, sizeof(multaddr));
7031 				if (format & PARSE) {
7032 					fprintf(stdout,
7033 						"nuttcp%s%s: multicast_source=%s multicast_group=%s ssm=0\n",
7034 						trans?"-t":"-r", ident,
7035 						multsrc, multaddr);
7036 				}
7037 				else {
7038 					fprintf(stdout,
7039 						"nuttcp%s%s: sending from multicast source %s\n",
7040 						trans?"-t":"-r", ident,
7041 						multsrc);
7042 					fprintf(stdout,
7043 						"nuttcp%s%s: using asm on multicast group %s\n",
7044 						trans?"-t":"-r", ident,
7045 						multaddr);
7046 				}
7047 			}
7048 		    }
7049 #endif /* AF_INET6 */
7050 #ifdef MCAST_JOIN_SOURCE_GROUP
7051 		    else if ((mc_af == AF_INET) && ssm) { /* IPv4 SSM */
7052 			/* The multicast transmitter just sends to mc group */
7053 			if (mc_addr) {
7054 				struct sockaddr_in *user_group;
7055 
7056 				user_group =
7057 					(struct sockaddr_in *)mcres->ai_addr;
7058 				bcopy((char *)&(user_group->sin_addr.s_addr),
7059 				      (char *)&sinhim[1].sin_addr.s_addr,
7060 				      sizeof(struct in_addr));
7061 			}
7062 			else if (client) {
7063 				bcopy((char *)&me.sin_addr.s_addr,
7064 				      (char *)&sinhim[1].sin_addr.s_addr,
7065 				      sizeof(struct in_addr));
7066 			}
7067 			else {
7068 				bcopy((char *)&peer.sin_addr.s_addr,
7069 				      (char *)&sinhim[1].sin_addr.s_addr,
7070 				      sizeof(struct in_addr));
7071 			}
7072 			if (!mc_addr) {
7073 				sinhim[1].sin_addr.s_addr &= htonl(0xFFFFFF);
7074 				sinhim[1].sin_addr.s_addr |=
7075 					htonl(HI_MC_SSM << 24);
7076 			}
7077 			if (setsockopt(fd[1], IPPROTO_IP, IP_MULTICAST_TTL,
7078 				       (void *)&multicast,
7079 				       sizeof(multicast)) < 0)
7080 				err("setsockopt: IP_MULTICAST_TTL");
7081 			if (brief <= 0) {
7082 				inet_ntop(mc_af, &me.sin_addr.s_addr,
7083 					  multsrc, sizeof(multsrc));
7084 				inet_ntop(mc_af, &sinhim[1].sin_addr.s_addr,
7085 					  multaddr, sizeof(multaddr));
7086 				if (format & PARSE) {
7087 					fprintf(stdout,
7088 						"nuttcp%s%s: multicast_source=%s multicast_group=%s ssm=1\n",
7089 						trans?"-t":"-r", ident,
7090 						multsrc, multaddr);
7091 				}
7092 				else {
7093 					fprintf(stdout,
7094 						"nuttcp%s%s: sending from multicast source %s\n",
7095 						trans?"-t":"-r", ident,
7096 						multsrc);
7097 					fprintf(stdout,
7098 						"nuttcp%s%s: using ssm on multicast group %s\n",
7099 						trans?"-t":"-r", ident,
7100 						multaddr);
7101 				}
7102 			}
7103 		    }
7104 #ifdef AF_INET6
7105 		    else if ((mc_af == AF_INET6) && ssm) { /* IPv6 SSM */
7106 			/* The multicast transmitter just sends to mc group */
7107 			if (mc_addr) {
7108 				struct sockaddr_in6 *user_group;
7109 
7110 				user_group =
7111 					(struct sockaddr_in6 *)mcres->ai_addr;
7112 				bcopy((char *)&(user_group->sin6_addr),
7113 				      (char *)&sinhim6[1].sin6_addr,
7114 				      sizeof(struct in6_addr));
7115 			}
7116 			else if (client) {
7117 				bcopy((char *)&me6.sin6_addr,
7118 				      (char *)&sinhim6[1].sin6_addr,
7119 				      sizeof(struct in6_addr));
7120 			}
7121 			else {
7122 				bcopy((char *)&peer6.sin6_addr,
7123 				      (char *)&sinhim6[1].sin6_addr,
7124 				      sizeof(struct in6_addr));
7125 			}
7126 			if (!mc_addr) {
7127 				bcopy((char *)&hi_mc6,
7128 				      (char *)&sinhim6[1].sin6_addr,
7129 				      HI_MC6_LEN);
7130 			}
7131 			if (setsockopt(fd[1], IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
7132 				       (void *)&multicast,
7133 				       sizeof(multicast)) < 0)
7134 				err("setsockopt: IPV6_MULTICAST_HOPS");
7135 			if (brief <= 0) {
7136 				inet_ntop(mc_af, &me6.sin6_addr.s6_addr,
7137 					  multsrc, sizeof(multsrc));
7138 				inet_ntop(mc_af, &sinhim6[1].sin6_addr.s6_addr,
7139 					  multaddr, sizeof(multaddr));
7140 				if (format & PARSE) {
7141 					fprintf(stdout,
7142 						"nuttcp%s%s: multicast_source=%s multicast_group=%s ssm=1\n",
7143 						trans?"-t":"-r", ident,
7144 						multsrc, multaddr);
7145 				}
7146 				else {
7147 					fprintf(stdout,
7148 						"nuttcp%s%s: sending from multicast source %s\n",
7149 						trans?"-t":"-r", ident,
7150 						multsrc);
7151 					fprintf(stdout,
7152 						"nuttcp%s%s: using ssm on multicast group %s\n",
7153 						trans?"-t":"-r", ident,
7154 						multaddr);
7155 				}
7156 			}
7157 		    }
7158 #endif /* AF_INET6 */
7159 #endif /* MCAST_JOIN_SOURCE_GROUP */
7160 		    else {
7161 			err("unsupported AF");
7162 		    }
7163 		}
7164 
7165 		if (mcres) {
7166 			freeaddrinfo(mcres);
7167 			mcres = NULL;
7168 		}
7169 	}
7170 
7171 	if (trans && timeout) {
7172 		itimer.it_value.tv_sec = timeout;
7173 		itimer.it_value.tv_usec =
7174 			(timeout - itimer.it_value.tv_sec)*1000000;
7175 		itimer.it_interval.tv_sec = 0;
7176 		itimer.it_interval.tv_usec = 0;
7177 		signal(SIGALRM, sigalarm);
7178 		if (!udp)
7179 			setitimer(ITIMER_REAL, &itimer, 0);
7180 	}
7181 	else if (!trans && interval) {
7182 		sigact.sa_handler = &sigalarm;
7183 		sigemptyset(&sigact.sa_mask);
7184 		sigact.sa_flags = SA_RESTART;
7185 		sigaction(SIGALRM, &sigact, 0);
7186 		itimer.it_value.tv_sec = interval;
7187 		itimer.it_value.tv_usec =
7188 			(interval - itimer.it_value.tv_sec)*1000000;
7189 		itimer.it_interval.tv_sec = interval;
7190 		itimer.it_interval.tv_usec =
7191 			(interval - itimer.it_interval.tv_sec)*1000000;
7192 		setitimer(ITIMER_REAL, &itimer, 0);
7193 		if (clientserver) {
7194 			chk_idle_data = (interval < idle_data_min) ?
7195 						idle_data_min : interval;
7196 			chk_idle_data = (chk_idle_data > idle_data_max) ?
7197 						idle_data_max : chk_idle_data;
7198 		}
7199 	}
7200 	else if (clientserver && !trans) {
7201 		sigact.sa_handler = &sigalarm;
7202 		sigemptyset(&sigact.sa_mask);
7203 		sigact.sa_flags = SA_RESTART;
7204 		sigaction(SIGALRM, &sigact, 0);
7205 		if (timeout) {
7206 			chk_idle_data = timeout/2;
7207 		}
7208 		else {
7209 			if (rate != MAXRATE)
7210 				chk_idle_data = (double)(nbuf*buflen)
7211 							    /rate/125/2;
7212 			else
7213 				chk_idle_data = default_idle_data;
7214 		}
7215 		chk_idle_data = (chk_idle_data < idle_data_min) ?
7216 					idle_data_min : chk_idle_data;
7217 		chk_idle_data = (chk_idle_data > idle_data_max) ?
7218 					idle_data_max : chk_idle_data;
7219 		itimer.it_value.tv_sec = chk_idle_data;
7220 		itimer.it_value.tv_usec =
7221 			(chk_idle_data - itimer.it_value.tv_sec)
7222 				*1000000;
7223 		itimer.it_interval.tv_sec = chk_idle_data;
7224 		itimer.it_interval.tv_usec =
7225 			(chk_idle_data - itimer.it_interval.tv_sec)
7226 				*1000000;
7227 		setitimer(ITIMER_REAL, &itimer, 0);
7228 	}
7229 
7230 	if (interval && clientserver && client && trans)
7231 		do_poll = 1;
7232 
7233 	if (irate) {
7234 		pkt_time = (double)buflen/rate/125;
7235 		irate_pk_usec = pkt_time*1000000;
7236 		irate_pk_nsec = (pkt_time*1000000 - irate_pk_usec)*1000;
7237 		pkt_time_ms = pkt_time*1000;
7238 	}
7239 #ifdef DEBUG
7240 	if (irate && (format & DEBUGIRATE)) {
7241 		debugout = fopen(DEBUGOUTPUT, "a+");
7242 		if (debugout)
7243 			fprintf(debugout, "BEGIN nuttcp debug output\n");
7244 	}
7245 #endif
7246 	prep_timer();
7247 	errno = 0;
7248 	stream_idx = 0;
7249 	ocorrection = 0;
7250 	correction = 0.0;
7251 	if (do_poll) {
7252 		long flags;
7253 
7254 		pollfds[0].fd = fileno(ctlconn);
7255 		pollfds[0].events = POLLIN | POLLPRI;
7256 		pollfds[0].revents = 0;
7257 		for ( i = 1; i <= nstream; i++ ) {
7258 			pollfds[i].fd = fd[i];
7259 			pollfds[i].events = POLLOUT;
7260 			pollfds[i].revents = 0;
7261 		}
7262 		flags = fcntl(0, F_GETFL, 0);
7263 		if (flags < 0)
7264 			err("fcntl 1");
7265 		flags |= O_NONBLOCK;
7266 		if (fcntl(0, F_SETFL, flags) < 0)
7267 			err("fcntl 2");
7268 	}
7269 	if (sinkmode) {
7270 		register int cnt = 0;
7271 		if (trans) {
7272 			if (udp) {
7273 				strcpy(buf, "BOD0");
7274 				if (multicast) {
7275 				    bcopy((char *)&sinhim[1].sin_addr.s_addr,
7276 					  (char *)&save_mc.sin_addr.s_addr,
7277 					  sizeof(struct in_addr));
7278 				    bcopy((char *)&save_sinhim.sin_addr.s_addr,
7279 					  (char *)&sinhim[1].sin_addr.s_addr,
7280 					  sizeof(struct in_addr));
7281 				}
7282 				(void)Nwrite( fd[stream_idx + 1], buf, 4 ); /* rcvr start */
7283 				if (two_bod) {
7284 					usleep(250000);
7285 					strcpy(buf, "BOD1");
7286 					(void)Nwrite( fd[stream_idx + 1], buf, 4 ); /* rcvr start */
7287 				}
7288 				if (multicast) {
7289 				    bcopy((char *)&save_mc.sin_addr.s_addr,
7290 					  (char *)&sinhim[1].sin_addr.s_addr,
7291 					  sizeof(struct in_addr));
7292 				}
7293 				if (timeout)
7294 					setitimer(ITIMER_REAL, &itimer, 0);
7295 				prep_timer();
7296 			}
7297 			bzero(buf + 8, 8);	/* zero out timestamp */
7298 			nbytes += buflen;
7299 			if (do_poll && (format & DEBUGPOLL)) {
7300 				fprintf(stdout, "do_poll is set\n");
7301 				fflush(stdout);
7302 			}
7303 			if (udplossinfo)
7304 				bcopy(&nbytes, buf + 24, 8);
7305 			if (!udp && !(format & NORETRANS) &&
7306 			    (nstream == 1) &&
7307 			    ((retransinfo == 1) ||
7308 			     ((retransinfo >= 2) &&
7309 			      (force_retrans >= retransinfo)))) {
7310 				uint32_t tmp;
7311 
7312 				if (client) {
7313 					if (trans || send_retrans)
7314 						do_retrans = 1;
7315 					if (trans)
7316 						send_retrans = 1;
7317 					if (!udp)
7318 						bzero(buf + 24, 8);
7319 				}
7320 				else {
7321 					if (retransinfo == 1)
7322 						tmp = 0x5254524Eu;  /* "RTRN" */
7323 					else
7324 						tmp = 0x48525452u;  /* "HRTR" */
7325 					bcopy(&nretrans[1], buf + 24, 4);
7326 					bcopy(&tmp, buf + 28, 4);
7327 					do_retrans = 0;
7328 				}
7329 			}
7330 			else {
7331 				send_retrans = 0;
7332 				do_retrans = 0;
7333 				if (!udp)
7334 					bzero(buf + 24, 8);
7335 			}
7336 			if (!udp && !(format & NOCWND) &&
7337 			    (nstream == 1) && cwndinfo) {
7338 				if (client) {
7339 					if (trans || send_cwnd)
7340 						do_cwnd = 1;
7341 					if (trans)
7342 						send_cwnd = 1;
7343 				}
7344 				else {
7345 					do_cwnd = 0;
7346 				}
7347 			}
7348 			else {
7349 				send_cwnd = 0;
7350 				do_cwnd = 0;
7351 			}
7352 			if (nbuf == INT_MAX)
7353 				nbuf = ULLONG_MAX;
7354 			if (!client) {
7355 				/* check if client went away */
7356 				pollfds[0].fd = fileno(ctlconn);
7357 				save_events = pollfds[0].events;
7358 				pollfds[0].events = POLLIN | POLLPRI;
7359 				pollfds[0].revents = 0;
7360 				if ((poll(pollfds, 1, 0) > 0) &&
7361 				    (pollfds[0].revents & (POLLIN | POLLPRI))) {
7362 					nbuf = 0;
7363 					intr = 1;
7364 				}
7365 				pollfds[0].events = save_events;
7366 			}
7367 			while (nbuf-- && ((cnt = Nwrite(fd[stream_idx + 1], buf, buflen)) == buflen) && !intr) {
7368 				if (clientserver && ((nbuf & 0x3FF) == 0)) {
7369 				    if (!client) {
7370 					/* check if client went away */
7371 					pollfds[0].fd = fileno(ctlconn);
7372 					save_events = pollfds[0].events;
7373 					pollfds[0].events = POLLIN | POLLPRI;
7374 					pollfds[0].revents = 0;
7375 					if ((poll(pollfds, 1, 0) > 0)
7376 						&& (pollfds[0].revents &
7377 							(POLLIN | POLLPRI)))
7378 						intr = 1;
7379 					pollfds[0].events = save_events;
7380 				    }
7381 				    else if (handle_urg) {
7382 					/* check for urgent TCP data
7383 					 * on control connection */
7384 					pollfds[0].fd = fileno(ctlconn);
7385 					save_events = pollfds[0].events;
7386 					pollfds[0].events = POLLPRI;
7387 					pollfds[0].revents = 0;
7388 					if ((poll(pollfds, 1, 0) > 0)
7389 						&& (pollfds[0].revents &
7390 							POLLPRI)) {
7391 						tmpbuf[0] = '\0';
7392 						if ((recv(fd[0], tmpbuf, 1,
7393 							  MSG_OOB) == -1) &&
7394 						    (errno == EINVAL))
7395 							recv(fd[0], tmpbuf,
7396 							     1, 0);
7397 						if (tmpbuf[0] == 'A')
7398 							intr = 1;
7399 						else
7400 							err("recv urgent data");
7401 					}
7402 					pollfds[0].events = save_events;
7403 				    }
7404 				}
7405 				nbytes += buflen;
7406 				cnt = 0;
7407 				if (udplossinfo)
7408 					bcopy(&nbytes, buf + 24, 8);
7409 				if (send_retrans) {
7410 					nretrans[1] = get_retrans(
7411 							fd[stream_idx + 1],
7412 							&tcpinf);
7413 					nretrans[1] -= iretrans[1];
7414 					bcopy(&nretrans[1], buf + 24, 4);
7415 				}
7416 #if defined(linux)
7417 				if (send_cwnd) {
7418 					cwnd[1] = tcpinf.tcpinfo_snd_cwnd
7419 							*datamss/1024;
7420 					bcopy(&cwnd[1], buf + 28, 4);
7421 				}
7422 #endif
7423 				stream_idx++;
7424 				stream_idx = stream_idx % nstream;
7425 				if (do_poll &&
7426 				       ((pollst = poll(pollfds, nstream + 1, 0))
7427 						> 0) &&
7428 				       (pollfds[0].revents & (POLLIN | POLLPRI)) && !intr) {
7429 					/* check for server output */
7430 #ifdef DEBUG
7431 					if (format & DEBUGPOLL) {
7432 						fprintf(stdout, "got something %d: ", i);
7433 				    for ( i = 0; i < nstream + 1; i++ ) {
7434 					if (pollfds[i].revents & POLLIN) {
7435 						fprintf(stdout, " rfd %d",
7436 							pollfds[i].fd);
7437 					}
7438 					if (pollfds[i].revents & POLLPRI) {
7439 						fprintf(stdout, " pfd %d",
7440 							pollfds[i].fd);
7441 					}
7442 					if (pollfds[i].revents & POLLOUT) {
7443 						fprintf(stdout, " wfd %d",
7444 							pollfds[i].fd);
7445 					}
7446 					if (pollfds[i].revents & POLLERR) {
7447 						fprintf(stdout, " xfd %d",
7448 							pollfds[i].fd);
7449 					}
7450 					if (pollfds[i].revents & POLLHUP) {
7451 						fprintf(stdout, " hfd %d",
7452 							pollfds[i].fd);
7453 					}
7454 					if (pollfds[i].revents & POLLNVAL) {
7455 						fprintf(stdout, " nfd %d",
7456 							pollfds[i].fd);
7457 					}
7458 				    }
7459 						fprintf(stdout, "\n");
7460 						fflush(stdout);
7461 				    }
7462 					if (format & DEBUGPOLL) {
7463 						fprintf(stdout, "got server output: %s", intervalbuf);
7464 						fflush(stdout);
7465 					}
7466 #endif
7467 					while (fgets(intervalbuf, sizeof(intervalbuf), stdin))
7468 					{
7469 					if (strncmp(intervalbuf, "DONE", 4) == 0) {
7470 						if (format & DEBUGPOLL) {
7471 							fprintf(stdout, "got DONE\n");
7472 							fflush(stdout);
7473 						}
7474 						got_done = 1;
7475 						intr = 1;
7476 						do_poll = 0;
7477 						break;
7478 					}
7479 					else if (strncmp(intervalbuf, "nuttcp-r", 8) == 0) {
7480 						if ((brief <= 0) ||
7481 						    strstr(intervalbuf,
7482 							    "Warning") ||
7483 						    strstr(intervalbuf,
7484 							    "Error") ||
7485 						    strstr(intervalbuf,
7486 							    "Debug")) {
7487 							if (*ident) {
7488 								fputs("nuttcp-r", stdout);
7489 								fputs(ident, stdout);
7490 								fputs(intervalbuf + 8, stdout);
7491 							}
7492 							else
7493 								fputs(intervalbuf, stdout);
7494 							fflush(stdout);
7495 						}
7496 					}
7497 					else {
7498 						if (*ident)
7499 							fprintf(stdout, "%s: ", ident + 1);
7500 						cp1 = intervalbuf +
7501 							strlen(intervalbuf) - 1;
7502 						/* ugly kludge to get rid of
7503 						 * server "0 retrans" info at
7504 						 * start of transfer for small
7505 						 * interval reports -
7506 						 * hopefully it won't be
7507 						 * necessary to also check
7508 						 * at end of transfer when
7509 						 * processing server output */
7510 						if (!got_0retrans) {
7511 						    if (format & PARSE) {
7512 							if ((cp2 = strstr(
7513 								    intervalbuf,
7514 								    "host-"
7515 								    "retrans")))
7516 							    *(cp2 - 1) = '\0';
7517 							else if ((cp2 = strstr(
7518 								    intervalbuf,
7519 								    "retrans")))
7520 							    *(cp2 - 1) = '\0';
7521 							else {
7522 							    *cp1 = '\0';
7523 							    got_0retrans = 1;
7524 							}
7525 						    }
7526 						    else if (strstr(intervalbuf,
7527 								   "KB-cwnd")) {
7528 							if (strstr(intervalbuf,
7529 								"host-retrans"))
7530 							    *(cp1 - 34) = '\0';
7531 							else if (strstr(
7532 								    intervalbuf,
7533 								    "retrans"))
7534 							    *(cp1 - 29) = '\0';
7535 							else {
7536 							    *cp1 = '\0';
7537 							    got_0retrans = 1;
7538 							}
7539 						    }
7540 						    else {
7541 							if (strstr(intervalbuf,
7542 								"host-retrans"))
7543 							    *(cp1 - 19) = '\0';
7544 							else if (strstr(
7545 								    intervalbuf,
7546 								    "retrans"))
7547 							    *(cp1 - 14) = '\0';
7548 							else {
7549 							    *cp1 = '\0';
7550 							    got_0retrans = 1;
7551 							}
7552 						    }
7553 						}
7554 						else {
7555 						    *cp1 = '\0';
7556 						}
7557 						if (do_retrans) {
7558 						    cp1 = strstr(intervalbuf,
7559 								 "Mbps") + 4;
7560 						    ch = '\0';
7561 						    if (cp1) {
7562 							if (format & PARSE) {
7563 							    cp1 = strchr(cp1,
7564 									 '.');
7565 							    if (cp1)
7566 								cp1 += 5;
7567 							}
7568 							ch = *cp1;
7569 						    }
7570 						    if (ch)
7571 							*cp1 = '\0';
7572 						}
7573 						fputs(intervalbuf, stdout);
7574 						if (do_retrans && sinkmode) {
7575 						    nretrans[1] =
7576 						      get_retrans(fd[stream_idx
7577 									+ 1],
7578 								  &tcpinf);
7579 						    nretrans[1] -= iretrans[1];
7580 						    if (format & PARSE)
7581 							fprintf(stdout,
7582 							 P_RETRANS_FMT_INTERVAL,
7583 							   (retransinfo == 1) ?
7584 								"" : "host-",
7585 							   (nretrans[1] -
7586 								pretrans));
7587 						    else
7588 							fprintf(stdout,
7589 							 RETRANS_FMT_INTERVAL,
7590 							   (nretrans[1] -
7591 								pretrans),
7592 							   (retransinfo == 1) ?
7593 								"" : "host-");
7594 						    pretrans = nretrans[1];
7595 						}
7596 #if defined(linux)
7597 						if (do_cwnd && sinkmode) {
7598 						    cwnd[1] =
7599 						        tcpinf.tcpinfo_snd_cwnd
7600 								*datamss/1024;
7601 						    if (format & PARSE)
7602 							fprintf(stdout,
7603 							    P_CWND_FMT_INTERVAL,
7604 							    cwnd[1]);
7605 						    else
7606 							fprintf(stdout,
7607 							    CWND_FMT_INTERVAL,
7608 							    cwnd[1]);
7609 						}
7610 #endif
7611 						if (do_retrans && cp1 && ch) {
7612 						    *cp1 = ch;
7613 						    fputs(cp1, stdout);
7614 						}
7615 						fprintf(stdout, "\n");
7616 						fflush(stdout);
7617 					}
7618 					}
7619 				}
7620 				if (do_poll && (pollst < 0)) {
7621 					if (errno == EINTR)
7622 						break;
7623 					err("poll");
7624 				}
7625 			}
7626 			nbytes -= buflen;
7627 			if (intr && (cnt > 0))
7628 				nbytes += cnt;
7629 			if (udp) {
7630 				if (multicast)
7631 				    bcopy((char *)&save_sinhim.sin_addr.s_addr,
7632 					  (char *)&sinhim[1].sin_addr.s_addr,
7633 					  sizeof(struct in_addr));
7634 				strcpy(buf, "EOD0");
7635 				(void)Nwrite( fd[stream_idx + 1], buf, 4 ); /* rcvr end */
7636 			}
7637 		}
7638 		else {
7639 			first_read = 1;
7640 			first_jitter = 1;
7641 			first_jitteri = 1;
7642 			nowd = 0;
7643 			nowdi = 0;
7644 			owd_min = 1000000.0;
7645 			owd_mini = 1000000.0;
7646 			owd_max = -1000000.0;
7647 			owd_maxi = -1000000.0;
7648 			owd_avg = 0.0;
7649 			owd_avgi = 0.0;
7650 			need_swap = 0;
7651 			bzero(buf + 24, 8);
7652 			if (udp) {
7653 			    ntbytesc = 0;
7654 			    got_eod0 = 0;
7655 			    while (((cnt=Nread(fd[stream_idx + 1], buf, buflen)) > 0) && !intr) {
7656 				    if (cnt <= 4) {
7657 					    if (strncmp(buf, "EOD0", 4) == 0) {
7658 						    get_timeofday(&time_eod0,
7659 							(struct timezone *)0);
7660 						    got_eod0 = 1;
7661 						    done = 1;
7662 						    continue;
7663 					    }
7664 					    if (strncmp(buf, "EOD", 3) == 0) {
7665 						    ocorrection = buf[3] - '0';
7666 						    get_timeofday(&time_eod,
7667 							(struct timezone *)0);
7668 						    done = 1;
7669 						    break;	/* "EOF" */
7670 					    }
7671 					    if (strncmp(buf, "BOD", 3) == 0) {
7672 						    if (two_bod &&
7673 							(buf[3] == '0'))
7674 							    continue;
7675 						    if (interval)
7676 							setitimer(ITIMER_REAL,
7677 								  &itimer, 0);
7678 						    prep_timer();
7679 						    got_begin = 1;
7680 						    continue;
7681 					    }
7682 					    break;
7683 				    }
7684 				    else if (!got_begin) {
7685 					    if (interval)
7686 						    setitimer(ITIMER_REAL,
7687 							      &itimer, 0);
7688 					    prep_timer();
7689 					    got_begin = 1;
7690 				    }
7691 				    else if (got_eod0) {
7692 					    /* got data after EOD0, so
7693 					     * extend EOD0 time */
7694 					    get_timeofday(&time_eod0,
7695 							  (struct timezone *)0);
7696 				    }
7697 				    if (!got_begin)
7698 					    continue;
7699 				    nbytes += cnt;
7700 				    cnt = 0;
7701 				    /* problematic if the interval timer
7702 				     * goes off right here */
7703 				    if (udplossinfo) {
7704 					    if (first_read) {
7705 						    bcopy(buf + 24, &ntbytesc,
7706 								8);
7707 						    first_read = 0;
7708 						    if (ntbytesc > 0x100000000ull)
7709 							    need_swap = 1;
7710 						    if (!need_swap) {
7711 							    stream_idx++;
7712 							    stream_idx =
7713 								stream_idx
7714 								    % nstream;
7715 							    continue;
7716 						    }
7717 					    }
7718 					    if (!need_swap)
7719 						    bcopy(buf + 24, &ntbytesc,
7720 								8);
7721 					    else {
7722 						    cp1 = (char *)&ntbytesc;
7723 						    cp2 = buf + 31;
7724 						    for ( i = 0; i < 8; i++ )
7725 							    *cp1++ = *cp2--;
7726 					    }
7727 				    }
7728 				    if (do_jitter) {
7729 					    if (first_jitter) {
7730 						    get_timeofday(
7731 							&timepkr,
7732 							(struct timezone *)0);
7733 						    timepkri = timepkr;
7734 						    first_jitter = 0;
7735 						    first_jitteri = 0;
7736 						    ntbytescp = ntbytesc;
7737 						    ntbytescpi = ntbytesc;
7738 						    jitter = 0.0;
7739 						    jitteri = 0.0;
7740 						    njitter = 0;
7741 						    njitteri = 0;
7742 						    jitter_min = 1000000.0;
7743 						    jitter_mini = 1000000.0;
7744 						    jitter_max = -1000000.0;
7745 						    jitter_maxi = -1000000.0;
7746 						    jitter_avg = 0.0;
7747 						    jitter_avgi = 0.0;
7748 #ifdef DEBUG
7749 						    if (clientserver &&
7750 							client &&
7751 							(format & DEBUGJITTER))
7752 							fprintf(stdout,
7753 							    "pkt_time_ms"
7754 							    " = %6.3f ms\n",
7755 							    pkt_time_ms);
7756 #endif
7757 						    stream_idx++;
7758 						    stream_idx =
7759 							stream_idx % nstream;
7760 						    continue;
7761 					    }
7762 					    /* formula for jitter is from
7763 					     * RFC1889 - note synchronized
7764 					     * clocks are not required since
7765 					     * source packet delta time is
7766 					     * known (pkt_time_ms)
7767 					     *
7768 					     * D(i,j)=(Rj-Ri)-(Sj-Si)
7769 					     *       =(Rj-Sj)-(Ri-Si)
7770 					     * J=J+(|D(i-1,i)|-J)/16
7771 					     *
7772 					     * for nuttcp we just use the raw
7773 					     * absolute value of the delta
7774 					     *
7775 					     * J=|D(i-1,i)|
7776 					     */
7777 
7778 					    if (!do_owd) {
7779 						get_timeofday(&timerx,
7780 							(struct timezone *)0);
7781 					    }
7782 					    if (do_jitter & JITTER_IGNORE_OOO) {
7783 						/* first check that packet
7784 						 * is next in sequence */
7785 						if (udplossinfo &&
7786 						    (ntbytescp + buflen)
7787 							!= ntbytesc) {
7788 						    ntbytescp = ntbytesc;
7789 						    ntbytescpi = ntbytesc;
7790 						    timepkr = timerx;
7791 						    timepkri = timerx;
7792 						    stream_idx++;
7793 						    stream_idx =
7794 							stream_idx % nstream;
7795 						    continue;
7796 						}
7797 					    }
7798 
7799 					    tvsub( &timed, &timerx, &timepkr );
7800 					    pkt_delta =
7801 						timed.tv_sec*1000
7802 						    + ((double)timed.tv_usec)
7803 								/ 1000;
7804 					    pkt_delta -= pkt_time_ms;
7805 					    if (pkt_delta >= 0)
7806 						jitter = pkt_delta;
7807 					    else
7808 						jitter = -pkt_delta;
7809 					    njitter++;
7810 					    if (jitter < jitter_min)
7811 						jitter_min = jitter;
7812 					    if (jitter > jitter_max)
7813 						jitter_max = jitter;
7814 					    jitter_avg += jitter;
7815 #ifdef DEBUG
7816 					    if (clientserver && client &&
7817 						(format & DEBUGJITTER))
7818 						fprintf(stdout,
7819 						    "pkt_delta = %6.3f ms, "
7820 						    "jitter = %9.6f ms\n",
7821 						    pkt_delta, jitter);
7822 #endif
7823 					    timepkr = timerx;
7824 					    ntbytescp = ntbytesc;
7825 					    if (!interval) {
7826 						    stream_idx++;
7827 						    stream_idx =
7828 							stream_idx % nstream;
7829 						    continue;
7830 					    }
7831 					    if (first_jitteri) {
7832 						    get_timeofday(
7833 							&timepkri,
7834 							(struct timezone *)0);
7835 						    first_jitteri = 0;
7836 						    ntbytescpi = ntbytesc;
7837 						    jitteri = 0.0;
7838 						    njitteri = 0;
7839 						    jitter_mini = 1000000.0;
7840 						    jitter_maxi = -1000000.0;
7841 						    jitter_avgi = 0.0;
7842 						    stream_idx++;
7843 						    stream_idx =
7844 							stream_idx % nstream;
7845 						    continue;
7846 					    }
7847 					    tvsub( &timed, &timerx, &timepkri );
7848 					    pkt_delta =
7849 						timed.tv_sec*1000
7850 						    + ((double)timed.tv_usec)
7851 								/ 1000;
7852 					    pkt_delta -= pkt_time_ms;
7853 					    if (pkt_delta >= 0)
7854 						jitteri = pkt_delta;
7855 					    else
7856 						jitteri = -pkt_delta;
7857 					    njitteri++;
7858 					    if (jitteri < jitter_mini)
7859 						jitter_mini = jitteri;
7860 					    if (jitteri > jitter_maxi)
7861 						jitter_maxi = jitteri;
7862 					    jitter_avgi += jitteri;
7863 					    timepkri = timerx;
7864 					    ntbytescpi = ntbytesc;
7865 				    }
7866 				    stream_idx++;
7867 				    stream_idx = stream_idx % nstream;
7868 			    }
7869 			    if (intr && (cnt > 0))
7870 				    nbytes += cnt;
7871 			    if (got_eod0) {
7872 				    tvsub( &timed, &time_eod, &time_eod0 );
7873 				    correction = timed.tv_sec +
7874 						    ((double)timed.tv_usec)
7875 								/ 1000000;
7876 			    }
7877 			}
7878 			else {
7879 			    while (((cnt=Nread(fd[stream_idx + 1], buf, buflen)) > 0) && !intr) {
7880 				    nbytes += cnt;
7881 				    cnt = 0;
7882 				    if (first_read) {
7883 					if (interval && !(format & NORETRANS)) {
7884 					    uint32_t tmp;
7885 
7886 					    first_read = 0;
7887 					    bcopy(buf + 24, &nretrans[1], 4);
7888 					    bcopy(buf + 28, &tmp, 4);
7889 					    if (tmp == 0x5254524Eu) {
7890 						    /* "RTRN" */
7891 						    retransinfo = 1;
7892 #if defined(linux)
7893 						    cwndinfo = 1;
7894 #endif
7895 						    b_flag = 1;
7896 					    }
7897 					    else if (tmp == 0x48525452u) {
7898 						    /* "HRTR" */
7899 						    retransinfo = 2;
7900 						    cwndinfo = 0;
7901 						    read_cwnd = 0;
7902 						    b_flag = 1;
7903 					    }
7904 					    else if (tmp == 0x4E525452u) {
7905 						    /* "NRTR" */
7906 						    need_swap = 1;
7907 						    retransinfo = 1;
7908 #if defined(linux)
7909 						    cwndinfo = 1;
7910 #endif
7911 						    b_flag = 1;
7912 					    }
7913 					    else if (tmp == 0x52545248u) {
7914 						    /* "RTRH" */
7915 						    need_swap = 1;
7916 						    retransinfo = 2;
7917 						    cwndinfo = 0;
7918 						    read_cwnd = 0;
7919 						    b_flag = 1;
7920 					    }
7921 					    else {
7922 						    retransinfo = -1;
7923 						    cwndinfo = 0;
7924 						    read_retrans = 0;
7925 						    read_cwnd = 0;
7926 					    }
7927 					    if (format & NOCWND) {
7928 						    cwndinfo = 0;
7929 						    read_cwnd = 0;
7930 					    }
7931 					}
7932 					else {
7933 					    read_retrans = 0;
7934 					    read_cwnd = 0;
7935 					}
7936 				    }
7937 				    if (read_retrans) {
7938 					    if (!need_swap)
7939 						    bcopy(buf + 24,
7940 							  &nretrans[1], 4);
7941 					    else {
7942 						    cp1 = (char *)&nretrans[1];
7943 						    cp2 = buf + 27;
7944 						    for ( i = 0; i < 4; i++ )
7945 							    *cp1++ = *cp2--;
7946 					    }
7947 				    }
7948 				    if (read_cwnd) {
7949 					    if (!need_swap)
7950 						    bcopy(buf + 28,
7951 							  &cwnd[1], 4);
7952 					    else {
7953 						    cp1 = (char *)&cwnd[1];
7954 						    cp2 = buf + 31;
7955 						    for ( i = 0; i < 4; i++ )
7956 							    *cp1++ = *cp2--;
7957 					    }
7958 				    }
7959 				    stream_idx++;
7960 				    stream_idx = stream_idx % nstream;
7961 			    }
7962 			    if (intr && (cnt > 0))
7963 				    nbytes += cnt;
7964 			}
7965 		}
7966 	}
7967 	else {
7968 		register int cnt;
7969 		if (trans) {
7970 #if defined(linux)
7971 			struct stat instat;
7972 
7973 			if (fstat(savestdin, &instat) == 0) {
7974 				if (!S_ISREG(instat.st_mode) &&
7975 				    !S_ISBLK(instat.st_mode)) {
7976 					zerocopy = 0;
7977 					directio = 0;
7978 				}
7979 			}
7980 			else {
7981 				zerocopy = 0;
7982 				directio = 0;
7983 			}
7984 
7985 			if (directio) {
7986 				flags = fcntl(savestdin, F_GETFL, 0);
7987 				if (flags < 0)
7988 					errmes("fcntl get O_DIRECT");
7989 				else {
7990 					flags |= O_DIRECT;
7991 					if (fcntl(savestdin,
7992 						  F_SETFL, flags) < 0)
7993 						errmes("fcntl set O_DIRECT");
7994 				}
7995 			}
7996 
7997 			if (zerocopy) {
7998 				while (nbuf-- &&
7999 				       ((cnt=sendfile(fd[stream_idx + 1],
8000 						      savestdin,
8001 						      (off_t *)&nbytes,
8002 						      buflen)) > 0)) {
8003 					cnt = 0;
8004 					stream_idx++;
8005 					stream_idx = stream_idx % nstream;
8006 				}
8007 			}
8008 			else
8009 #endif
8010 			{
8011 				while (nbuf-- &&
8012 				       ((cnt=read(savestdin, buf, buflen)) > 0) &&
8013 				       (Nwrite(fd[stream_idx + 1], buf, cnt)
8014 						== cnt)) {
8015 					nbytes += cnt;
8016 					cnt = 0;
8017 					stream_idx++;
8018 					stream_idx = stream_idx % nstream;
8019 				}
8020 			}
8021 			if (udp) {
8022 				strcpy(buf, "EOD0");
8023 				(void)Nwrite( fd[stream_idx + 1], buf, 4 ); /* rcvr end */
8024 			}
8025 		}
8026 		else {
8027 #if defined(linux)
8028 			struct stat outstat;
8029 
8030 			if (fstat(savestdout, &outstat) == 0) {
8031 				if (!S_ISREG(outstat.st_mode) &&
8032 				    !S_ISBLK(outstat.st_mode))
8033 					directio = 0;
8034 			}
8035 			else
8036 				directio = 0;
8037 
8038 			if (directio) {
8039 				flags = fcntl(savestdout, F_GETFL, 0);
8040 				if (flags < 0)
8041 					errmes("fcntl get O_DIRECT");
8042 				else {
8043 					flags |= O_DIRECT;
8044 					if (fcntl(savestdout,
8045 						  F_SETFL, flags) < 0)
8046 						errmes("fcntl set O_DIRECT");
8047 				}
8048 			}
8049 #endif
8050 			while ((cnt=Nread(fd[stream_idx + 1], buf, buflen)) > 0 &&
8051 			    ((cnt != 4) || strncmp(buf, "EOD", 3) != 0) &&
8052 			    mwrite(savestdout, buf, cnt,
8053 				   cnt != buflen) == cnt) {
8054 				nbytes += cnt;
8055 				cnt = 0;
8056 				stream_idx++;
8057 				stream_idx = stream_idx % nstream;
8058 			}
8059 		}
8060 	}
8061 	if (errno && (errno != EAGAIN)) {
8062 		if ((errno != EINTR) &&
8063 #ifdef ERESTART
8064 		    (errno != ERESTART) &&
8065 #endif
8066 		    (!clientserver || client)) err("IO");
8067 	}
8068 	itimer.it_value.tv_sec = 0;
8069 	itimer.it_value.tv_usec = 0;
8070 	itimer.it_interval.tv_sec = 0;
8071 	itimer.it_interval.tv_usec = 0;
8072 	setitimer(ITIMER_REAL, &itimer, 0);
8073 	done = 1;
8074 	(void)read_timer(stats, sizeof(stats));
8075 	if (udp&&trans) {
8076 		usleep(500000);
8077 		strcpy(buf, "EOD1");
8078 		(void)Nwrite( fd[stream_idx + 1], buf, 4 ); /* rcvr end */
8079 		stream_idx++;
8080 		stream_idx = stream_idx % nstream;
8081 		usleep(500000);
8082 		strcpy(buf, "EOD2");
8083 		(void)Nwrite( fd[stream_idx + 1], buf, 4 ); /* rcvr end */
8084 		stream_idx++;
8085 		stream_idx = stream_idx % nstream;
8086 		usleep(500000);
8087 		strcpy(buf, "EOD3");
8088 		(void)Nwrite( fd[stream_idx + 1], buf, 4 ); /* rcvr end */
8089 		stream_idx++;
8090 		stream_idx = stream_idx % nstream;
8091 		usleep(500000);
8092 		strcpy(buf, "EOD4");
8093 		(void)Nwrite( fd[stream_idx + 1], buf, 4 ); /* rcvr end */
8094 		stream_idx++;
8095 		stream_idx = stream_idx % nstream;
8096 	}
8097 
8098 	if (!udp && trans && (format & DEBUGRETRANS)) {
8099 		sretrans = get_retrans(-1, &tcpinf);
8100 		fprintf(stdout, "before closing system retrans = %d\n",
8101 			sretrans);
8102 	}
8103 
8104 #ifdef DEBUG
8105 	if (clientserver && client && !trans && do_jitter && njitter &&
8106 	    (format & DEBUGJITTER)) {
8107 		fprintf(stdout, "njitter = %lld\n", njitter);
8108 		fprintf(stdout, "jitter_min = %9.6f ms\n", jitter_min);
8109 		fprintf(stdout, "jitter_max = %9.6f ms\n", jitter_max);
8110 		fprintf(stdout, "jitter_avg = %9.6f ms\n", jitter_avg/njitter);
8111 	}
8112 #endif
8113 
8114 	for ( stream_idx = 1; stream_idx <= nstream; stream_idx++ ) {
8115 		if (!udp && trans) {
8116 #if defined(linux) && defined(TCPI_OPT_TIMESTAMPS) && !defined(BROKEN_UNACKED)
8117 			/* if -DBROKEN_UNACKED skip check for unACKed data
8118 			 * (workaround motivated by possible bug encountered
8119 			 * on a Suse Linux 10.1 system)
8120 			 */
8121 			struct timeval timeunsent, timec, timed;
8122 			double xmitrate;
8123 			int unsent, xmitunsent;
8124 			long flags;
8125 
8126 			optlen = sizeof(tcpinf);
8127 			if (getsockopt(fd[stream_idx], SOL_TCP, TCP_INFO,
8128 				       (void *)&tcpinf, &optlen) < 0) {
8129 				mes("couldn't collect TCP info\n");
8130 				retransinfo = -1;
8131 				cwndinfo = 0;
8132 			}
8133 			if (ioctl(fd[stream_idx], SIOCOUTQ, &unsent) < 0) {
8134 				mes("couldn't get SIOCOUTQ value\n");
8135 				unsent = -1;
8136 			}
8137 			get_timeofday(&timeunsent, (struct timezone *)0);
8138 			realtd = 0.0;
8139 			xmitrate = ((double)nbytes-(double)unsent)/realt;
8140 			xmitunsent = (double)unsent/xmitrate;
8141 			xmitunsent = 2*xmitunsent + MAX_EOT_WAIT_SEC;
8142 			if (clientserver && client) {
8143 				reading_srvr_info = 1;
8144 				pollfds[0].fd = fileno(ctlconn);
8145 				pollfds[0].events = POLLIN | POLLPRI;
8146 				pollfds[0].revents = 0;
8147 				flags = fcntl(0, F_GETFL, 0);
8148 				if (flags < 0)
8149 					err("fcntl 1");
8150 				flags |= O_NONBLOCK;
8151 				if (fcntl(0, F_SETFL, flags) < 0)
8152 					err("fcntl 2");
8153 				itimer.it_value.tv_sec = xmitunsent + 10;
8154 				itimer.it_value.tv_usec = 0;
8155 				itimer.it_interval.tv_sec = 0;
8156 				itimer.it_interval.tv_usec = 0;
8157 				setitimer(ITIMER_REAL, &itimer, 0);
8158 			}
8159 			while ((unsent > 0) && (realtd < xmitunsent)) {
8160 				if (clientserver && client &&
8161 				    ((pollst = poll(pollfds, 1, 0)) > 0) &&
8162 				    (pollfds[0].revents & (POLLIN | POLLPRI)) &&
8163 				    !got_done) {
8164 					/* check for server output */
8165 					while (fgets(intervalbuf,
8166 					       sizeof(intervalbuf), stdin))
8167 					{
8168 					setitimer(ITIMER_REAL, &itimer, 0);
8169 					get_timeofday(&timeunsent,
8170 						      (struct timezone *)0);
8171 					if (strncmp(intervalbuf, "DONE", 4)
8172 							== 0) {
8173 						if (format & DEBUGPOLL) {
8174 							fprintf(stdout,
8175 								"got DONE\n");
8176 							fflush(stdout);
8177 						}
8178 						got_done = 1;
8179 						intr = 1;
8180 						break;
8181 					}
8182 					else if (strncmp(intervalbuf,
8183 							 "nuttcp-", 7) == 0) {
8184 						if ((brief <= 0) ||
8185 						    strstr(intervalbuf,
8186 							    "Warning") ||
8187 						    strstr(intervalbuf,
8188 							    "Error") ||
8189 						    strstr(intervalbuf,
8190 							    "Debug")) {
8191 							if (*ident) {
8192 							    fputs("nuttcp",
8193 								  stdout);
8194 							    fputs(trans ?
8195 								    "-r" : "-t",
8196 								  stdout);
8197 							    fputs(ident,
8198 								  stdout);
8199 							    fputs(intervalbuf
8200 								    + 8,
8201 								  stdout);
8202 							}
8203 							else
8204 							    fputs(intervalbuf,
8205 								  stdout);
8206 							fflush(stdout);
8207 						}
8208 						if (strstr(intervalbuf,
8209 							   "Error"))
8210 							exit(1);
8211 					}
8212 					else {
8213 						if (*ident)
8214 							fprintf(stdout, "%s: ",
8215 								ident + 1);
8216 						intervalbuf[strlen(intervalbuf)
8217 								- 1] = '\0';
8218 						if (do_retrans) {
8219 						    cp1 = strstr(intervalbuf,
8220 								 "Mbps") + 4;
8221 						    ch = '\0';
8222 						    if (cp1) {
8223 							if (format & PARSE) {
8224 							    cp1 = strchr(cp1,
8225 									 '.');
8226 							    if (cp1)
8227 								cp1 += 5;
8228 							}
8229 							ch = *cp1;
8230 						    }
8231 						    if (ch)
8232 							*cp1 = '\0';
8233 						}
8234 						fputs(intervalbuf, stdout);
8235 						if (do_retrans && sinkmode &&
8236 						    (nstream == 1)) {
8237 						    nretrans[1] =
8238 						      get_retrans(
8239 							    fd[stream_idx],
8240 							    &tcpinf);
8241 						    nretrans[1] -= iretrans[1];
8242 						    if (format & PARSE)
8243 							fprintf(stdout,
8244 							 P_RETRANS_FMT_INTERVAL,
8245 							   (retransinfo == 1) ?
8246 								"" : "host-",
8247 							   (nretrans[1]
8248 								- pretrans));
8249 						    else
8250 							fprintf(stdout,
8251 							 RETRANS_FMT_INTERVAL,
8252 							   (nretrans[1]
8253 								- pretrans),
8254 							   (retransinfo == 1) ?
8255 								"" : "host-");
8256 						    pretrans =
8257 							nretrans[1];
8258 						}
8259 						if (do_cwnd && sinkmode &&
8260 						    (nstream == 1)) {
8261 						    cwnd[1] =
8262 						        tcpinf.tcpinfo_snd_cwnd
8263 								*datamss/1024;
8264 						    if (format & PARSE)
8265 							fprintf(stdout,
8266 							    P_CWND_FMT_INTERVAL,
8267 							    cwnd[1]);
8268 						    else
8269 							fprintf(stdout,
8270 							    CWND_FMT_INTERVAL,
8271 							    cwnd[1]);
8272 						}
8273 						if (do_retrans && cp1 && ch) {
8274 						    *cp1 = ch;
8275 						    fputs(cp1, stdout);
8276 						}
8277 						fprintf(stdout, "\n");
8278 						fflush(stdout);
8279 					}
8280 					}
8281 				}
8282 				if (format & DEBUGRETRANS)
8283 					print_tcpinfo();
8284 				if (format & DEBUGRETRANS)
8285 					usleep(100000);
8286 				else
8287 					usleep(1000);
8288 				optlen = sizeof(tcpinf);
8289 				if (getsockopt(fd[stream_idx],
8290 					       SOL_TCP, TCP_INFO,
8291 					       (void *)&tcpinf, &optlen) < 0) {
8292 					mes("couldn't collect TCP info\n");
8293 					retransinfo = -1;
8294 					cwndinfo = 0;
8295 				}
8296 				if (ioctl(fd[stream_idx], SIOCOUTQ,
8297 					  &unsent) < 0) {
8298 					mes("couldn't get SIOCOUTQ value\n");
8299 					unsent = -1;
8300 				}
8301 				get_timeofday(&timec, (struct timezone *)0);
8302 				tvsub(&timed, &timec, &timeunsent);
8303 				realtd = timed.tv_sec
8304 					    + ((double)timed.tv_usec) / 1000000;
8305 			}
8306 			if (clientserver && client) {
8307 				reading_srvr_info = 0;
8308 				flags = fcntl(0, F_GETFL, 0);
8309 				if (flags < 0)
8310 					err("fcntl 1");
8311 				flags &= ~O_NONBLOCK;
8312 				if (fcntl(0, F_SETFL, flags) < 0)
8313 					err("fcntl 2");
8314 				itimer.it_value.tv_sec = 0;
8315 				itimer.it_value.tv_usec = 0;
8316 				setitimer(ITIMER_REAL, &itimer, 0);
8317 			}
8318 
8319 			if (getsockopt(fd[stream_idx], SOL_TCP, TCP_INFO,
8320 				       (void *)&tcpinf, &optlen) < 0) {
8321 				mes("couldn't collect TCP info\n");
8322 				retransinfo = -1;
8323 				cwndinfo = 0;
8324 			}
8325 			if (unsent > 0) {
8326 				/* assume receiver went away */
8327 				if (clientserver && client) {
8328 					mes("Error: timeout while draining "
8329 					    "socket send queue");
8330 					exit(1);
8331 				}
8332 				goto cleanup;
8333 			}
8334 
8335 			if (format & DEBUGRETRANS)
8336 				print_tcpinfo();
8337 #endif
8338 			if (retransinfo > 0) {
8339 				if ((stream_idx == 1) || (retransinfo == 1)) {
8340 					nretrans[stream_idx] =
8341 						get_retrans(fd[stream_idx],
8342 							    &tcpinf);
8343 					nretrans[stream_idx] -=
8344 						iretrans[stream_idx];
8345 #if defined(linux)
8346 					if (retransinfo == 1)
8347 						cwnd[stream_idx] =
8348 							tcpinf.tcpinfo_snd_cwnd
8349 								*datamss/1024;
8350 #endif
8351 				}
8352 			}
8353 		}
8354 	}
8355 	if (!udp && trans && (format & DEBUGRETRANS)) {
8356 		sretrans = get_retrans(-1, &tcpinf);
8357 		fprintf(stdout, "after closing system retrans = %d\n",
8358 			sretrans);
8359 	}
8360 
8361 	if (interval && clientserver && client && do_retrans && !got_done) {
8362 		/* don't fully close data channels yet since there
8363 		 * may be some straggler interval reports to which we
8364 		 * will need to append retrans info, so just shutdown()
8365 		 * for writing for now */
8366 		for ( stream_idx = 1; stream_idx <= nstream; stream_idx++ )
8367 			shutdown(fd[stream_idx], SHUT_WR);
8368 	}
8369 	else
8370 		close_data_channels();
8371 
8372 	if (interval && clientserver && !client && !trans) {
8373 		fprintf(stdout, "DONE\n");
8374 		fflush(stdout);
8375 	}
8376 
8377 	if (cput <= 0.0)  cput = 0.000001;
8378 	if (realt <= 0.0)  realt = 0.000001;
8379 
8380 	if (udp && !trans) {
8381 		if (got_eod0)
8382 			realt -= correction;
8383 		else
8384 			realt -= ocorrection * 0.5;
8385 	}
8386 
8387 	sprintf(srvrbuf, "%.4f", (double)nbytes/1024/1024);
8388 	sscanf(srvrbuf, "%lf", &MB);
8389 
8390 	if (clientserver && client)
8391 		reading_srvr_info = 1;
8392 
8393 	if (interval && clientserver && client && trans && !got_done) {
8394 		long flags;
8395 
8396 		if (format & DEBUGPOLL) {
8397 			fprintf(stdout, "getting rest of server output\n");
8398 			fflush(stdout);
8399 		}
8400 		flags = fcntl(0, F_GETFL, 0);
8401 		if (flags < 0)
8402 			err("fcntl 3");
8403 		flags &= ~O_NONBLOCK;
8404 		if (fcntl(0, F_SETFL, flags) < 0)
8405 			err("fcntl 4");
8406 		itimer.it_value.tv_sec = SRVR_INFO_TIMEOUT;
8407 		itimer.it_value.tv_usec = 0;
8408 		itimer.it_interval.tv_sec = 0;
8409 		itimer.it_interval.tv_usec = 0;
8410 		setitimer(ITIMER_REAL, &itimer, 0);
8411 		while (fgets(intervalbuf, sizeof(intervalbuf), stdin)) {
8412 			setitimer(ITIMER_REAL, &itimer, 0);
8413 			if (strncmp(intervalbuf, "DONE", 4) == 0) {
8414 				if (format & DEBUGPOLL) {
8415 					fprintf(stdout, "got DONE 2\n");
8416 					fflush(stdout);
8417 				}
8418 				break;
8419 			}
8420 			if ((!strstr(intervalbuf, " MB / ") ||
8421 			     !strstr(intervalbuf, " sec = ")) && (brief > 0))
8422 				continue;
8423 			if (*ident)
8424 				fprintf(stdout, "%s: ", ident + 1);
8425 			intervalbuf[strlen(intervalbuf) - 1] = '\0';
8426 			if (do_retrans) {
8427 				cp1 = strstr(intervalbuf, "Mbps") + 4;
8428 				ch = '\0';
8429 				if (cp1) {
8430 					if (format & PARSE) {
8431 						cp1 = strchr(cp1, '.');
8432 						if (cp1)
8433 							cp1 += 5;
8434 					}
8435 					ch = *cp1;
8436 				}
8437 				if (ch)
8438 					*cp1 = '\0';
8439 			}
8440 			fputs(intervalbuf, stdout);
8441 			if (do_retrans && sinkmode) {
8442 				nretrans[1] = get_retrans(fd[1], &tcpinf);
8443 				nretrans[1] -= iretrans[1];
8444 				if (format & PARSE)
8445 					fprintf(stdout, P_RETRANS_FMT_INTERVAL,
8446 						(retransinfo == 1) ?
8447 							"" : "host-",
8448 						(nretrans[1] - pretrans));
8449 				else
8450 					fprintf(stdout, RETRANS_FMT_INTERVAL,
8451 						(nretrans[1] - pretrans),
8452 						(retransinfo == 1) ?
8453 							"" : "host-");
8454 				pretrans = nretrans[1];
8455 			}
8456 #if defined(linux)
8457 			if (do_cwnd && sinkmode) {
8458 				cwnd[1] = tcpinf.tcpinfo_snd_cwnd
8459 						*datamss/1024;
8460 				if (format & PARSE)
8461 					fprintf(stdout, P_CWND_FMT_INTERVAL,
8462 						cwnd[1]);
8463 				else
8464 					fprintf(stdout, CWND_FMT_INTERVAL,
8465 						cwnd[1]);
8466 			}
8467 #endif
8468 			if (do_retrans && cp1 && ch) {
8469 				*cp1 = ch;
8470 				fputs(cp1, stdout);
8471 			}
8472 			fprintf(stdout, "\n");
8473 			fflush(stdout);
8474 		}
8475 		itimer.it_value.tv_sec = 0;
8476 		itimer.it_value.tv_usec = 0;
8477 		setitimer(ITIMER_REAL, &itimer, 0);
8478 	}
8479 
8480 	if (interval && clientserver && client && do_retrans) {
8481 		/* it's OK to fully close the data channels now */
8482 		close_data_channels();
8483 	}
8484 
8485 	if (clientserver && client) {
8486 		itimer.it_value.tv_sec = SRVR_INFO_TIMEOUT;
8487 		itimer.it_value.tv_usec = 0;
8488 		setitimer(ITIMER_REAL, &itimer, 0);
8489 		cp1 = srvrbuf;
8490 		got_srvr_retrans = 0;
8491 		got_srvr_cwnd = 0;
8492 		while (fgets(cp1, sizeof(srvrbuf) - (cp1 - srvrbuf), stdin)) {
8493 			setitimer(ITIMER_REAL, &itimer, 0);
8494 			if (*(cp1 + strlen(cp1) - 1) != '\n') {
8495 				*cp1 = '\0';
8496 				break;
8497 			}
8498 			if (strstr(cp1, "real") && strstr(cp1, "seconds")) {
8499 				strcpy(fmt, "nuttcp-%*c: ");
8500 				if (format & PARSE)
8501 					strcat(fmt, P_PERF_FMT_IN);
8502 				else
8503 					strcat(fmt, PERF_FMT_IN);
8504 				sscanf(cp1, fmt,
8505 				       &srvr_MB, &srvr_realt, &srvr_KBps,
8506 				       &srvr_Mbps);
8507 				if (trans && udp) {
8508 					strncpy(tmpbuf, cp1, 256);
8509 					*(tmpbuf + 256) = '\0';
8510 					if (strncmp(tmpbuf,
8511 						    "nuttcp-r", 8) == 0)
8512 						sprintf(cp1, "nuttcp-r%s%s",
8513 							ident, tmpbuf + 8);
8514 					cp1 += strlen(cp1);
8515 					cp2 = cp1;
8516 					sprintf(cp2, "nuttcp-r:");
8517 					cp2 += 9;
8518 					if (format & PARSE)
8519 						strcpy(fmt, P_DROP_FMT);
8520 					else
8521 						strcpy(fmt, DROP_FMT);
8522 					sprintf(cp2, fmt,
8523 						(int64_t)(((MB - srvr_MB)
8524 							*1024*1024)
8525 								/buflen + 0.5),
8526 						(uint64_t)((MB*1024*1024)
8527 							/buflen + 0.5));
8528 					cp2 += strlen(cp2);
8529 					fractloss = ((MB != 0.0) ?
8530 						1 - srvr_MB/MB : 0.0);
8531 					if (format & PARSE)
8532 						strcpy(fmt, P_LOSS_FMT);
8533 					else if ((fractloss != 0.0) &&
8534 						 (fractloss < 0.001))
8535 						strcpy(fmt, LOSS_FMT5);
8536 					else
8537 						strcpy(fmt, LOSS_FMT);
8538 					sprintf(cp2, fmt, fractloss * 100);
8539 					cp2 += strlen(cp2);
8540 					sprintf(cp2, "\n");
8541 				}
8542 			}
8543 			else if (strstr(cp1, "sys")) {
8544 				strcpy(fmt, "nuttcp-%*c: ");
8545 				if (format & PARSE) {
8546 					strcat(fmt, "stats=cpu ");
8547 					strcat(fmt, P_CPU_STATS_FMT_IN2);
8548 				}
8549 				else
8550 					strcat(fmt, CPU_STATS_FMT_IN2);
8551 				if (sscanf(cp1, fmt,
8552 					   &srvr_cpu_util) != 7) {
8553 					strcpy(fmt, "nuttcp-%*c: ");
8554 					if (format & PARSE) {
8555 						strcat(fmt, "stats=cpu ");
8556 						strcat(fmt,
8557 						       P_CPU_STATS_FMT_IN);
8558 					}
8559 					else
8560 						strcat(fmt, CPU_STATS_FMT_IN);
8561 					sscanf(cp1, fmt,
8562 					       &srvr_cpu_util);
8563 				}
8564 			}
8565 			else if ((cp2 = strstr(cp1, "retrans"))) {
8566 				got_srvr_retrans = 1;
8567 				retransinfo = 1;
8568 				if (strstr(cp1, "host-retrans"))
8569 					retransinfo = 2;
8570 				if (format & PARSE)
8571 					sscanf(cp2, P_RETRANS_FMT_IN,
8572 					       &total_retrans);
8573 				else
8574 					sscanf(cp2, RETRANS_FMT_IN,
8575 					       &total_retrans);
8576 				if (format & PARSE) {
8577 					if ((cp2 = strstr(cp2,
8578 							"retrans_by_stream=")))
8579 						cp2 += 18;
8580 					else
8581 						cp2 = NULL;
8582 				}
8583 				else {
8584 					if ((cp2 = strstr(cp2, "( ")))
8585 						cp2 += 2;
8586 					else
8587 						cp2 = NULL;
8588 				}
8589 				if (cp2) {
8590 					sscanf(cp2, "%d", &nretrans[1]);
8591 					stream_idx = 2;
8592 					while ((stream_idx <= nstream) &&
8593 					       (cp2 = strchr(cp2, '+'))) {
8594 						cp2++;
8595 						sscanf(cp2, "%d",
8596 						       &nretrans[stream_idx]);
8597 						stream_idx++;
8598 					}
8599 				}
8600 				/* below is for compatibility with 6.0.x beta */
8601 				if ((cp2 = strstr(cp1, "RTT"))) {
8602 					if (format & PARSE)
8603 						sscanf(cp2, P_RTT_FMT_IN, &rtt);
8604 					else
8605 						sscanf(cp2, RTT_FMT_INB, &rtt);
8606 				}
8607 				if ((cp2 = strstr(cp1, "cwnd"))) {
8608 					got_srvr_cwnd = 1;
8609 					cwndinfo = 1;
8610 					if (format & PARSE)
8611 						sscanf(cp2, P_CWND_FMT_IN,
8612 						       &total_snd_cwnd);
8613 					else
8614 						sscanf(cp2, CWND_FMT_IN,
8615 						       &total_snd_cwnd);
8616 					if (format & PARSE) {
8617 						if ((cp2 = strstr(cp2,
8618 							    "cwnd_by_stream=")))
8619 							cp2 += 15;
8620 						else
8621 							cp2 = NULL;
8622 					}
8623 					else {
8624 						if ((cp2 = strstr(cp2, "( ")))
8625 							cp2 += 2;
8626 						else
8627 							cp2 = NULL;
8628 					}
8629 					if (cp2) {
8630 						sscanf(cp2, "%d", &cwnd[1]);
8631 						stream_idx = 2;
8632 						while ((stream_idx <=
8633 								nstream) &&
8634 						       (cp2 = strchr(cp2,
8635 								     '+'))) {
8636 							cp2++;
8637 							sscanf(cp2, "%d",
8638 							    &cwnd[stream_idx]);
8639 							stream_idx++;
8640 						}
8641 					}
8642 				}
8643 			}
8644 			else if ((cp2 = strstr(cp1, "RTT")) ||
8645 				 (cp2 = strstr(cp1, "rtt"))) {
8646 				if (format & PARSE)
8647 					sscanf(cp2, P_RTT_FMT_IN, &rtt);
8648 				else
8649 					sscanf(cp2, RTT_FMT_IN, &rtt);
8650 			}
8651 			else if ((cp2 = strstr(cp1, "jitter"))) {
8652 				if (format & PARSE)
8653 					sscanf(cp2, P_JITTER_FMT_IN,
8654 					       &jitter_min, &jitter_avg,
8655 					       &jitter_max);
8656 				else
8657 					sscanf(cp2, JITTER_FMT_IN,
8658 					       &jitter_min, &jitter_avg,
8659 					       &jitter_max);
8660 				njitter = 1;
8661 			}
8662 			else if ((cp2 = strstr(cp1, "OWD"))) {
8663 				if (format & PARSE)
8664 					sscanf(cp2, P_OWD_FMT_IN,
8665 					       &owd_min, &owd_avg, &owd_max);
8666 				else
8667 					sscanf(cp2, OWD_FMT_IN,
8668 					       &owd_min, &owd_avg, &owd_max);
8669 				nowd = 1;
8670 			}
8671 			else if ((strstr(cp1, "KB/cpu")) && !verbose)
8672 				continue;
8673 			strncpy(tmpbuf, cp1, 256);
8674 			*(tmpbuf + 256) = '\0';
8675 			if (strncmp(tmpbuf, "nuttcp-", 7) == 0)
8676 				sprintf(cp1, "nuttcp-%c%s%s",
8677 					tmpbuf[7], ident, tmpbuf + 8);
8678 			if ((strstr(cp1, "Warning") ||
8679 			     strstr(cp1, "Error") ||
8680 			     strstr(cp1, "Debug"))
8681 					&& (brief > 0)) {
8682 				fputs(cp1, stdout);
8683 				fflush(stdout);
8684 			}
8685 			cp1 += strlen(cp1);
8686 		}
8687 		itimer.it_value.tv_sec = 0;
8688 		itimer.it_value.tv_usec = 0;
8689 		setitimer(ITIMER_REAL, &itimer, 0);
8690 		got_srvr_output = 1;
8691 		if (!udp && !trans) {
8692 			if (!got_srvr_retrans)
8693 				retransinfo = -1;
8694 			if (!got_srvr_cwnd)
8695 				cwndinfo = 0;
8696 		}
8697 	}
8698 
8699 	if (!udp && trans) {
8700 		if (retransinfo > 0) {
8701 			total_retrans = 0;
8702 			for ( stream_idx = 1; stream_idx <= nstream; stream_idx++ ) {
8703 				total_retrans += nretrans[stream_idx];
8704 			}
8705 		}
8706 		if (cwndinfo) {
8707 			total_snd_cwnd = 0;
8708 			for ( stream_idx = 1; stream_idx <= nstream; stream_idx++ ) {
8709 				total_snd_cwnd += cwnd[stream_idx];
8710 			}
8711 		}
8712 	}
8713 
8714 	if (brief <= 0) {
8715 		strcpy(fmt, "nuttcp%s%s: ");
8716 		if (format & PARSE)
8717 			strcat(fmt, P_PERF_FMT_OUT);
8718 		else
8719 			strcat(fmt, PERF_FMT_OUT);
8720 		fprintf(stdout, fmt, trans?"-t":"-r", ident,
8721 			(double)nbytes/(1024*1024), realt,
8722 			(double)nbytes/realt/1024,
8723 			(double)nbytes/realt/125000);
8724 		if (clientserver && client && !trans && udp) {
8725 			fprintf(stdout, "nuttcp-r%s:", ident);
8726 			if (format & PARSE)
8727 				strcpy(fmt, P_DROP_FMT);
8728 			else
8729 				strcpy(fmt, DROP_FMT);
8730 			fprintf(stdout, fmt,
8731 				(int64_t)(((srvr_MB - MB)*1024*1024)
8732 					/buflen + 0.5),
8733 				(uint64_t)((srvr_MB*1024*1024)/buflen + 0.5));
8734 			fractloss = ((srvr_MB != 0.0) ? 1 - MB/srvr_MB : 0.0);
8735 			if (format & PARSE)
8736 				strcpy(fmt, P_LOSS_FMT);
8737 			else if ((fractloss != 0.0) && (fractloss < 0.001))
8738 				strcpy(fmt, LOSS_FMT5);
8739 			else
8740 				strcpy(fmt, LOSS_FMT);
8741 			fprintf(stdout, fmt, fractloss * 100);
8742 			fprintf(stdout, "\n");
8743 		}
8744 		if (clientserver && udp && !trans && do_jitter && njitter) {
8745 			strcpy(fmt, "nuttcp%s%s: ");
8746 			if (format & PARSE)
8747 				strcat(fmt, P_JITTER_FMT);
8748 			else
8749 				strcat(fmt, JITTER_FMT);
8750 			fprintf(stdout, fmt, trans?"-t":"-r", ident,
8751 				jitter_min, jitter_avg/njitter, jitter_max);
8752 			fprintf(stdout, "\n");
8753 		}
8754 		if (clientserver && !trans && do_owd && nowd) {
8755 			strcpy(fmt, "nuttcp%s%s: ");
8756 			if (format & PARSE)
8757 				strcat(fmt, P_OWD_FMT);
8758 			else
8759 				strcat(fmt, OWD_FMT);
8760 			fprintf(stdout, fmt, trans?"-t":"-r", ident,
8761 				owd_min, owd_avg/nowd, owd_max);
8762 			fprintf(stdout, "\n");
8763 		}
8764 		if (verbose) {
8765 			strcpy(fmt, "nuttcp%s%s: ");
8766 			if (format & PARSE)
8767 				strcat(fmt, "megabytes=%.4f cpu_seconds=%.2f KB_per_cpu_second=%.2f\n");
8768 			else
8769 				strcat(fmt, "%.4f MB in %.2f CPU seconds = %.2f KB/cpu sec\n");
8770 			fprintf(stdout, fmt,
8771 				trans?"-t":"-r", ident,
8772 				(double)nbytes/(1024*1024), cput,
8773 				(double)nbytes/cput/1024);
8774 		}
8775 		if (!udp && trans && (retransinfo > 0)) {
8776 			fprintf(stdout, "nuttcp%s%s: ",
8777 				trans ? "-t" : "-r", ident);
8778 			if (format & PARSE)
8779 				strcpy(fmt, P_RETRANS_FMT);
8780 			else
8781 				strcpy(fmt, RETRANS_FMT);
8782 			fprintf(stdout, fmt,
8783 				retransinfo == 1 ? "" : "host-", total_retrans);
8784 			if ((nstream > 1) && (retransinfo == 1) &&
8785 			    total_retrans) {
8786 				if (format & PARSE)
8787 					fprintf(stdout, P_RETRANS_FMT_STREAMS,
8788 						nretrans[1]);
8789 				else
8790 					fprintf(stdout, " ( %d", nretrans[1]);
8791 				for ( stream_idx = 2; stream_idx <= nstream;
8792 				      stream_idx++ ) {
8793 					fprintf(stdout, "+%d",
8794 						nretrans[stream_idx]);
8795 				}
8796 				if (!(format & PARSE))
8797 					fprintf(stdout, " )");
8798 			}
8799 #if defined(linux)
8800 			if (cwndinfo) {
8801 				if (format & PARSE)
8802 					strcpy(fmt, P_CWND_FMT);
8803 				else
8804 					strcpy(fmt, CWND_FMT);
8805 				fprintf(stdout, fmt, total_snd_cwnd);
8806 				if ((nstream > 1) && (retransinfo == 1) &&
8807 				    total_snd_cwnd) {
8808 					if (format & PARSE)
8809 						fprintf(stdout, P_CWND_FMT_STREAMS,
8810 							cwnd[1]);
8811 					else
8812 						fprintf(stdout, " ( %d", cwnd[1]);
8813 					for ( stream_idx = 2; stream_idx <= nstream;
8814 					      stream_idx++ ) {
8815 						fprintf(stdout, "+%d",
8816 							cwnd[stream_idx]);
8817 					}
8818 					if (!(format & PARSE))
8819 						fprintf(stdout, " )");
8820 				}
8821 			}
8822 #endif
8823 			fprintf(stdout, "\n");
8824 		}
8825 
8826 		strcpy(fmt, "nuttcp%s%s: ");
8827 		if (format & PARSE)
8828 			strcat(fmt, "io_calls=%d msec_per_call=%.2f calls_per_sec=%.2f\n");
8829 		else
8830 			strcat(fmt, "%d I/O calls, msec/call = %.2f, calls/sec = %.2f\n");
8831 		fprintf(stdout, fmt,
8832 			trans?"-t":"-r", ident,
8833 			numCalls,
8834 			1024.0 * realt/((double)numCalls),
8835 			((double)numCalls)/realt);
8836 
8837 		strcpy(fmt, "nuttcp%s%s: ");
8838 		if (format & PARSE)
8839 			strcat(fmt, "stats=cpu %s\n");
8840 		else
8841 			strcat(fmt, "%s\n");
8842 		fprintf(stdout, fmt, trans?"-t":"-r", ident, stats);
8843 	}
8844 
8845 	if (format & PARSE)
8846 		strcpy(fmt, P_CPU_STATS_FMT_IN2);
8847 	else
8848 		strcpy(fmt, CPU_STATS_FMT_IN2);
8849 	if (sscanf(stats, fmt, &cpu_util) != 6) {
8850 		if (format & PARSE)
8851 			strcpy(fmt, P_CPU_STATS_FMT_IN);
8852 		else
8853 			strcpy(fmt, CPU_STATS_FMT_IN);
8854 		sscanf(stats, fmt, &cpu_util);
8855 	}
8856 
8857 	if (brief && clientserver && client) {
8858 		if ((brief < 0) || interval)
8859 			fprintf(stdout, "\n");
8860 		if (udp) {
8861 			if (trans) {
8862 				if (*ident)
8863 					fprintf(stdout, "%s: ", ident + 1);
8864 				if (format & PARSE)
8865 					strcpy(fmt, P_PERF_FMT_BRIEF);
8866 				else
8867 					strcpy(fmt, PERF_FMT_BRIEF);
8868 				fprintf(stdout, fmt,
8869 					srvr_MB, srvr_realt, srvr_Mbps,
8870 					cpu_util, srvr_cpu_util);
8871 				if (!(format & NODROPS)) {
8872 					if (format & PARSE)
8873 						strcpy(fmt, P_DROP_FMT_BRIEF);
8874 					else
8875 						strcpy(fmt, DROP_FMT_BRIEF);
8876 					fprintf(stdout, fmt,
8877 						(int64_t)(((MB - srvr_MB)
8878 							*1024*1024)
8879 								/buflen + 0.5),
8880 						(uint64_t)((MB*1024*1024)
8881 							/buflen + 0.5));
8882 				}
8883 				if (!(format & NOPERCENTLOSS)) {
8884 					fractloss = ((MB != 0.0) ?
8885 						1 - srvr_MB/MB : 0.0);
8886 					if (format & PARSE)
8887 						strcpy(fmt, P_LOSS_FMT_BRIEF);
8888 					else if ((fractloss != 0.0) &&
8889 						 (fractloss < 0.001))
8890 						strcpy(fmt, LOSS_FMT_BRIEF5);
8891 					else
8892 						strcpy(fmt, LOSS_FMT_BRIEF);
8893 					fprintf(stdout, fmt, fractloss * 100);
8894 				}
8895 				if (format & XMITSTATS) {
8896 					if (format & PARSE)
8897 						strcpy(fmt, P_PERF_FMT_BRIEF3);
8898 					else
8899 						strcpy(fmt, PERF_FMT_BRIEF3);
8900 					fprintf(stdout, fmt, MB);
8901 				}
8902 				if ((do_jitter & JITTER_MIN) && njitter) {
8903 					if (format & PARSE)
8904 						strcpy(fmt,
8905 						       P_JITTER_MIN_FMT_BRIEF);
8906 					else
8907 						strcpy(fmt,
8908 						       JITTER_MIN_FMT_BRIEF);
8909 					fprintf(stdout, fmt, jitter_min);
8910 				}
8911 				if ((do_jitter & JITTER_AVG) && njitter) {
8912 					if (format & PARSE)
8913 						strcpy(fmt,
8914 						       P_JITTER_AVG_FMT_BRIEF);
8915 					else
8916 						strcpy(fmt,
8917 						       JITTER_AVG_FMT_BRIEF);
8918 					fprintf(stdout, fmt,
8919 						jitter_avg/njitter);
8920 				}
8921 				if ((do_jitter & JITTER_MAX) && njitter) {
8922 					if (format & PARSE)
8923 						strcpy(fmt,
8924 						       P_JITTER_MAX_FMT_BRIEF);
8925 					else
8926 						strcpy(fmt,
8927 						       JITTER_MAX_FMT_BRIEF);
8928 					fprintf(stdout, fmt, jitter_max);
8929 				}
8930 				if ((do_owd & OWD_MIN) && nowd) {
8931 					if (format & PARSE)
8932 						strcpy(fmt,
8933 						       P_OWD_MIN_FMT_BRIEF);
8934 					else
8935 						strcpy(fmt, OWD_MIN_FMT_BRIEF);
8936 					fprintf(stdout, fmt, owd_min);
8937 				}
8938 				if ((do_owd & OWD_AVG) && nowd) {
8939 					if (format & PARSE)
8940 						strcpy(fmt,
8941 						       P_OWD_AVG_FMT_BRIEF);
8942 					else
8943 						strcpy(fmt, OWD_AVG_FMT_BRIEF);
8944 					fprintf(stdout, fmt, owd_avg/nowd);
8945 				}
8946 				if ((do_owd & OWD_MAX) && nowd) {
8947 					if (format & PARSE)
8948 						strcpy(fmt,
8949 						       P_OWD_MAX_FMT_BRIEF);
8950 					else
8951 						strcpy(fmt, OWD_MAX_FMT_BRIEF);
8952 					fprintf(stdout, fmt, owd_max);
8953 				}
8954 			}
8955 			else {
8956 				if (*ident)
8957 					fprintf(stdout, "%s: ", ident + 1);
8958 				if (format & PARSE)
8959 					strcpy(fmt, P_PERF_FMT_BRIEF);
8960 				else
8961 					strcpy(fmt, PERF_FMT_BRIEF);
8962 				fprintf(stdout, fmt,
8963 					MB, realt, (double)nbytes/realt/125000,
8964 					srvr_cpu_util, cpu_util);
8965 				if (!(format & NODROPS)) {
8966 					if (format & PARSE)
8967 						strcpy(fmt, P_DROP_FMT_BRIEF);
8968 					else
8969 						strcpy(fmt, DROP_FMT_BRIEF);
8970 					fprintf(stdout, fmt,
8971 						(int64_t)(((srvr_MB - MB)
8972 							*1024*1024)
8973 								/buflen + 0.5),
8974 						(uint64_t)((srvr_MB*1024*1024)
8975 							/buflen + 0.5));
8976 				}
8977 				if (!(format & NOPERCENTLOSS)) {
8978 					fractloss = ((srvr_MB != 0.0) ?
8979 						1 - MB/srvr_MB : 0.0);
8980 					if (format & PARSE)
8981 						strcpy(fmt, P_LOSS_FMT_BRIEF);
8982 					else if ((fractloss != 0.0) &&
8983 						 (fractloss < 0.001))
8984 						strcpy(fmt, LOSS_FMT_BRIEF5);
8985 					else
8986 						strcpy(fmt, LOSS_FMT_BRIEF);
8987 					fprintf(stdout, fmt, fractloss * 100);
8988 				}
8989 				if (format & XMITSTATS) {
8990 					if (format & PARSE)
8991 						strcpy(fmt, P_PERF_FMT_BRIEF3);
8992 					else
8993 						strcpy(fmt, PERF_FMT_BRIEF3);
8994 					fprintf(stdout, fmt, srvr_MB);
8995 				}
8996 				if ((do_jitter & JITTER_MIN) && njitter) {
8997 					if (format & PARSE)
8998 						strcpy(fmt,
8999 						       P_JITTER_MIN_FMT_BRIEF);
9000 					else
9001 						strcpy(fmt,
9002 						       JITTER_MIN_FMT_BRIEF);
9003 					fprintf(stdout, fmt, jitter_min);
9004 				}
9005 				if ((do_jitter & JITTER_AVG) && njitter) {
9006 					if (format & PARSE)
9007 						strcpy(fmt,
9008 						       P_JITTER_AVG_FMT_BRIEF);
9009 					else
9010 						strcpy(fmt,
9011 						       JITTER_AVG_FMT_BRIEF);
9012 					fprintf(stdout, fmt,
9013 						jitter_avg/njitter);
9014 				}
9015 				if ((do_jitter & JITTER_MAX) && njitter) {
9016 					if (format & PARSE)
9017 						strcpy(fmt,
9018 						       P_JITTER_MAX_FMT_BRIEF);
9019 					else
9020 						strcpy(fmt,
9021 						       JITTER_MAX_FMT_BRIEF);
9022 					fprintf(stdout, fmt, jitter_max);
9023 				}
9024 				if ((do_owd & OWD_MIN) && nowd) {
9025 					if (format & PARSE)
9026 						strcpy(fmt,
9027 						       P_OWD_MIN_FMT_BRIEF);
9028 					else
9029 						strcpy(fmt, OWD_MIN_FMT_BRIEF);
9030 					fprintf(stdout, fmt, owd_min);
9031 				}
9032 				if ((do_owd & OWD_AVG) && nowd) {
9033 					if (format & PARSE)
9034 						strcpy(fmt,
9035 						       P_OWD_AVG_FMT_BRIEF);
9036 					else
9037 						strcpy(fmt, OWD_AVG_FMT_BRIEF);
9038 					fprintf(stdout, fmt, owd_avg/nowd);
9039 				}
9040 				if ((do_owd & OWD_MAX) && nowd) {
9041 					if (format & PARSE)
9042 						strcpy(fmt,
9043 						       P_OWD_MAX_FMT_BRIEF);
9044 					else
9045 						strcpy(fmt, OWD_MAX_FMT_BRIEF);
9046 					fprintf(stdout, fmt, owd_max);
9047 				}
9048 			}
9049 			fprintf(stdout, "\n");
9050 		}
9051 		else
9052 			if (trans) {
9053 				if ((retransinfo > 0) &&
9054 				    (!(format & NORETRANS))) {
9055 					if (format & DEBUGRETRANS) {
9056 					    sretrans = get_retrans(-1, &tcpinf);
9057 					    fprintf(stdout,
9058 						"report system retrans = %d\n",
9059 						sretrans);
9060 					}
9061 				}
9062 				if (*ident)
9063 					fprintf(stdout, "%s: ", ident + 1);
9064 				if (format & PARSE)
9065 					strcpy(fmt, P_PERF_FMT_BRIEF);
9066 				else
9067 					strcpy(fmt, PERF_FMT_BRIEF);
9068 				fprintf(stdout, fmt,
9069 					srvr_MB, srvr_realt, srvr_Mbps,
9070 					cpu_util, srvr_cpu_util);
9071 				if ((nstream > 1) && (retransinfo == 1) &&
9072 				    total_retrans && !(format & NORETRANS) &&
9073 				    (brief & BRIEF_RETRANS_STREAMS)) {
9074 					if (format & PARSE) {
9075 					    fprintf(stdout, P_RETRANS_FMT_BRIEF,
9076 						    "", total_retrans);
9077 					    fprintf(stdout,
9078 						    P_RETRANS_FMT_STREAMS,
9079 						    nretrans[1]);
9080 					}
9081 					else {
9082 					    fprintf(stdout,
9083 						    RETRANS_FMT_BRIEF_STR1,
9084 						    total_retrans,
9085 						    nretrans[1]);
9086 					}
9087 					for ( stream_idx = 2;
9088 					      stream_idx <= nstream;
9089 					      stream_idx++ ) {
9090 					    fprintf(stdout, "+%d",
9091 						    nretrans[stream_idx]);
9092 					}
9093 					if (!(format & PARSE))
9094 					    fprintf(stdout,
9095 						    RETRANS_FMT_BRIEF_STR2);
9096 				}
9097 				else if ((retransinfo > 0) &&
9098 				    (!(format & NORETRANS))) {
9099 					if (format & PARSE)
9100 						fprintf(stdout,
9101 							P_RETRANS_FMT_BRIEF,
9102 							retransinfo == 1 ?
9103 								"" : "host-",
9104 							total_retrans);
9105 					else
9106 						fprintf(stdout,
9107 							RETRANS_FMT_BRIEF,
9108 							total_retrans,
9109 							retransinfo == 1 ?
9110 								"" : "host-");
9111 				}
9112 #if defined(linux)
9113 				if ((nstream > 1) && cwndinfo &&
9114 				    (retransinfo == 1) &&
9115 				    total_snd_cwnd && !(format & NOCWND) &&
9116 				    (brief & BRIEF_CWND_STREAMS)) {
9117 					if (format & PARSE) {
9118 					    fprintf(stdout, P_CWND_FMT_BRIEF,
9119 						    total_snd_cwnd);
9120 					    fprintf(stdout,
9121 						    P_CWND_FMT_STREAMS,
9122 						    cwnd[1]);
9123 					}
9124 					else {
9125 					    fprintf(stdout,
9126 						    CWND_FMT_BRIEF_STR1,
9127 						    total_snd_cwnd,
9128 						    cwnd[1]);
9129 					}
9130 					for ( stream_idx = 2;
9131 					      stream_idx <= nstream;
9132 					      stream_idx++ ) {
9133 					    fprintf(stdout, "+%d",
9134 						    cwnd[stream_idx]);
9135 					}
9136 					if (!(format & PARSE))
9137 					    fprintf(stdout,
9138 						    CWND_FMT_BRIEF_STR2);
9139 				}
9140 				else if (cwndinfo && (!(format & NOCWND))) {
9141 					if (format & PARSE)
9142 						fprintf(stdout,
9143 							P_CWND_FMT_BRIEF,
9144 							total_snd_cwnd);
9145 					else
9146 						fprintf(stdout,
9147 							CWND_FMT_BRIEF,
9148 							total_snd_cwnd);
9149 				}
9150 #endif
9151 				if (rtt && (format & WANTRTT)) {
9152 					if (format & PARSE)
9153 						strcpy(fmt, P_RTT_FMT_BRIEF);
9154 					else
9155 						strcpy(fmt, RTT_FMT_BRIEF);
9156 					fprintf(stdout, fmt, rtt);
9157 				}
9158 				if ((do_owd & OWD_MIN) && nowd) {
9159 					if (format & PARSE)
9160 						strcpy(fmt,
9161 						       P_OWD_MIN_FMT_BRIEF);
9162 					else
9163 						strcpy(fmt, OWD_MIN_FMT_BRIEF);
9164 					fprintf(stdout, fmt, owd_min);
9165 				}
9166 				if ((do_owd & OWD_AVG) && nowd) {
9167 					if (format & PARSE)
9168 						strcpy(fmt,
9169 						       P_OWD_AVG_FMT_BRIEF);
9170 					else
9171 						strcpy(fmt, OWD_AVG_FMT_BRIEF);
9172 					fprintf(stdout, fmt, owd_avg/nowd);
9173 				}
9174 				if ((do_owd & OWD_MAX) && nowd) {
9175 					if (format & PARSE)
9176 						strcpy(fmt,
9177 						       P_OWD_MAX_FMT_BRIEF);
9178 					else
9179 						strcpy(fmt, OWD_MAX_FMT_BRIEF);
9180 					fprintf(stdout, fmt, owd_max);
9181 				}
9182 				fprintf(stdout, "\n");
9183 			}
9184 			else {
9185 				if (*ident)
9186 					fprintf(stdout, "%s: ", ident + 1);
9187 				if (format & PARSE)
9188 					strcpy(fmt, P_PERF_FMT_BRIEF);
9189 				else
9190 					strcpy(fmt, PERF_FMT_BRIEF);
9191 				fprintf(stdout, fmt,
9192 					MB, realt, (double)nbytes/realt/125000,
9193 					srvr_cpu_util, cpu_util);
9194 				if ((nstream > 1) && (retransinfo == 1) &&
9195 				    total_retrans && !(format & NORETRANS) &&
9196 				    (brief & BRIEF_RETRANS_STREAMS) &&
9197 				    (irvers >= 70101)) {
9198 					if (format & PARSE) {
9199 					    fprintf(stdout, P_RETRANS_FMT_BRIEF,
9200 						    "", total_retrans);
9201 					    fprintf(stdout,
9202 						    P_RETRANS_FMT_STREAMS,
9203 						    nretrans[1]);
9204 					}
9205 					else {
9206 					    fprintf(stdout,
9207 						    RETRANS_FMT_BRIEF_STR1,
9208 						    total_retrans,
9209 						    nretrans[1]);
9210 					}
9211 					for ( stream_idx = 2;
9212 					      stream_idx <= nstream;
9213 					      stream_idx++ ) {
9214 					    fprintf(stdout, "+%d",
9215 						    nretrans[stream_idx]);
9216 					}
9217 					if (!(format & PARSE))
9218 					    fprintf(stdout,
9219 						    RETRANS_FMT_BRIEF_STR2);
9220 				}
9221 				else if ((retransinfo > 0) &&
9222 				    (!(format & NORETRANS))) {
9223 					if (format & PARSE)
9224 						fprintf(stdout,
9225 							P_RETRANS_FMT_BRIEF,
9226 							retransinfo == 1 ?
9227 								"" : "host-",
9228 							total_retrans);
9229 					else
9230 						fprintf(stdout,
9231 							RETRANS_FMT_BRIEF,
9232 							total_retrans,
9233 							retransinfo == 1 ?
9234 								"" : "host-");
9235 				}
9236 				if ((nstream > 1) && cwndinfo &&
9237 				    (retransinfo == 1) &&
9238 				    total_snd_cwnd && !(format & NOCWND) &&
9239 				    (brief & BRIEF_CWND_STREAMS) &&
9240 				    (irvers >= 80001)) {
9241 					if (format & PARSE) {
9242 					    fprintf(stdout, P_CWND_FMT_BRIEF,
9243 						    total_snd_cwnd);
9244 					    fprintf(stdout,
9245 						    P_CWND_FMT_STREAMS,
9246 						    cwnd[1]);
9247 					}
9248 					else {
9249 					    fprintf(stdout,
9250 						    CWND_FMT_BRIEF_STR1,
9251 						    total_snd_cwnd,
9252 						    cwnd[1]);
9253 					}
9254 					for ( stream_idx = 2;
9255 					      stream_idx <= nstream;
9256 					      stream_idx++ ) {
9257 					    fprintf(stdout, "+%d",
9258 						    cwnd[stream_idx]);
9259 					}
9260 					if (!(format & PARSE))
9261 					    fprintf(stdout,
9262 						    CWND_FMT_BRIEF_STR2);
9263 				}
9264 				else if (cwndinfo && (!(format & NOCWND))) {
9265 					if (format & PARSE)
9266 						fprintf(stdout,
9267 							P_CWND_FMT_BRIEF,
9268 							total_snd_cwnd);
9269 					else
9270 						fprintf(stdout,
9271 							CWND_FMT_BRIEF,
9272 							total_snd_cwnd);
9273 				}
9274 				if (rtt && (format & WANTRTT)) {
9275 					if (format & PARSE)
9276 						strcpy(fmt, P_RTT_FMT_BRIEF);
9277 					else
9278 						strcpy(fmt, RTT_FMT_BRIEF);
9279 					fprintf(stdout, fmt, rtt);
9280 				}
9281 				if ((do_owd & OWD_MIN) && nowd) {
9282 					if (format & PARSE)
9283 						strcpy(fmt,
9284 						       P_OWD_MIN_FMT_BRIEF);
9285 					else
9286 						strcpy(fmt, OWD_MIN_FMT_BRIEF);
9287 					fprintf(stdout, fmt, owd_min);
9288 				}
9289 				if ((do_owd & OWD_AVG) && nowd) {
9290 					if (format & PARSE)
9291 						strcpy(fmt,
9292 						       P_OWD_AVG_FMT_BRIEF);
9293 					else
9294 						strcpy(fmt, OWD_AVG_FMT_BRIEF);
9295 					fprintf(stdout, fmt, owd_avg/nowd);
9296 				}
9297 				if ((do_owd & OWD_MAX) && nowd) {
9298 					if (format & PARSE)
9299 						strcpy(fmt,
9300 						       P_OWD_MAX_FMT_BRIEF);
9301 					else
9302 						strcpy(fmt, OWD_MAX_FMT_BRIEF);
9303 					fprintf(stdout, fmt, owd_max);
9304 				}
9305 				fprintf(stdout, "\n");
9306 			}
9307 	}
9308 	else {
9309 		if (brief && !clientserver) {
9310 			if (brief < 0)
9311 				fprintf(stdout, "\n");
9312 			if (*ident)
9313 				fprintf(stdout, "%s: ", ident + 1);
9314 			fprintf(stdout, PERF_FMT_BRIEF2 "\n", MB,
9315 				realt, (double)nbytes/realt/125000, cpu_util,
9316 				trans?"TX":"RX");
9317 		}
9318 	}
9319 
9320 cleanup:
9321 	if (clientserver) {
9322 		if (client) {
9323 			itimer.it_value.tv_sec = SRVR_INFO_TIMEOUT;
9324 			itimer.it_value.tv_usec = 0;
9325 			setitimer(ITIMER_REAL, &itimer, 0);
9326 			if (brief <= 0)
9327 				fputs("\n", stdout);
9328 			if (brief <= 0) {
9329 				if (got_srvr_output) {
9330 					fputs(srvrbuf, stdout);
9331 				}
9332 			}
9333 			else {
9334 				while (fgets(buf, mallocsize, stdin)) {
9335 					setitimer(ITIMER_REAL, &itimer, 0);
9336 					fputs(buf, stdout);
9337 				}
9338 			}
9339 			itimer.it_value.tv_sec = 0;
9340 			itimer.it_value.tv_usec = 0;
9341 			setitimer(ITIMER_REAL, &itimer, 0);
9342 			fflush(stdout);
9343 			close(0);
9344 		}
9345 		else {
9346 			fflush(stdout);
9347 			close(1);
9348 			if (!inetd) {
9349 				dup(savestdout);
9350 				close(savestdout);
9351 				fflush(stderr);
9352 				if (!nofork) {
9353 					close(2);
9354 					dup(1);
9355 				}
9356 			}
9357 		}
9358 		fclose(ctlconn);
9359 #ifdef DEBUG
9360 		if (irate && (format & DEBUGIRATE))
9361 			if (debugout) {
9362 				fprintf(debugout, "END nuttcp debug output\n");
9363 				fclose(debugout);
9364 			}
9365 #endif
9366 		if (!inetd)
9367 			close(fd[0]);
9368 		if (!udp && trans && (retransinfo > 0)) {
9369 			if (format & DEBUGRETRANS) {
9370 				sretrans = get_retrans(-1, &tcpinf);
9371 				fprintf(stdout, "final system retrans = %d\n",
9372 					sretrans);
9373 			}
9374 		}
9375 	}
9376 	if (clientserver && !client) {
9377 		for ( stream_idx = 1; stream_idx <= nstream; stream_idx++ ) {
9378 			fd[stream_idx] = -1;
9379 		}
9380 		if (multilink &&
9381 		    ((trans && !reverse) || (!trans && reverse)) && !udp) {
9382 			for ( stream_idx = 2; stream_idx <= nstream;
9383 			      stream_idx++ ) {
9384 				res[stream_idx] = NULL;
9385 			}
9386 		}
9387 		itimer.it_value.tv_sec = 0;
9388 		itimer.it_value.tv_usec = 0;
9389 		itimer.it_interval.tv_sec = 0;
9390 		itimer.it_interval.tv_usec = 0;
9391 		setitimer(ITIMER_REAL, &itimer, 0);
9392 		signal(SIGALRM, SIG_DFL);
9393 		bzero((char *)&frominet, sizeof(frominet));
9394 		bzero((char *)&clientaddr, sizeof(clientaddr));
9395 #ifdef AF_INET6
9396 		bzero((char *)&clientaddr6, sizeof(clientaddr6));
9397 		clientscope6 = 0;
9398 #endif
9399 		cput = 0.000001;
9400 		realt = 0.000001;
9401 		nbytes = 0;
9402 		ntbytes = 0;
9403 		ntbytesc = 0;
9404 		chk_nbytes = 0;
9405 		numCalls = 0;
9406 /*		Don't re-initialize buflen since it's used to		*/
9407 /*		determine if we need to change the buffer memory	*/
9408 /*		allocation for the next client data stream request	*/
9409 /*		buflen = 64 * 1024;					*/
9410 /*		if (udp) buflen = DEFAULTUDPBUFLEN;			*/
9411 		nbuf = 0;
9412 		sendwin = origsendwin;
9413 		rcvwin = origrcvwin;
9414 		b_flag = 1;
9415 		rate = MAXRATE;
9416 		maxburst = 1;
9417 		nburst = 1;
9418 		irate = 0;
9419 		iratesss = 0;
9420 		irate_cum_nsec = 0.0;
9421 		af3 = 0;
9422 		timeout = 0.0;
9423 		interval = 0.0;
9424 		chk_interval = 0.0;
9425 		chk_idle_data = 0.0;
9426 		datamss = 0;
9427 		tos = 0;
9428 		nodelay = 0;
9429 		do_poll = 0;
9430 		pbytes = 0;
9431 		ptbytes = 0;
9432 		ident[0] = '\0';
9433 		intr = 0;
9434 		abortconn = 0;
9435 		ipad_stride.ip32 = 0;
9436 		port = 5101;
9437 		srcport = 0;
9438 		trans = 0;
9439 		braindead = 0;
9440 		udp = 0;
9441 		udplossinfo = 0;
9442 		do_jitter = 0;
9443 		do_owd = 0;
9444 		retransinfo = 0;
9445 		init_pkt_cwnd = 0;
9446 		sss_pkt_cwnd = 0;
9447 		cwndinfo = 0;
9448 		force_retrans = 0;
9449 		rtt = 0.0;
9450 		which_rt = 1;
9451 		pretrans = 0;
9452 		sretrans = 0;
9453 		got_srvr_output = 0;
9454 		reading_srvr_info = 0;
9455 		reverse = 0;
9456 		format = 0;
9457 		traceroute = 0;
9458 		multicast = 0;
9459 		mc_addr = NULL;
9460 		ssm = -1;
9461 		skip_data = 0;
9462 		host3 = NULL;
9463 		thirdparty = 0;
9464 		ctlport3 = 0;
9465 		nbuf_bytes = 0;
9466 		rate_pps = 0;
9467 		brief = 0;
9468 		done = 0;
9469 		got_begin = 0;
9470 		two_bod = 0;
9471 		handle_urg = 0;
9472 		for ( stream_idx = 0; stream_idx <= nstream; stream_idx++ ) {
9473 			if (res[stream_idx]) {
9474 				freeaddrinfo(res[stream_idx]);
9475 				res[stream_idx] = NULL;
9476 			}
9477 			nretrans[stream_idx] = 0;
9478 			iretrans[stream_idx] = 0;
9479 			cwnd[stream_idx] = 0;
9480 		}
9481 		nstream = 1;
9482 		multilink = 0;
9483 		if (!oneshot)
9484 			goto doit;
9485 		exit(0);
9486 	}
9487 
9488 	if (multilink) {
9489 		for ( stream_idx = 2; stream_idx <= nstream; stream_idx++ ) {
9490 			res[stream_idx] = NULL;
9491 		}
9492 	}
9493 	for ( stream_idx = 0; stream_idx <= nstream; stream_idx++ ) {
9494 		if (res[stream_idx]) {
9495 			freeaddrinfo(res[stream_idx]);
9496 			res[stream_idx] = NULL;
9497 		}
9498 	}
9499 
9500 	exit(0);
9501 
9502 usage:
9503 	fprintf(stdout, Usage);
9504 	exit(1);
9505 }
9506 
9507 static void
err(char * s)9508 err( char *s )
9509 {
9510 	long flags, saveflags;
9511 
9512 	fprintf(stderr, "nuttcp%s%s: v%d.%d.%d%s: Error: ", trans?"-t":"-r",
9513 			ident, vers_major, vers_minor, vers_delta,
9514 			beta ? BETA_STR : "");
9515 	perror(s);
9516 	fprintf(stderr, "errno=%d\n", errno);
9517 	fflush(stderr);
9518 	if ((stream_idx > 0) && !done &&
9519 	    clientserver && !client && !trans && handle_urg) {
9520 		/* send 'A' for ABORT as urgent TCP data
9521 		 * on control connection (don't block) */
9522 		saveflags = fcntl(fd[0], F_GETFL, 0);
9523 		if (saveflags != -1) {
9524 			flags = saveflags | O_NONBLOCK;
9525 			fcntl(fd[0], F_SETFL, flags);
9526 		}
9527 		send(fd[0], "A", 1, MSG_OOB);
9528 		if (saveflags != -1) {
9529 			flags = saveflags;
9530 			fcntl(fd[0], F_SETFL, flags);
9531 		}
9532 	}
9533 	exit(1);
9534 }
9535 
9536 static void
mes(char * s)9537 mes( char *s )
9538 {
9539 	fprintf(stdout, "nuttcp%s%s: v%d.%d.%d%s: %s\n", trans?"-t":"-r", ident,
9540 			vers_major, vers_minor, vers_delta,
9541 			beta ? BETA_STR : "", s);
9542 }
9543 
9544 static void
errmes(char * s)9545 errmes( char *s )
9546 {
9547 	fprintf(stderr, "nuttcp%s%s: v%d.%d.%d%s: Error: ", trans?"-t":"-r",
9548 			ident, vers_major, vers_minor, vers_delta,
9549 			beta ? BETA_STR : "");
9550 	perror(s);
9551 	fprintf(stderr, "errno=%d\n", errno);
9552 	fflush(stderr);
9553 }
9554 
9555 void
pattern(register char * cp,register int cnt)9556 pattern( register char *cp, register int cnt )
9557 {
9558 	register char c;
9559 	c = 0;
9560 	while (cnt-- > 0) {
9561 		while (!isprint((c&0x7F)))  c++;
9562 		*cp++ = (c++&0x7F);
9563 	}
9564 }
9565 
9566 void
get_timeofday(struct timeval * tv,struct timezone * tz)9567 get_timeofday( struct timeval *tv, struct timezone *tz )
9568 {
9569 #ifdef HAVE_CLOCK_GETTIME
9570 	struct timespec tod;
9571 	clockid_t clk_id;
9572 
9573 #if defined(_POSIX_MONOTONIC_CLOCK) || defined(__CYGWIN__)
9574 	if (do_owd) {
9575 		clk_id = CLOCK_REALTIME;
9576 	}
9577 	else {
9578 		clk_id = CLOCK_MONOTONIC;
9579 	}
9580 #else	/* !(defined(_POSIX_MONOTONIC_CLOCK) || defined(__CYGWIN__)) */
9581 	clk_id = CLOCK_REALTIME;
9582 #endif	/* defined(_POSIX_MONOTONIC_CLOCK) || defined(__CYGWIN__) */
9583 
9584 	clock_gettime( clk_id, &tod );
9585 	tv->tv_sec  = tod.tv_sec;
9586 	tv->tv_usec = tod.tv_nsec / 1000;
9587 
9588 #else	/* !HAVE_CLOCK_GETTIME */
9589 	gettimeofday( tv, tz );
9590 #endif	/* HAVE_CLOCK_GETTIME */
9591 
9592 	return;
9593 }
9594 
9595 /*
9596  *			P R E P _ T I M E R
9597  */
9598 void
prep_timer()9599 prep_timer()
9600 {
9601 	get_timeofday(&time0, (struct timezone *)0);
9602 	timep.tv_sec = time0.tv_sec;
9603 	timep.tv_usec = time0.tv_usec;
9604 	timepk.tv_sec = time0.tv_sec;
9605 	timepk.tv_usec = time0.tv_usec;
9606 	getrusage(RUSAGE_SELF, &ru0);
9607 }
9608 
9609 /*
9610  *			R E A D _ T I M E R
9611  *
9612  */
9613 double
read_timer(char * str,int len)9614 read_timer( char *str, int len )
9615 {
9616 	struct timeval timedol;
9617 	struct rusage ru1;
9618 	struct timeval td;
9619 	struct timeval tend, tstart;
9620 	char line[132];
9621 
9622 	getrusage(RUSAGE_SELF, &ru1);
9623 	get_timeofday(&timedol, (struct timezone *)0);
9624 	prusage(&ru0, &ru1, &timedol, &time0, line);
9625 	(void)strncpy( str, line, len );
9626 
9627 	/* Get real time */
9628 	tvsub( &td, &timedol, &time0 );
9629 	realt = td.tv_sec + ((double)td.tv_usec) / 1000000;
9630 
9631 	/* Get CPU time (user+sys) */
9632 	tvadd( &tend, &ru1.ru_utime, &ru1.ru_stime );
9633 	tvadd( &tstart, &ru0.ru_utime, &ru0.ru_stime );
9634 	tvsub( &td, &tend, &tstart );
9635 	cput = td.tv_sec + ((double)td.tv_usec) / 1000000;
9636 	if (cput < 0.00001)  cput = 0.00001;
9637 	return( cput );
9638 }
9639 
9640 static void
prusage(register struct rusage * r0,register struct rusage * r1,struct timeval * e,struct timeval * b,char * outp)9641 prusage( register struct rusage *r0, register struct rusage *r1, struct timeval *e, struct timeval *b, char *outp )
9642 {
9643 	struct timeval tdiff;
9644 	register time_t t;
9645 	register char *cp;
9646 	register int i;
9647 	int ms;
9648 
9649 	t = (r1->ru_utime.tv_sec-r0->ru_utime.tv_sec)*100+
9650 	    (r1->ru_utime.tv_usec-r0->ru_utime.tv_usec)/10000+
9651 	    (r1->ru_stime.tv_sec-r0->ru_stime.tv_sec)*100+
9652 	    (r1->ru_stime.tv_usec-r0->ru_stime.tv_usec)/10000;
9653 	ms =  (e->tv_sec-b->tv_sec)*100 + (e->tv_usec-b->tv_usec)/10000;
9654 
9655 #define END(x)	{ while (*x) x++; }
9656 
9657 	if (format & PARSE)
9658 		cp = "user=%U system=%S elapsed=%E cpu=%P memory=%Xi+%Dd-%Mmaxrss io=%F+%Rpf swaps=%Ccsw";
9659 	else
9660 		cp = "%Uuser %Ssys %Ereal %P %Xi+%Dd %Mmaxrss %F+%Rpf %Ccsw";
9661 
9662 	for ( ; *cp; cp++ ) {
9663 		if (*cp != '%')
9664 			*outp++ = *cp;
9665 		else if (cp[1]) switch(*++cp) {
9666 
9667 		case 'U':
9668 			tvsub(&tdiff, &r1->ru_utime, &r0->ru_utime);
9669 			sprintf(outp, "%ld.%01ld", (long)tdiff.tv_sec, (long)tdiff.tv_usec/100000);
9670 			END(outp);
9671 			break;
9672 
9673 		case 'S':
9674 			tvsub(&tdiff, &r1->ru_stime, &r0->ru_stime);
9675 			sprintf(outp, "%ld.%01ld", (long)tdiff.tv_sec, (long)tdiff.tv_usec/100000);
9676 			END(outp);
9677 			break;
9678 
9679 		case 'E':
9680 			psecs(ms / 100, outp);
9681 			END(outp);
9682 			break;
9683 
9684 		case 'P':
9685 			sprintf(outp, "%d%%", (int) (t*100 / ((ms ? ms : 1))));
9686 			END(outp);
9687 			break;
9688 
9689 		case 'W':
9690 			i = r1->ru_nswap - r0->ru_nswap;
9691 			sprintf(outp, "%d", i);
9692 			END(outp);
9693 			break;
9694 
9695 		case 'X':
9696 			sprintf(outp, "%ld", t == 0 ? 0 : (r1->ru_ixrss-r0->ru_ixrss)/t);
9697 			END(outp);
9698 			break;
9699 
9700 		case 'D':
9701 			sprintf(outp, "%ld", t == 0 ? 0 :
9702 			    (r1->ru_idrss+r1->ru_isrss-(r0->ru_idrss+r0->ru_isrss))/t);
9703 			END(outp);
9704 			break;
9705 
9706 		case 'K':
9707 			sprintf(outp, "%ld", t == 0 ? 0 :
9708 			    ((r1->ru_ixrss+r1->ru_isrss+r1->ru_idrss) -
9709 			    (r0->ru_ixrss+r0->ru_idrss+r0->ru_isrss))/t);
9710 			END(outp);
9711 			break;
9712 
9713 		case 'M':
9714 			sprintf(outp, "%ld", r1->ru_maxrss/2);
9715 			END(outp);
9716 			break;
9717 
9718 		case 'F':
9719 			sprintf(outp, "%ld", r1->ru_majflt-r0->ru_majflt);
9720 			END(outp);
9721 			break;
9722 
9723 		case 'R':
9724 			sprintf(outp, "%ld", r1->ru_minflt-r0->ru_minflt);
9725 			END(outp);
9726 			break;
9727 
9728 		case 'I':
9729 			sprintf(outp, "%ld", r1->ru_inblock-r0->ru_inblock);
9730 			END(outp);
9731 			break;
9732 
9733 		case 'O':
9734 			sprintf(outp, "%ld", r1->ru_oublock-r0->ru_oublock);
9735 			END(outp);
9736 			break;
9737 		case 'C':
9738 			sprintf(outp, "%ld+%ld", r1->ru_nvcsw-r0->ru_nvcsw,
9739 				r1->ru_nivcsw-r0->ru_nivcsw);
9740 			END(outp);
9741 			break;
9742 		}
9743 	}
9744 	*outp = '\0';
9745 }
9746 
9747 static void
tvadd(struct timeval * tsum,struct timeval * t0,struct timeval * t1)9748 tvadd( struct timeval *tsum, struct timeval *t0, struct timeval *t1 )
9749 {
9750 
9751 	tsum->tv_sec = t0->tv_sec + t1->tv_sec;
9752 	tsum->tv_usec = t0->tv_usec + t1->tv_usec;
9753 	if (tsum->tv_usec > 1000000)
9754 		tsum->tv_sec++, tsum->tv_usec -= 1000000;
9755 }
9756 
9757 static void
tvsub(struct timeval * tdiff,struct timeval * t1,struct timeval * t0)9758 tvsub( struct timeval *tdiff, struct timeval *t1, struct timeval *t0 )
9759 {
9760 
9761 	tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
9762 	tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
9763 	if (tdiff->tv_usec < 0)
9764 		tdiff->tv_sec--, tdiff->tv_usec += 1000000;
9765 }
9766 
9767 static void
psecs(long l,register char * cp)9768 psecs( long l, register char *cp )
9769 {
9770 	register int i;
9771 
9772 	i = l / 3600;
9773 	if (i) {
9774 		sprintf(cp, "%d:", i);
9775 		END(cp);
9776 		i = l % 3600;
9777 		sprintf(cp, "%d%d", (i/60) / 10, (i/60) % 10);
9778 		END(cp);
9779 	}
9780 	else {
9781 		i = l;
9782 		sprintf(cp, "%d", i / 60);
9783 		END(cp);
9784 	}
9785 	i %= 60;
9786 	*cp++ = ':';
9787 	sprintf(cp, "%d%d", i / 10, i % 10);
9788 }
9789 
9790 /*
9791  *			N R E A D
9792  */
9793 int
Nread(int fd,char * buf,int count)9794 Nread( int fd, char *buf, int count )
9795 {
9796 	struct sockaddr_storage from;
9797 	socklen_t len = sizeof(from);
9798 	struct timeval timed;	/* time delta */
9799 	register int cnt;
9800 	if (udp) {
9801 		cnt = recvfrom( fd, buf, count, 0, (struct sockaddr *)&from, &len );
9802 		numCalls++;
9803 	}
9804 	else {
9805 		if (b_flag)
9806 			cnt = mread( fd, buf, count );	/* fill buf */
9807 		else {
9808 			cnt = read( fd, buf, count );
9809 			numCalls++;
9810 		}
9811 	}
9812 	if (do_owd && (cnt > 4)) {
9813 		uint32_t secs, usecs;
9814 
9815 		/* get transmitter timestamp */
9816 		bcopy(buf + 8, &secs, 4);
9817 		bcopy(buf + 12, &usecs, 4);
9818 		timetx.tv_sec = ntohl(secs);
9819 		timetx.tv_usec = ntohl(usecs);
9820 		get_timeofday(&timerx, (struct timezone *)0);
9821 		tvsub( &timed, &timerx, &timetx );
9822 		owd = timed.tv_sec*1000 + ((double)timed.tv_usec)/1000;
9823 		nowd++;
9824 		if (owd < owd_min)
9825 			owd_min = owd;
9826 		if (owd > owd_max)
9827 			owd_max = owd;
9828 		owd_avg += owd;
9829 		nowdi++;
9830 		if (owd < owd_mini)
9831 			owd_mini = owd;
9832 		if (owd > owd_maxi)
9833 			owd_maxi = owd;
9834 		owd_avgi += owd;
9835 	}
9836 	return(cnt);
9837 }
9838 
9839 /*
9840  *			N W R I T E
9841  */
9842 int
Nwrite(int fd,char * buf,int count)9843 Nwrite( int fd, char *buf, int count )
9844 {
9845 	struct timeval timedol;
9846 	struct timeval td;
9847 	register int cnt = 0;
9848 	double deltat, delta0;
9849 	double pktdelay = 0;
9850 	int pktdelay_sec, pktdelay_usec, sssdelay;
9851 
9852 	if (irate) {
9853 		sssdelay = 0;
9854 		/* Get real time */
9855 		get_timeofday(&timedol, (struct timezone *)0);
9856 		tvsub( &td, &timedol, &timepk );
9857 		deltat = td.tv_sec + ((double)td.tv_usec) / 1000000;
9858 
9859 		if (deltat >= (1 + maxburst)*pkt_time) {
9860 			timepk.tv_sec = timedol.tv_sec;
9861 			timepk.tv_usec = timedol.tv_usec;
9862 			irate_cum_nsec = 0;
9863 			deltat = 0.0;
9864 			nburst = 1;
9865 		}
9866 
9867 		if (nburst++ >= maxburst) {
9868 			if (iratesss && cwndinfo) {
9869 				/* note iratesss only supported for 1 stream */
9870 				tvsub( &td, &timedol, &time0 );
9871 				delta0 = td.tv_sec + ((double)td.tv_usec)
9872 							/ 1000000;
9873 				if (delta0 > which_rt*rtt/1000) {
9874 					which_rt++;
9875 					sss_pkt_cwnd = (cwnd[1] + 1)*1024/datamss;
9876 					sss_pkt_cwnd *= 2;
9877 				}
9878 				pktdelay = rtt/1000/sss_pkt_cwnd*count/datamss;
9879 				if (pktdelay <
9880 					    maxburst*(double)count/rate/125) {
9881 					pktdelay =
9882 						maxburst*(double)count/rate/125;
9883 					iratesss = 0;
9884 				}
9885 				else {
9886 					sssdelay = 1;
9887 				}
9888 			}
9889 			else {
9890 				pktdelay = maxburst*(double)count/rate/125;
9891 			}
9892 			while ((pktdelay > deltat) && !intr) {
9893 				/* Get real time */
9894 				get_timeofday(&timedol, (struct timezone *)0);
9895 				tvsub( &td, &timedol, &timepk );
9896 				deltat = td.tv_sec + ((double)td.tv_usec)
9897 							/ 1000000;
9898 			}
9899 		}
9900 
9901 		if (nburst > maxburst) {
9902 			if (sssdelay) {
9903 				pktdelay_sec = pktdelay;
9904 				pktdelay_usec = (pktdelay - pktdelay_sec)
9905 							*1000000;
9906 				timepk.tv_usec += pktdelay_usec;
9907 				if (timepk.tv_usec >= 1000000) {
9908 					timepk.tv_usec -= 1000000;
9909 					timepk.tv_sec += 1;
9910 				}
9911 				timepk.tv_sec += pktdelay_sec;
9912 			}
9913 			else {
9914 				irate_cum_nsec += maxburst*irate_pk_nsec;
9915 				while (irate_cum_nsec >= 1000.0) {
9916 					irate_cum_nsec -= 1000.0;
9917 					timepk.tv_usec++;
9918 				}
9919 				timepk.tv_usec += maxburst*irate_pk_usec;
9920 				while (timepk.tv_usec >= 1000000) {
9921 					timepk.tv_usec -= 1000000;
9922 					timepk.tv_sec++;
9923 				}
9924 			}
9925 			nburst = 1;
9926 		}
9927 		if (intr && (!udp || (count != 4))) return(0);
9928 	}
9929 	else {
9930 		while ((double)nbytes/realt/125 > rate) {
9931 			/* Get real time */
9932 			get_timeofday(&timedol, (struct timezone *)0);
9933 			tvsub( &td, &timedol, &time0 );
9934 			realt = td.tv_sec + ((double)td.tv_usec) / 1000000;
9935 			if (realt <= 0.0)  realt = 0.000001;
9936 		}
9937 	}
9938 	if (do_owd && (count > 4)) {
9939 		uint32_t secs, usecs;
9940 
9941 		/* record transmitter timestamp in packet */
9942 		get_timeofday(&timedol, (struct timezone *)0);
9943 		secs = htonl(timedol.tv_sec);
9944 		usecs = htonl(timedol.tv_usec);
9945 		bcopy(&secs, buf + 8, 4);
9946 		bcopy(&usecs, buf + 12, 4);
9947 	}
9948 	if (udp) {
9949 again:
9950 		if (af == AF_INET) {
9951 			cnt = sendto( fd, buf, count, 0, (struct sockaddr *)&sinhim[stream_idx + 1], sizeof(sinhim[stream_idx + 1]) );
9952 		}
9953 #ifdef AF_INET6
9954 		else if (af == AF_INET6) {
9955 			cnt = sendto( fd, buf, count, 0, (struct sockaddr *)&sinhim6[stream_idx + 1], sizeof(sinhim6[stream_idx + 1]) );
9956 		}
9957 #endif
9958 		else {
9959 			err("unsupported AF");
9960 		}
9961 		numCalls++;
9962 		if (cnt<0 && errno == ENOBUFS) {
9963 			delay(18000);
9964 			errno = 0;
9965 			goto again;
9966 		}
9967 	}
9968 	else {
9969 #if defined(linux) && defined(DEBUG)
9970 		if (irate && (format & DEBUGIRATE) && debugout) {
9971 			struct timeval timewr;
9972 			double pktwrtime;
9973 			static int cnt = 0;
9974 
9975 			cnt++;
9976 			if (cnt == 1) {
9977 				fprintf(debugout, "count = %d, datamss = %d, "
9978 						  "pktxmit = %.8f, "
9979 						  "rtt = %.6f, maxburst = %d\n",
9980 					count, datamss,
9981 					(double)count/rate/125,
9982 					rtt/1000, maxburst);
9983 			}
9984 			get_timeofday(&timewr, (struct timezone *)0);
9985 			tvsub( &td, &timewr, &time0 );
9986 			pktwrtime = td.tv_sec + (double)td.tv_usec/1000000;
9987 			fprintf(debugout, "pktwrtime = %.6f, pktdelay = %.6f, "
9988 					  "sss_pkt_cwnd = %d, "
9989 					  "cur_pkt_cwnd = %d, iratesss = %d, "
9990 					  "which_rt = %d\n",
9991 					  pktwrtime, pktdelay,
9992 					  sss_pkt_cwnd,
9993 					  (cwnd[1] + 1)*1024/datamss, iratesss,
9994 					  which_rt);
9995 		}
9996 #endif
9997 		cnt = write( fd, buf, count );
9998 		numCalls++;
9999 	}
10000 	return(cnt);
10001 }
10002 
10003 int
delay(int us)10004 delay( int us )
10005 {
10006 	struct timeval tv;
10007 
10008 	tv.tv_sec = 0;
10009 	tv.tv_usec = us;
10010 	(void)select( 1, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
10011 	return(1);
10012 }
10013 
10014 /*
10015  *			M R E A D
10016  *
10017  * This function performs the function of a read(II) but will
10018  * call read(II) multiple times in order to get the requested
10019  * number of characters.  This can be necessary because
10020  * network connections don't deliver data with the same
10021  * grouping as it is written with.  Written by Robert S. Miles, BRL.
10022  */
10023 int
mread(int fd,register char * bufp,unsigned n)10024 mread( int fd, register char *bufp, unsigned n )
10025 {
10026 	register unsigned	count = 0;
10027 	register int		nread;
10028 
10029 	do {
10030 		nread = read(fd, bufp, n-count);
10031 		numCalls++;
10032 		if (nread < 0) {
10033 			if (errno != EINTR)
10034 				perror("nuttcp_mread");
10035 			return(-1);
10036 		}
10037 		if (nread == 0)
10038 			return((int)count);
10039 		count += (unsigned)nread;
10040 		bufp += nread;
10041 	 } while (count < n);
10042 
10043 	return((int)count);
10044 }
10045 
10046 /*
10047  *			M W R I T E
10048  *
10049  * This function performs the function of a write(II) but will
10050  * call write(II) multiple times in order to put the requested
10051  * number of characters.  This can be necessary because
10052  * piped connections may not be able to deliver data with
10053  * the full requested count.
10054  */
10055 int
mwrite(int fd,register char * bufp,unsigned n,int last_write)10056 mwrite( int fd, register char *bufp, unsigned n, int last_write )
10057 {
10058 	register unsigned	count = 0;
10059 	register int		nwrite;
10060 #if defined(linux)
10061 	long			flags;
10062 
10063 	if (directio && last_write) {
10064 		flags = fcntl(savestdout, F_GETFL, 0);
10065 		if (flags < 0)
10066 			errmes("fcntl get O_DIRECT");
10067 		else {
10068 			flags &= ~O_DIRECT;
10069 			if (fcntl(savestdout, F_SETFL, flags) < 0)
10070 				errmes("fcntl set O_DIRECT");
10071 		}
10072 	}
10073 #endif
10074 	do {
10075 		nwrite = write(fd, bufp, n-count);
10076 		numCalls++;
10077 		if (nwrite < 0) {
10078 			if (errno != EINTR)
10079 				perror("nuttcp_mwrite");
10080 			return(-1);
10081 		}
10082 		count += (unsigned)nwrite;
10083 		bufp += nwrite;
10084 	 } while (count < n);
10085 
10086 	return((int)count);
10087 }
10088 
10089 /*
10090  *			G E T O P T V A L P
10091  *
10092  * This function returns a character pointer to the option value
10093  * pointed at by argv and sets skiparg to 1 if the option and its
10094  * value were passed as separate arguments (otherwise it sets
10095  * skiparg to 0).  index is the position within argv where the
10096  * option value resides if the option was specified as a single
10097  * argument.  reqval indicates whether or not the option requires
10098  * a value
10099  */
10100 char *
getoptvalp(char ** argv,int index,int reqval,int * skiparg)10101 getoptvalp( char **argv, int index, int reqval, int *skiparg )
10102 {
10103 	struct sockaddr_storage dummy;
10104 	char **nextarg;
10105 
10106 	*skiparg = 0;
10107 	nextarg = argv + 1;
10108 
10109 	/* if there is a value in the current arg return it */
10110 	if (argv[0][index])
10111 		return(&argv[0][index]);
10112 
10113 	/* if there isn't a next arg return a pointer to the
10114 	   current arg value (which will be an empty string) */
10115 	if (*nextarg == NULL)
10116 		return(&argv[0][index]);
10117 
10118 	/* if the next arg is another option, and a value isn't
10119 	 * required, return a pointer to the current arg value
10120 	 * (which will be an empty string) */
10121 	if ((**nextarg == '-') && !reqval)
10122 		return(&argv[0][index]);
10123 
10124 	/* if there is an arg after the next arg and it is another
10125 	   option, return the next arg as the option value */
10126 	if (*(nextarg + 1) && (**(nextarg + 1) == '-')) {
10127 		*skiparg = 1;
10128 		return(*nextarg);
10129 	}
10130 
10131 	/* if the option requires a value, return the next arg
10132 	   as the option value */
10133 	if (reqval) {
10134 		*skiparg = 1;
10135 		return(*nextarg);
10136 	}
10137 
10138 	/* if the next arg is an Ipv4 address, return a pointer to the
10139 	   current arg value (which will be an empty string) */
10140 	if (inet_pton(AF_INET, *nextarg, &dummy) > 0)
10141 		return(&argv[0][index]);
10142 
10143 #ifdef AF_INET6
10144 	/* if the next arg is an Ipv6 address, return a pointer to the
10145 	   current arg value (which will be an empty string) */
10146 	if (inet_pton(AF_INET6, *nextarg, &dummy) > 0)
10147 		return(&argv[0][index]);
10148 #endif
10149 
10150 	/* if the next arg begins with an alphabetic character,
10151 	   assume it is a hostname and thus return a pointer to the
10152 	   current arg value (which will be an empty string).
10153 	   note all current options which don't require a value
10154 	   have numeric values (start with a digit) */
10155 	if (isalpha((int)(**nextarg)))
10156 		return(&argv[0][index]);
10157 
10158 	/* assume the next arg is the option value */
10159 	*skiparg = 1;
10160 
10161 	return(*nextarg);
10162 }
10163 
10164 #define PROC_SNMP		"/proc/net/snmp"
10165 #define PROC_BUF_LEN		256
10166 #define PROC_BUF_LEN2		128
10167 #define NETSTAT			"netstat"
10168 
10169 #if defined(linux)
10170 #define RETRANS			"segments retransmited"
10171 #define NETSTAT_DIR		"/bin/"
10172 #define NRETRANS_BEFORE
10173 #elif defined(__FreeBSD__)
10174 #define RETRANS			"retransmitted"
10175 #define NETSTAT_DIR		"/usr/bin/"
10176 #define NRETRANS_BEFORE
10177 #elif defined(__APPLE__) && defined(__MACH__)
10178 #define RETRANS			"retransmitted"
10179 #define NETSTAT_DIR		"/usr/sbin/"
10180 #define NRETRANS_BEFORE
10181 #elif defined(sparc)
10182 #define RETRANS			"tcpRetransSegs"
10183 #define NETSTAT_DIR		"/usr/bin/"
10184 #elif defined(sgi)
10185 #define RETRANS			"retransmitted"
10186 #define NETSTAT_DIR		"/usr/etc/"
10187 #define NRETRANS_BEFORE
10188 #elif defined(__CYGWIN__) || defined(_WIN32)
10189 #define RETRANS			"Segments Retransmitted"
10190 #define NETSTAT_DIR		""
10191 #else
10192 #define RETRANS			"retransmitted"
10193 #define NETSTAT_DIR		"/usr/bin/"
10194 #define NRETRANS_BEFORE
10195 #endif
10196 
10197 char	proc_buf[PROC_BUF_LEN];
10198 char	proc_buf2[PROC_BUF_LEN2];
10199 
get_retrans(int sockfd,struct STRUCT_TCPINFO * tcpinfo)10200 int get_retrans( int sockfd, struct STRUCT_TCPINFO *tcpinfo )
10201 {
10202 	FILE	*proc_snmp;
10203 	char	*cp, *cp2;
10204 	int	num_retrans;
10205 	int	pipefd[2];
10206 	int	pidstat;
10207 	pid_t	pid = 0;
10208 	pid_t	wait_pid;
10209 
10210 	if (retransinfo < 0)
10211 		return(0);
10212 
10213 #if defined(linux) && defined(TCPI_OPT_TIMESTAMPS)
10214 	if ((retransinfo <= 1) && (sockfd >= 0)) {
10215 		optlen = sizeof(*tcpinfo);
10216 		if (getsockopt(sockfd, SOL_TCP, TCP_INFO, (void *)tcpinfo,
10217 			       &optlen) == 0) {
10218 			if (optlen >= SIZEOF_TCP_INFO_RETRANS) {
10219 				retransinfo = 1;
10220 				cwndinfo = 1;
10221 				b_flag = 1;
10222 				return(tcpinfo->tcpi_total_retrans);
10223 			}
10224 		}
10225 		if (retransinfo == 1) {
10226 			retransinfo = -1;
10227 			cwndinfo = 0;
10228 			return(0);
10229 		}
10230 		retransinfo = 2;
10231 		cwndinfo = 0;
10232 	}
10233 #else
10234 	retransinfo = 2;
10235 	cwndinfo = 0;
10236 #endif
10237 
10238 	if ((retransinfo == 3) || (!(proc_snmp = fopen(PROC_SNMP, "r")))) {
10239 		retransinfo = 3;
10240 		cwndinfo = 0;
10241 		if (pipe(pipefd) != 0) {
10242 			retransinfo = -1;
10243 			cwndinfo = 0;
10244 			return(0);
10245 		}
10246 		if ((pid = fork()) == (pid_t)-1) {
10247 			perror("can't fork");
10248 			close(pipefd[0]);
10249 			close(pipefd[1]);
10250 			retransinfo = -1;
10251 			cwndinfo = 0;
10252 			return(0);
10253 		}
10254 		if (pid == 0) {
10255 			signal(SIGINT, SIG_DFL);
10256 			close(1);
10257 			close(2);
10258 			dup(pipefd[1]);
10259 			dup(pipefd[1]);
10260 			close(pipefd[0]);
10261 			close(pipefd[1]);
10262 			execl(NETSTAT_DIR NETSTAT, NETSTAT, "-s", NULL);
10263 			perror("execl failed");
10264 			fprintf(stderr, "failed to execute %s%s -s\n",
10265 				NETSTAT_DIR, NETSTAT);
10266 			fflush(stdout);
10267 			fflush(stderr);
10268 			exit(0);
10269 		}
10270 		close(pipefd[1]);
10271 		if (!(proc_snmp = fdopen(pipefd[0], "r"))) {
10272 			close(pipefd[0]);
10273 			retransinfo = -1;
10274 			cwndinfo = 0;
10275 			return(0);
10276 		}
10277 	}
10278 
10279 	errno = 0;
10280 	num_retrans = -1;
10281 	while (fgets(proc_buf, sizeof(proc_buf), proc_snmp)) {
10282 		if (retransinfo == 2) {
10283 			if (strncmp(proc_buf, "Tcp:", 4) != 0)
10284 				continue;
10285 			if ((!fgets(proc_buf2, sizeof(proc_buf2), proc_snmp))
10286 				|| (strncmp(proc_buf2, "Tcp:", 4) != 0))
10287 				break;
10288 			cp = proc_buf;
10289 			cp2 = proc_buf2;
10290 			while ((cp = strchr(cp, ' '))) {
10291 				while (*++cp == ' ')
10292 					;
10293 				if (!(*cp))
10294 					goto close;
10295 				if (!(cp2 = strchr(cp2, ' ')))
10296 					goto close;
10297 				while (*++cp2 == ' ')
10298 					;
10299 				if (!(*cp2))
10300 					goto close;
10301 				if (strncmp(cp, "RetransSegs", 11) == 0) {
10302 					if (!isdigit((int)(*cp2)))
10303 						goto close;
10304 					num_retrans = atoi(cp2);
10305 					goto close;
10306 				}
10307 				else
10308 					continue;
10309 			}
10310 		}
10311 		else {
10312 			if ((cp = strstr(proc_buf, RETRANS))) {
10313 #ifdef NRETRANS_BEFORE
10314 				num_retrans = atoi(proc_buf);
10315 #else
10316 				cp2 = strchr(cp, '=');
10317 				cp2++;
10318 				num_retrans = atoi(cp2);
10319 #endif
10320 				break;
10321 			}
10322 		}
10323 	}
10324 
10325 close:
10326 	fclose(proc_snmp);
10327 	if (retransinfo == 3) {
10328 		while ((wait_pid = wait(&pidstat)) != pid) {
10329 			if (wait_pid == (pid_t)-1) {
10330 				if (errno == ECHILD)
10331 					break;
10332 				err("wait failed");
10333 			}
10334 		}
10335 	}
10336 
10337 	if (num_retrans < 0) {
10338 		retransinfo = -1;
10339 		cwndinfo = 0;
10340 		return(0);
10341 	}
10342 
10343 	return(num_retrans);
10344 }
10345 
10346 #if defined(linux) && defined(TCPI_OPT_TIMESTAMPS)
10347 
10348 void
print_tcpinfo()10349 print_tcpinfo()
10350 {
10351 	fprintf(stdout, "state = %d, ca_state = %d, retransmits = %d, "
10352 			"unacked = %d, sacked = %d\n",
10353 		tcpinf.tcpinfo_state, tcpinf.tcpinfo_ca_state,
10354 		tcpinf.tcpinfo_retransmits, tcpinf.tcpinfo_unacked,
10355 		tcpinf.tcpinfo_sacked);
10356 	fprintf(stdout, "           lost = %d, retrans = %d, fackets = %d, "
10357 			"rtt = %d, rttvar = %d\n",
10358 		tcpinf.tcpinfo_lost, tcpinf.tcpinfo_retrans,
10359 		tcpinf.tcpinfo_fackets, tcpinf.tcpinfo_rtt,
10360 		tcpinf.tcpinfo_rttvar);
10361 	fprintf(stdout, "           snd_ssthresh = %d, snd_cwnd = %d, "
10362 			"total_retrans = %d\n",
10363 		tcpinf.tcpinfo_snd_ssthresh, tcpinf.tcpinfo_snd_cwnd,
10364 		tcpinf.tcpi_total_retrans);
10365 	return;
10366 }
10367 
10368 #endif
10369 
10370