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