xref: /iperf/src/iperf_util.c (revision e919e8c2)
17d375156SJon Dugan /*
202d411cbSBruce A. Mah  * iperf, Copyright (c) 2014, 2016, 2017, The Regents of the University of
3da9f046fSBruce A. Mah  * California, through Lawrence Berkeley National Laboratory (subject
4da9f046fSBruce A. Mah  * to receipt of any required approvals from the U.S. Dept. of
5da9f046fSBruce A. Mah  * Energy).  All rights reserved.
67d375156SJon Dugan  *
7da9f046fSBruce A. Mah  * If you have questions about your rights to use or distribute this
8da9f046fSBruce A. Mah  * software, please contact Berkeley Lab's Technology Transfer
9da9f046fSBruce A. Mah  * Department at [email protected].
10da9f046fSBruce A. Mah  *
11da9f046fSBruce A. Mah  * NOTICE.  This software is owned by the U.S. Department of Energy.
12da9f046fSBruce A. Mah  * As such, the U.S. Government has been granted for itself and others
13da9f046fSBruce A. Mah  * acting on its behalf a paid-up, nonexclusive, irrevocable,
14da9f046fSBruce A. Mah  * worldwide license in the Software to reproduce, prepare derivative
15da9f046fSBruce A. Mah  * works, and perform publicly and display publicly.  Beginning five
16da9f046fSBruce A. Mah  * (5) years after the date permission to assert copyright is obtained
17da9f046fSBruce A. Mah  * from the U.S. Department of Energy, and subject to any subsequent
18da9f046fSBruce A. Mah  * five (5) year renewals, the U.S. Government is granted for itself
19da9f046fSBruce A. Mah  * and others acting on its behalf a paid-up, nonexclusive,
20da9f046fSBruce A. Mah  * irrevocable, worldwide license in the Software to reproduce,
21da9f046fSBruce A. Mah  * prepare derivative works, distribute copies to the public, perform
22da9f046fSBruce A. Mah  * publicly and display publicly, and to permit others to do so.
23da9f046fSBruce A. Mah  *
24da9f046fSBruce A. Mah  * This code is distributed under a BSD style license, see the LICENSE
25da9f046fSBruce A. Mah  * file for complete information.
267d375156SJon Dugan  */
278a0b5a5dSsethdelliott /* iperf_util.c
288a0b5a5dSsethdelliott  *
298a0b5a5dSsethdelliott  * Iperf utility functions
308a0b5a5dSsethdelliott  *
318a0b5a5dSsethdelliott  */
3240050b7bSBruce A. Mah #include "iperf_config.h"
33b0b16b86SJon Dugan 
34b0b16b86SJon Dugan #include <stdio.h>
35a5e327b4SSuresh Sundriyal #include <signal.h>
36b0b16b86SJon Dugan #include <stdlib.h>
3798ce496bSjef #include <unistd.h>
38b0b16b86SJon Dugan #include <string.h>
39b5e0751fSJef Poskanzer #include <stdarg.h>
408a0b5a5dSsethdelliott #include <sys/select.h>
4198ce496bSjef #include <sys/types.h>
4298ce496bSjef #include <sys/time.h>
43056361fcSJef Poskanzer #include <sys/resource.h>
449a829841SBruce A. Mah #include <sys/utsname.h>
4598ce496bSjef #include <time.h>
468a0b5a5dSsethdelliott #include <errno.h>
4773b02f98SBruce A. Mah #include <fcntl.h>
488a0b5a5dSsethdelliott 
49b5e0751fSJef Poskanzer #include "cjson.h"
50e7ab564cSSami Farin #include "iperf.h"
51e7ab564cSSami Farin #include "iperf_api.h"
52e7ab564cSSami Farin 
53e7ab564cSSami Farin /*
54e7ab564cSSami Farin  * Read entropy from /dev/urandom
55e7ab564cSSami Farin  * Errors are fatal.
56e7ab564cSSami Farin  * Returns 0 on success.
57e7ab564cSSami Farin  */
readentropy(void * out,size_t outsize)58e7ab564cSSami Farin int readentropy(void *out, size_t outsize)
59e7ab564cSSami Farin {
60e7ab564cSSami Farin     static FILE *frandom;
61e7ab564cSSami Farin     static const char rndfile[] = "/dev/urandom";
62e7ab564cSSami Farin 
63e7ab564cSSami Farin     if (!outsize) return 0;
64e7ab564cSSami Farin 
65e7ab564cSSami Farin     if (frandom == NULL) {
66e7ab564cSSami Farin         frandom = fopen(rndfile, "rb");
67e7ab564cSSami Farin         if (frandom == NULL) {
68e7ab564cSSami Farin             iperf_errexit(NULL, "error - failed to open %s: %s\n",
69e7ab564cSSami Farin                           rndfile, strerror(errno));
70e7ab564cSSami Farin         }
71e7ab564cSSami Farin         setbuf(frandom, NULL);
72e7ab564cSSami Farin     }
73e7ab564cSSami Farin     if (fread(out, 1, outsize, frandom) != outsize) {
74e7ab564cSSami Farin         iperf_errexit(NULL, "error - failed to read %s: %s\n",
75e7ab564cSSami Farin                       rndfile,
76e7ab564cSSami Farin                       feof(frandom) ? "EOF" : strerror(errno));
77e7ab564cSSami Farin     }
78e7ab564cSSami Farin     return 0;
79e7ab564cSSami Farin }
80e7ab564cSSami Farin 
818a0b5a5dSsethdelliott 
82cbea72b6SPhil Levchenko /*
83cbea72b6SPhil Levchenko  * Fills buffer with repeating pattern (similar to pattern that used in iperf2)
84cbea72b6SPhil Levchenko  */
fill_with_repeating_pattern(void * out,size_t outsize)85cbea72b6SPhil Levchenko void fill_with_repeating_pattern(void *out, size_t outsize)
86cbea72b6SPhil Levchenko {
87cbea72b6SPhil Levchenko     size_t i;
88cbea72b6SPhil Levchenko     int counter = 0;
89cbea72b6SPhil Levchenko     char *buf = (char *)out;
90cbea72b6SPhil Levchenko 
91cbea72b6SPhil Levchenko     if (!outsize) return;
92cbea72b6SPhil Levchenko 
93cbea72b6SPhil Levchenko     for (i = 0; i < outsize; i++) {
94cbea72b6SPhil Levchenko         buf[i] = (char)('0' + counter);
95cbea72b6SPhil Levchenko         if (counter >= 9)
96cbea72b6SPhil Levchenko             counter = 0;
97cbea72b6SPhil Levchenko         else
98cbea72b6SPhil Levchenko             counter++;
99cbea72b6SPhil Levchenko     }
100cbea72b6SPhil Levchenko }
101cbea72b6SPhil Levchenko 
102cbea72b6SPhil Levchenko 
1032ab386bfSjef /* make_cookie
1048a0b5a5dSsethdelliott  *
1052ab386bfSjef  * Generate and return a cookie string
1068a0b5a5dSsethdelliott  *
1078a0b5a5dSsethdelliott  * Iperf uses this function to create test "cookies" which
1088a0b5a5dSsethdelliott  * server as unique test identifiers. These cookies are also
1098a0b5a5dSsethdelliott  * used for the authentication of stream connections.
110e7ab564cSSami Farin  * Assumes cookie has size (COOKIE_SIZE + 1) char's.
1118a0b5a5dSsethdelliott  */
112b0b16b86SJon Dugan 
113b0b16b86SJon Dugan void
make_cookie(const char * cookie)1143888e044SDavid Bar-On make_cookie(const char *cookie)
115b0b16b86SJon Dugan {
116e7ab564cSSami Farin     unsigned char *out = (unsigned char*)cookie;
117e7ab564cSSami Farin     size_t pos;
118e7ab564cSSami Farin     static const unsigned char rndchars[] = "abcdefghijklmnopqrstuvwxyz234567";
119b0b16b86SJon Dugan 
120e7ab564cSSami Farin     readentropy(out, COOKIE_SIZE);
121e7ab564cSSami Farin     for (pos = 0; pos < (COOKIE_SIZE - 1); pos++) {
122e7ab564cSSami Farin         out[pos] = rndchars[out[pos] % (sizeof(rndchars) - 1)];
123e7ab564cSSami Farin     }
124e7ab564cSSami Farin     out[pos] = '\0';
125b0b16b86SJon Dugan }
1268a0b5a5dSsethdelliott 
1278a0b5a5dSsethdelliott 
1288a0b5a5dSsethdelliott /* is_closed
1298a0b5a5dSsethdelliott  *
1308a0b5a5dSsethdelliott  * Test if the file descriptor fd is closed.
1318a0b5a5dSsethdelliott  *
1328a0b5a5dSsethdelliott  * Iperf uses this function to test whether a TCP stream socket
1338a0b5a5dSsethdelliott  * is closed, because accepting and denying an invalid connection
1348a0b5a5dSsethdelliott  * in iperf_tcp_accept is not considered an error.
1358a0b5a5dSsethdelliott  */
1368a0b5a5dSsethdelliott 
1378a0b5a5dSsethdelliott int
is_closed(int fd)1388a0b5a5dSsethdelliott is_closed(int fd)
1398a0b5a5dSsethdelliott {
1408a0b5a5dSsethdelliott     struct timeval tv;
1418a0b5a5dSsethdelliott     fd_set readset;
1428a0b5a5dSsethdelliott 
1438a0b5a5dSsethdelliott     FD_ZERO(&readset);
1448a0b5a5dSsethdelliott     FD_SET(fd, &readset);
1458a0b5a5dSsethdelliott     tv.tv_sec = 0;
1468a0b5a5dSsethdelliott     tv.tv_usec = 0;
1478a0b5a5dSsethdelliott 
1488a0b5a5dSsethdelliott     if (select(fd+1, &readset, NULL, NULL, &tv) < 0) {
1498a0b5a5dSsethdelliott         if (errno == EBADF)
150ec2d0670SJef Poskanzer             return 1;
1518a0b5a5dSsethdelliott     }
152ec2d0670SJef Poskanzer     return 0;
1538a0b5a5dSsethdelliott }
1549673370fSJef Poskanzer 
1559673370fSJef Poskanzer 
1569673370fSJef Poskanzer double
timeval_to_double(struct timeval * tv)1579673370fSJef Poskanzer timeval_to_double(struct timeval * tv)
1589673370fSJef Poskanzer {
1599673370fSJef Poskanzer     double d;
1609673370fSJef Poskanzer 
1619673370fSJef Poskanzer     d = tv->tv_sec + tv->tv_usec / 1000000;
1629673370fSJef Poskanzer 
1639673370fSJef Poskanzer     return d;
1649673370fSJef Poskanzer }
1659673370fSJef Poskanzer 
1669673370fSJef Poskanzer int
timeval_equals(struct timeval * tv0,struct timeval * tv1)1679673370fSJef Poskanzer timeval_equals(struct timeval * tv0, struct timeval * tv1)
1689673370fSJef Poskanzer {
1699673370fSJef Poskanzer     if ( tv0->tv_sec == tv1->tv_sec && tv0->tv_usec == tv1->tv_usec )
1709673370fSJef Poskanzer 	return 1;
1719673370fSJef Poskanzer     else
1729673370fSJef Poskanzer 	return 0;
1739673370fSJef Poskanzer }
1749673370fSJef Poskanzer 
1759673370fSJef Poskanzer double
timeval_diff(struct timeval * tv0,struct timeval * tv1)1769673370fSJef Poskanzer timeval_diff(struct timeval * tv0, struct timeval * tv1)
1779673370fSJef Poskanzer {
1789673370fSJef Poskanzer     double time1, time2;
1799673370fSJef Poskanzer 
1809673370fSJef Poskanzer     time1 = tv0->tv_sec + (tv0->tv_usec / 1000000.0);
1819673370fSJef Poskanzer     time2 = tv1->tv_sec + (tv1->tv_usec / 1000000.0);
1829673370fSJef Poskanzer 
1839673370fSJef Poskanzer     time1 = time1 - time2;
1849673370fSJef Poskanzer     if (time1 < 0)
1859673370fSJef Poskanzer         time1 = -time1;
186ec2d0670SJef Poskanzer     return time1;
1879673370fSJef Poskanzer }
1889673370fSJef Poskanzer 
1899673370fSJef Poskanzer void
cpu_util(double pcpu[3])190056361fcSJef Poskanzer cpu_util(double pcpu[3])
1919673370fSJef Poskanzer {
192cde81d76SBen Fox-Moore     static struct iperf_time last;
1939673370fSJef Poskanzer     static clock_t clast;
194056361fcSJef Poskanzer     static struct rusage rlast;
195cde81d76SBen Fox-Moore     struct iperf_time now, temp_time;
1969673370fSJef Poskanzer     clock_t ctemp;
197056361fcSJef Poskanzer     struct rusage rtemp;
1989673370fSJef Poskanzer     double timediff;
199056361fcSJef Poskanzer     double userdiff;
200056361fcSJef Poskanzer     double systemdiff;
2019673370fSJef Poskanzer 
2029673370fSJef Poskanzer     if (pcpu == NULL) {
203cde81d76SBen Fox-Moore         iperf_time_now(&last);
2049673370fSJef Poskanzer         clast = clock();
205056361fcSJef Poskanzer 	getrusage(RUSAGE_SELF, &rlast);
2069673370fSJef Poskanzer         return;
2079673370fSJef Poskanzer     }
2089673370fSJef Poskanzer 
209cde81d76SBen Fox-Moore     iperf_time_now(&now);
2109673370fSJef Poskanzer     ctemp = clock();
211056361fcSJef Poskanzer     getrusage(RUSAGE_SELF, &rtemp);
2129673370fSJef Poskanzer 
213cde81d76SBen Fox-Moore     iperf_time_diff(&now, &last, &temp_time);
214d6075799STommi Rantala     timediff = iperf_time_in_usecs(&temp_time);
215cde81d76SBen Fox-Moore 
216056361fcSJef Poskanzer     userdiff = ((rtemp.ru_utime.tv_sec * 1000000.0 + rtemp.ru_utime.tv_usec) -
217056361fcSJef Poskanzer                 (rlast.ru_utime.tv_sec * 1000000.0 + rlast.ru_utime.tv_usec));
218056361fcSJef Poskanzer     systemdiff = ((rtemp.ru_stime.tv_sec * 1000000.0 + rtemp.ru_stime.tv_usec) -
219056361fcSJef Poskanzer                   (rlast.ru_stime.tv_sec * 1000000.0 + rlast.ru_stime.tv_usec));
2209673370fSJef Poskanzer 
221bf219a4dSBruce A. Mah     pcpu[0] = (((ctemp - clast) * 1000000.0 / CLOCKS_PER_SEC) / timediff) * 100;
222056361fcSJef Poskanzer     pcpu[1] = (userdiff / timediff) * 100;
223056361fcSJef Poskanzer     pcpu[2] = (systemdiff / timediff) * 100;
2249673370fSJef Poskanzer }
225b5e0751fSJef Poskanzer 
22640050b7bSBruce A. Mah const char *
get_system_info(void)227e96ab740SJef Poskanzer get_system_info(void)
228e96ab740SJef Poskanzer {
2299a829841SBruce A. Mah     static char buf[1024];
2309a829841SBruce A. Mah     struct utsname  uts;
231e96ab740SJef Poskanzer 
2329a829841SBruce A. Mah     memset(buf, 0, 1024);
2339a829841SBruce A. Mah     uname(&uts);
2349a829841SBruce A. Mah 
2359a829841SBruce A. Mah     snprintf(buf, sizeof(buf), "%s %s %s %s %s", uts.sysname, uts.nodename,
2369a829841SBruce A. Mah 	     uts.release, uts.version, uts.machine);
2379a829841SBruce A. Mah 
238e96ab740SJef Poskanzer     return buf;
239e96ab740SJef Poskanzer }
240e96ab740SJef Poskanzer 
241e96ab740SJef Poskanzer 
24240050b7bSBruce A. Mah const char *
get_optional_features(void)24340050b7bSBruce A. Mah get_optional_features(void)
24440050b7bSBruce A. Mah {
24540050b7bSBruce A. Mah     static char features[1024];
24640050b7bSBruce A. Mah     unsigned int numfeatures = 0;
24740050b7bSBruce A. Mah 
24840050b7bSBruce A. Mah     snprintf(features, sizeof(features), "Optional features available: ");
24940050b7bSBruce A. Mah 
25040050b7bSBruce A. Mah #if defined(HAVE_CPU_AFFINITY)
25140050b7bSBruce A. Mah     if (numfeatures > 0) {
25240050b7bSBruce A. Mah 	strncat(features, ", ",
25340050b7bSBruce A. Mah 		sizeof(features) - strlen(features) - 1);
25440050b7bSBruce A. Mah     }
25540050b7bSBruce A. Mah     strncat(features, "CPU affinity setting",
25640050b7bSBruce A. Mah 	sizeof(features) - strlen(features) - 1);
25740050b7bSBruce A. Mah     numfeatures++;
25840050b7bSBruce A. Mah #endif /* HAVE_CPU_AFFINITY */
25940050b7bSBruce A. Mah 
26040050b7bSBruce A. Mah #if defined(HAVE_FLOWLABEL)
26140050b7bSBruce A. Mah     if (numfeatures > 0) {
26240050b7bSBruce A. Mah 	strncat(features, ", ",
26340050b7bSBruce A. Mah 		sizeof(features) - strlen(features) - 1);
26440050b7bSBruce A. Mah     }
26540050b7bSBruce A. Mah     strncat(features, "IPv6 flow label",
26640050b7bSBruce A. Mah 	sizeof(features) - strlen(features) - 1);
26740050b7bSBruce A. Mah     numfeatures++;
26840050b7bSBruce A. Mah #endif /* HAVE_FLOWLABEL */
26940050b7bSBruce A. Mah 
2700b0aa349SStefano Garzarella #if defined(HAVE_SCTP_H)
27140050b7bSBruce A. Mah     if (numfeatures > 0) {
27240050b7bSBruce A. Mah 	strncat(features, ", ",
27340050b7bSBruce A. Mah 		sizeof(features) - strlen(features) - 1);
27440050b7bSBruce A. Mah     }
27540050b7bSBruce A. Mah     strncat(features, "SCTP",
27640050b7bSBruce A. Mah 	sizeof(features) - strlen(features) - 1);
27740050b7bSBruce A. Mah     numfeatures++;
2780b0aa349SStefano Garzarella #endif /* HAVE_SCTP_H */
27940050b7bSBruce A. Mah 
28040050b7bSBruce A. Mah #if defined(HAVE_TCP_CONGESTION)
28140050b7bSBruce A. Mah     if (numfeatures > 0) {
28240050b7bSBruce A. Mah 	strncat(features, ", ",
28340050b7bSBruce A. Mah 		sizeof(features) - strlen(features) - 1);
28440050b7bSBruce A. Mah     }
28540050b7bSBruce A. Mah     strncat(features, "TCP congestion algorithm setting",
28640050b7bSBruce A. Mah 	sizeof(features) - strlen(features) - 1);
28740050b7bSBruce A. Mah     numfeatures++;
28840050b7bSBruce A. Mah #endif /* HAVE_TCP_CONGESTION */
28940050b7bSBruce A. Mah 
2903f8c33cdSBruce A. Mah #if defined(HAVE_SENDFILE)
2913f8c33cdSBruce A. Mah     if (numfeatures > 0) {
2923f8c33cdSBruce A. Mah 	strncat(features, ", ",
2933f8c33cdSBruce A. Mah 		sizeof(features) - strlen(features) - 1);
2943f8c33cdSBruce A. Mah     }
2953f8c33cdSBruce A. Mah     strncat(features, "sendfile / zerocopy",
2963f8c33cdSBruce A. Mah 	sizeof(features) - strlen(features) - 1);
2973f8c33cdSBruce A. Mah     numfeatures++;
2983f8c33cdSBruce A. Mah #endif /* HAVE_SENDFILE */
2993f8c33cdSBruce A. Mah 
3009915746aSBruce A. Mah #if defined(HAVE_SO_MAX_PACING_RATE)
3019915746aSBruce A. Mah     if (numfeatures > 0) {
3029915746aSBruce A. Mah 	strncat(features, ", ",
3039915746aSBruce A. Mah 		sizeof(features) - strlen(features) - 1);
3049915746aSBruce A. Mah     }
3059915746aSBruce A. Mah     strncat(features, "socket pacing",
3069915746aSBruce A. Mah 	sizeof(features) - strlen(features) - 1);
3079915746aSBruce A. Mah     numfeatures++;
3089915746aSBruce A. Mah #endif /* HAVE_SO_MAX_PACING_RATE */
3099915746aSBruce A. Mah 
31002d411cbSBruce A. Mah #if defined(HAVE_SSL)
31102d411cbSBruce A. Mah     if (numfeatures > 0) {
31202d411cbSBruce A. Mah 	strncat(features, ", ",
31302d411cbSBruce A. Mah 		sizeof(features) - strlen(features) - 1);
31402d411cbSBruce A. Mah     }
31502d411cbSBruce A. Mah     strncat(features, "authentication",
31602d411cbSBruce A. Mah 	sizeof(features) - strlen(features) - 1);
31702d411cbSBruce A. Mah     numfeatures++;
31802d411cbSBruce A. Mah #endif /* HAVE_SSL */
31902d411cbSBruce A. Mah 
32021581a72SBruce A. Mah #if defined(HAVE_SO_BINDTODEVICE)
32121581a72SBruce A. Mah     if (numfeatures > 0) {
32221581a72SBruce A. Mah 	strncat(features, ", ",
32321581a72SBruce A. Mah 		sizeof(features) - strlen(features) - 1);
32421581a72SBruce A. Mah     }
32521581a72SBruce A. Mah     strncat(features, "bind to device",
32621581a72SBruce A. Mah 	sizeof(features) - strlen(features) - 1);
32721581a72SBruce A. Mah     numfeatures++;
32821581a72SBruce A. Mah #endif /* HAVE_SO_BINDTODEVICE */
32921581a72SBruce A. Mah 
330*49a5771aSDavid Bar-On #if defined(HAVE_DONT_FRAGMENT)
331*49a5771aSDavid Bar-On     if (numfeatures > 0) {
332*49a5771aSDavid Bar-On 	strncat(features, ", ",
333*49a5771aSDavid Bar-On 		sizeof(features) - strlen(features) - 1);
334*49a5771aSDavid Bar-On     }
335*49a5771aSDavid Bar-On     strncat(features, "support IPv4 don't fragment",
336*49a5771aSDavid Bar-On 	sizeof(features) - strlen(features) - 1);
337*49a5771aSDavid Bar-On     numfeatures++;
338*49a5771aSDavid Bar-On #endif /* HAVE_DONT_FRAGMENT */
339*49a5771aSDavid Bar-On 
34040050b7bSBruce A. Mah     if (numfeatures == 0) {
34140050b7bSBruce A. Mah 	strncat(features, "None",
34240050b7bSBruce A. Mah 		sizeof(features) - strlen(features) - 1);
34340050b7bSBruce A. Mah     }
34440050b7bSBruce A. Mah 
34540050b7bSBruce A. Mah     return features;
34640050b7bSBruce A. Mah }
34740050b7bSBruce A. Mah 
348b5e0751fSJef Poskanzer /* Helper routine for building cJSON objects in a printf-like manner.
349b5e0751fSJef Poskanzer **
350b5e0751fSJef Poskanzer ** Sample call:
351b5e0751fSJef Poskanzer **   j = iperf_json_printf("foo: %b  bar: %d  bletch: %f  eep: %s", b, i, f, s);
352b5e0751fSJef Poskanzer **
353b5e0751fSJef Poskanzer ** The four formatting characters and the types they expect are:
354b5e0751fSJef Poskanzer **   %b  boolean           int
355b5e0751fSJef Poskanzer **   %d  integer           int64_t
356b5e0751fSJef Poskanzer **   %f  floating point    double
357b5e0751fSJef Poskanzer **   %s  string            char *
358b5e0751fSJef Poskanzer ** If the values you're passing in are not these exact types, you must
359b5e0751fSJef Poskanzer ** cast them, there is no automatic type coercion/widening here.
360b5e0751fSJef Poskanzer **
361b5e0751fSJef Poskanzer ** The colons mark the end of field names, and blanks are ignored.
362b5e0751fSJef Poskanzer **
363b5e0751fSJef Poskanzer ** This routine is not particularly robust, but it's not part of the API,
364b5e0751fSJef Poskanzer ** it's just for internal iperf3 use.
365b5e0751fSJef Poskanzer */
366b5e0751fSJef Poskanzer cJSON*
iperf_json_printf(const char * format,...)367b5e0751fSJef Poskanzer iperf_json_printf(const char *format, ...)
368b5e0751fSJef Poskanzer {
369b5e0751fSJef Poskanzer     cJSON* o;
370b5e0751fSJef Poskanzer     va_list argp;
371b5e0751fSJef Poskanzer     const char *cp;
372b5e0751fSJef Poskanzer     char name[100];
373b5e0751fSJef Poskanzer     char* np;
374b5e0751fSJef Poskanzer     cJSON* j;
375b5e0751fSJef Poskanzer 
376b5e0751fSJef Poskanzer     o = cJSON_CreateObject();
377b5e0751fSJef Poskanzer     if (o == NULL)
378b5e0751fSJef Poskanzer         return NULL;
379b5e0751fSJef Poskanzer     va_start(argp, format);
380b5e0751fSJef Poskanzer     np = name;
381b5e0751fSJef Poskanzer     for (cp = format; *cp != '\0'; ++cp) {
382b5e0751fSJef Poskanzer 	switch (*cp) {
383b5e0751fSJef Poskanzer 	    case ' ':
384b5e0751fSJef Poskanzer 	    break;
385b5e0751fSJef Poskanzer 	    case ':':
386b5e0751fSJef Poskanzer 	    *np = '\0';
387b5e0751fSJef Poskanzer 	    break;
388b5e0751fSJef Poskanzer 	    case '%':
389b5e0751fSJef Poskanzer 	    ++cp;
390b5e0751fSJef Poskanzer 	    switch (*cp) {
391b5e0751fSJef Poskanzer 		case 'b':
392b5e0751fSJef Poskanzer 		j = cJSON_CreateBool(va_arg(argp, int));
393b5e0751fSJef Poskanzer 		break;
394b5e0751fSJef Poskanzer 		case 'd':
395ed94082bSBruce A. Mah 		j = cJSON_CreateNumber(va_arg(argp, int64_t));
396b5e0751fSJef Poskanzer 		break;
397b5e0751fSJef Poskanzer 		case 'f':
398ed94082bSBruce A. Mah 		j = cJSON_CreateNumber(va_arg(argp, double));
399b5e0751fSJef Poskanzer 		break;
400b5e0751fSJef Poskanzer 		case 's':
401b5e0751fSJef Poskanzer 		j = cJSON_CreateString(va_arg(argp, char *));
402b5e0751fSJef Poskanzer 		break;
403b5e0751fSJef Poskanzer 		default:
4040da552c3Sg-coder 		va_end(argp);
405b5e0751fSJef Poskanzer 		return NULL;
406b5e0751fSJef Poskanzer 	    }
4070da552c3Sg-coder 	    if (j == NULL) {
4080da552c3Sg-coder 	    	va_end(argp);
409b5e0751fSJef Poskanzer 	    	return NULL;
4100da552c3Sg-coder 	    }
411b5e0751fSJef Poskanzer 	    cJSON_AddItemToObject(o, name, j);
412b5e0751fSJef Poskanzer 	    np = name;
413b5e0751fSJef Poskanzer 	    break;
414b5e0751fSJef Poskanzer 	    default:
415b5e0751fSJef Poskanzer 	    *np++ = *cp;
416b5e0751fSJef Poskanzer 	    break;
417b5e0751fSJef Poskanzer 	}
418b5e0751fSJef Poskanzer     }
419b5e0751fSJef Poskanzer     va_end(argp);
420b5e0751fSJef Poskanzer     return o;
421b5e0751fSJef Poskanzer }
422a4c1383aSJef Poskanzer 
423a4c1383aSJef Poskanzer /* Debugging routine to dump out an fd_set. */
424a4c1383aSJef Poskanzer void
iperf_dump_fdset(FILE * fp,const char * str,int nfds,fd_set * fds)4253888e044SDavid Bar-On iperf_dump_fdset(FILE *fp, const char *str, int nfds, fd_set *fds)
426a4c1383aSJef Poskanzer {
427a4c1383aSJef Poskanzer     int fd;
428a4c1383aSJef Poskanzer     int comma;
429a4c1383aSJef Poskanzer 
430a4c1383aSJef Poskanzer     fprintf(fp, "%s: [", str);
431a4c1383aSJef Poskanzer     comma = 0;
432a4c1383aSJef Poskanzer     for (fd = 0; fd < nfds; ++fd) {
433a4c1383aSJef Poskanzer         if (FD_ISSET(fd, fds)) {
434a4c1383aSJef Poskanzer 	    if (comma)
435a4c1383aSJef Poskanzer 		fprintf(fp, ", ");
436a4c1383aSJef Poskanzer 	    fprintf(fp, "%d", fd);
437a4c1383aSJef Poskanzer 	    comma = 1;
438a4c1383aSJef Poskanzer 	}
439a4c1383aSJef Poskanzer     }
440a4c1383aSJef Poskanzer     fprintf(fp, "]\n");
441a4c1383aSJef Poskanzer }
442cb2dcd3fSBruce A. Mah 
44373b02f98SBruce A. Mah /*
44473b02f98SBruce A. Mah  * daemon(3) implementation for systems lacking one.
44573b02f98SBruce A. Mah  * Cobbled together from various daemon(3) implementations,
44673b02f98SBruce A. Mah  * not intended to be general-purpose. */
44773b02f98SBruce A. Mah #ifndef HAVE_DAEMON
daemon(int nochdir,int noclose)44873b02f98SBruce A. Mah int daemon(int nochdir, int noclose)
44973b02f98SBruce A. Mah {
45073b02f98SBruce A. Mah     pid_t pid = 0;
45173b02f98SBruce A. Mah     pid_t sid = 0;
45273b02f98SBruce A. Mah     int fd;
45373b02f98SBruce A. Mah 
45473b02f98SBruce A. Mah     /*
45573b02f98SBruce A. Mah      * Ignore any possible SIGHUP when the parent process exits.
45673b02f98SBruce A. Mah      * Note that the iperf3 server process will eventually install
45773b02f98SBruce A. Mah      * its own signal handler for SIGHUP, so we can be a little
45873b02f98SBruce A. Mah      * sloppy about not restoring the prior value.  This does not
45973b02f98SBruce A. Mah      * generalize.
46073b02f98SBruce A. Mah      */
46173b02f98SBruce A. Mah     signal(SIGHUP, SIG_IGN);
46273b02f98SBruce A. Mah 
46373b02f98SBruce A. Mah     pid = fork();
46473b02f98SBruce A. Mah     if (pid < 0) {
46573b02f98SBruce A. Mah 	    return -1;
46673b02f98SBruce A. Mah     }
46773b02f98SBruce A. Mah     if (pid > 0) {
46873b02f98SBruce A. Mah 	/* Use _exit() to avoid doing atexit() stuff. */
46973b02f98SBruce A. Mah 	_exit(0);
47073b02f98SBruce A. Mah     }
47173b02f98SBruce A. Mah 
47273b02f98SBruce A. Mah     sid = setsid();
47373b02f98SBruce A. Mah     if (sid < 0) {
47473b02f98SBruce A. Mah 	return -1;
47573b02f98SBruce A. Mah     }
47673b02f98SBruce A. Mah 
47773b02f98SBruce A. Mah     /*
47873b02f98SBruce A. Mah      * Fork again to avoid becoming a session leader.
47973b02f98SBruce A. Mah      * This might only matter on old SVr4-derived OSs.
48073b02f98SBruce A. Mah      * Note in particular that glibc and FreeBSD libc
48173b02f98SBruce A. Mah      * only fork once.
48273b02f98SBruce A. Mah      */
48373b02f98SBruce A. Mah     pid = fork();
48473b02f98SBruce A. Mah     if (pid == -1) {
48573b02f98SBruce A. Mah 	return -1;
48673b02f98SBruce A. Mah     } else if (pid != 0) {
48773b02f98SBruce A. Mah 	_exit(0);
48873b02f98SBruce A. Mah     }
48973b02f98SBruce A. Mah 
49073b02f98SBruce A. Mah     if (!nochdir) {
49173b02f98SBruce A. Mah 	chdir("/");
49273b02f98SBruce A. Mah     }
49373b02f98SBruce A. Mah 
49473b02f98SBruce A. Mah     if (!noclose && (fd = open("/dev/null", O_RDWR, 0)) != -1) {
49573b02f98SBruce A. Mah 	dup2(fd, STDIN_FILENO);
49673b02f98SBruce A. Mah 	dup2(fd, STDOUT_FILENO);
49773b02f98SBruce A. Mah 	dup2(fd, STDERR_FILENO);
49873b02f98SBruce A. Mah 	if (fd > 2) {
49973b02f98SBruce A. Mah 	    close(fd);
50073b02f98SBruce A. Mah 	}
50173b02f98SBruce A. Mah     }
50273b02f98SBruce A. Mah     return (0);
50373b02f98SBruce A. Mah }
50473b02f98SBruce A. Mah #endif /* HAVE_DAEMON */
50573b02f98SBruce A. Mah 
506cb2dcd3fSBruce A. Mah /* Compatibility version of getline(3) for systems that don't have it.. */
507cb2dcd3fSBruce A. Mah #ifndef HAVE_GETLINE
508cb2dcd3fSBruce A. Mah /* The following code adopted from NetBSD's getline.c, which is: */
509cb2dcd3fSBruce A. Mah 
510cb2dcd3fSBruce A. Mah /*-
511cb2dcd3fSBruce A. Mah  * Copyright (c) 2011 The NetBSD Foundation, Inc.
512cb2dcd3fSBruce A. Mah  * All rights reserved.
513cb2dcd3fSBruce A. Mah  *
514cb2dcd3fSBruce A. Mah  * This code is derived from software contributed to The NetBSD Foundation
515cb2dcd3fSBruce A. Mah  * by Christos Zoulas.
516cb2dcd3fSBruce A. Mah  *
517cb2dcd3fSBruce A. Mah  * Redistribution and use in source and binary forms, with or without
518cb2dcd3fSBruce A. Mah  * modification, are permitted provided that the following conditions
519cb2dcd3fSBruce A. Mah  * are met:
520cb2dcd3fSBruce A. Mah  * 1. Redistributions of source code must retain the above copyright
521cb2dcd3fSBruce A. Mah  *    notice, this list of conditions and the following disclaimer.
522cb2dcd3fSBruce A. Mah  * 2. Redistributions in binary form must reproduce the above copyright
523cb2dcd3fSBruce A. Mah  *    notice, this list of conditions and the following disclaimer in the
524cb2dcd3fSBruce A. Mah  *    documentation and/or other materials provided with the distribution.
525cb2dcd3fSBruce A. Mah  *
526cb2dcd3fSBruce A. Mah  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
527cb2dcd3fSBruce A. Mah  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
528cb2dcd3fSBruce A. Mah  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
529cb2dcd3fSBruce A. Mah  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
530cb2dcd3fSBruce A. Mah  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
531cb2dcd3fSBruce A. Mah  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
532cb2dcd3fSBruce A. Mah  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
533cb2dcd3fSBruce A. Mah  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
534cb2dcd3fSBruce A. Mah  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
535cb2dcd3fSBruce A. Mah  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
536cb2dcd3fSBruce A. Mah  * POSSIBILITY OF SUCH DAMAGE.
537cb2dcd3fSBruce A. Mah  */
538cb2dcd3fSBruce A. Mah ssize_t
getdelim(char ** buf,size_t * bufsiz,int delimiter,FILE * fp)539cb2dcd3fSBruce A. Mah getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp)
540cb2dcd3fSBruce A. Mah {
541cb2dcd3fSBruce A. Mah 	char *ptr, *eptr;
542cb2dcd3fSBruce A. Mah 
543cb2dcd3fSBruce A. Mah 
544cb2dcd3fSBruce A. Mah 	if (*buf == NULL || *bufsiz == 0) {
545cb2dcd3fSBruce A. Mah 		*bufsiz = BUFSIZ;
546cb2dcd3fSBruce A. Mah 		if ((*buf = malloc(*bufsiz)) == NULL)
547cb2dcd3fSBruce A. Mah 			return -1;
548cb2dcd3fSBruce A. Mah 	}
549cb2dcd3fSBruce A. Mah 
550cb2dcd3fSBruce A. Mah 	for (ptr = *buf, eptr = *buf + *bufsiz;;) {
551cb2dcd3fSBruce A. Mah 		int c = fgetc(fp);
552cb2dcd3fSBruce A. Mah 		if (c == -1) {
553cb2dcd3fSBruce A. Mah 			if (feof(fp)) {
554cb2dcd3fSBruce A. Mah 				ssize_t diff = (ssize_t)(ptr - *buf);
555cb2dcd3fSBruce A. Mah 				if (diff != 0) {
556cb2dcd3fSBruce A. Mah 					*ptr = '\0';
557cb2dcd3fSBruce A. Mah 					return diff;
558cb2dcd3fSBruce A. Mah 				}
559cb2dcd3fSBruce A. Mah 			}
560cb2dcd3fSBruce A. Mah 			return -1;
561cb2dcd3fSBruce A. Mah 		}
562cb2dcd3fSBruce A. Mah 		*ptr++ = c;
563cb2dcd3fSBruce A. Mah 		if (c == delimiter) {
564cb2dcd3fSBruce A. Mah 			*ptr = '\0';
565cb2dcd3fSBruce A. Mah 			return ptr - *buf;
566cb2dcd3fSBruce A. Mah 		}
567cb2dcd3fSBruce A. Mah 		if (ptr + 2 >= eptr) {
568cb2dcd3fSBruce A. Mah 			char *nbuf;
569cb2dcd3fSBruce A. Mah 			size_t nbufsiz = *bufsiz * 2;
570cb2dcd3fSBruce A. Mah 			ssize_t d = ptr - *buf;
571cb2dcd3fSBruce A. Mah 			if ((nbuf = realloc(*buf, nbufsiz)) == NULL)
572cb2dcd3fSBruce A. Mah 				return -1;
573cb2dcd3fSBruce A. Mah 			*buf = nbuf;
574cb2dcd3fSBruce A. Mah 			*bufsiz = nbufsiz;
575cb2dcd3fSBruce A. Mah 			eptr = nbuf + nbufsiz;
576cb2dcd3fSBruce A. Mah 			ptr = nbuf + d;
577cb2dcd3fSBruce A. Mah 		}
578cb2dcd3fSBruce A. Mah 	}
579cb2dcd3fSBruce A. Mah }
580cb2dcd3fSBruce A. Mah 
581cb2dcd3fSBruce A. Mah ssize_t
getline(char ** buf,size_t * bufsiz,FILE * fp)582cb2dcd3fSBruce A. Mah getline(char **buf, size_t *bufsiz, FILE *fp)
583cb2dcd3fSBruce A. Mah {
584cb2dcd3fSBruce A. Mah 	return getdelim(buf, bufsiz, '\n', fp);
585cb2dcd3fSBruce A. Mah }
586cb2dcd3fSBruce A. Mah 
587cb2dcd3fSBruce A. Mah #endif
588