1 /*
2  * iperf, Copyright (c) 2014, 2016, 2017, The Regents of the University of
3  * California, through Lawrence Berkeley National Laboratory (subject
4  * to receipt of any required approvals from the U.S. Dept. of
5  * Energy).  All rights reserved.
6  *
7  * If you have questions about your rights to use or distribute this
8  * software, please contact Berkeley Lab's Technology Transfer
9  * Department at TTD@lbl.gov.
10  *
11  * NOTICE.  This software is owned by the U.S. Department of Energy.
12  * As such, the U.S. Government has been granted for itself and others
13  * acting on its behalf a paid-up, nonexclusive, irrevocable,
14  * worldwide license in the Software to reproduce, prepare derivative
15  * works, and perform publicly and display publicly.  Beginning five
16  * (5) years after the date permission to assert copyright is obtained
17  * from the U.S. Department of Energy, and subject to any subsequent
18  * five (5) year renewals, the U.S. Government is granted for itself
19  * and others acting on its behalf a paid-up, nonexclusive,
20  * irrevocable, worldwide license in the Software to reproduce,
21  * prepare derivative works, distribute copies to the public, perform
22  * publicly and display publicly, and to permit others to do so.
23  *
24  * This code is distributed under a BSD style license, see the LICENSE
25  * file for complete information.
26  */
27 /* iperf_util.c
28  *
29  * Iperf utility functions
30  *
31  */
32 #include "iperf_config.h"
33 
34 #include <stdio.h>
35 #include <signal.h>
36 #include <stdlib.h>
37 #include <unistd.h>
38 #include <string.h>
39 #include <stdarg.h>
40 #include <sys/select.h>
41 #include <sys/types.h>
42 #include <sys/time.h>
43 #include <sys/resource.h>
44 #include <sys/utsname.h>
45 #include <time.h>
46 #include <errno.h>
47 #include <fcntl.h>
48 
49 #include "cjson.h"
50 #include "iperf.h"
51 #include "iperf_api.h"
52 
53 /*
54  * Read entropy from /dev/urandom
55  * Errors are fatal.
56  * Returns 0 on success.
57  */
readentropy(void * out,size_t outsize)58 int readentropy(void *out, size_t outsize)
59 {
60     static FILE *frandom;
61     static const char rndfile[] = "/dev/urandom";
62 
63     if (!outsize) return 0;
64 
65     if (frandom == NULL) {
66         frandom = fopen(rndfile, "rb");
67         if (frandom == NULL) {
68             iperf_errexit(NULL, "error - failed to open %s: %s\n",
69                           rndfile, strerror(errno));
70         }
71         setbuf(frandom, NULL);
72     }
73     if (fread(out, 1, outsize, frandom) != outsize) {
74         iperf_errexit(NULL, "error - failed to read %s: %s\n",
75                       rndfile,
76                       feof(frandom) ? "EOF" : strerror(errno));
77     }
78     return 0;
79 }
80 
81 
82 /*
83  * Fills buffer with repeating pattern (similar to pattern that used in iperf2)
84  */
fill_with_repeating_pattern(void * out,size_t outsize)85 void fill_with_repeating_pattern(void *out, size_t outsize)
86 {
87     size_t i;
88     int counter = 0;
89     char *buf = (char *)out;
90 
91     if (!outsize) return;
92 
93     for (i = 0; i < outsize; i++) {
94         buf[i] = (char)('0' + counter);
95         if (counter >= 9)
96             counter = 0;
97         else
98             counter++;
99     }
100 }
101 
102 
103 /* make_cookie
104  *
105  * Generate and return a cookie string
106  *
107  * Iperf uses this function to create test "cookies" which
108  * server as unique test identifiers. These cookies are also
109  * used for the authentication of stream connections.
110  * Assumes cookie has size (COOKIE_SIZE + 1) char's.
111  */
112 
113 void
make_cookie(const char * cookie)114 make_cookie(const char *cookie)
115 {
116     unsigned char *out = (unsigned char*)cookie;
117     size_t pos;
118     static const unsigned char rndchars[] = "abcdefghijklmnopqrstuvwxyz234567";
119 
120     readentropy(out, COOKIE_SIZE);
121     for (pos = 0; pos < (COOKIE_SIZE - 1); pos++) {
122         out[pos] = rndchars[out[pos] % (sizeof(rndchars) - 1)];
123     }
124     out[pos] = '\0';
125 }
126 
127 
128 /* is_closed
129  *
130  * Test if the file descriptor fd is closed.
131  *
132  * Iperf uses this function to test whether a TCP stream socket
133  * is closed, because accepting and denying an invalid connection
134  * in iperf_tcp_accept is not considered an error.
135  */
136 
137 int
is_closed(int fd)138 is_closed(int fd)
139 {
140     struct timeval tv;
141     fd_set readset;
142 
143     FD_ZERO(&readset);
144     FD_SET(fd, &readset);
145     tv.tv_sec = 0;
146     tv.tv_usec = 0;
147 
148     if (select(fd+1, &readset, NULL, NULL, &tv) < 0) {
149         if (errno == EBADF)
150             return 1;
151     }
152     return 0;
153 }
154 
155 
156 double
timeval_to_double(struct timeval * tv)157 timeval_to_double(struct timeval * tv)
158 {
159     double d;
160 
161     d = tv->tv_sec + tv->tv_usec / 1000000;
162 
163     return d;
164 }
165 
166 int
timeval_equals(struct timeval * tv0,struct timeval * tv1)167 timeval_equals(struct timeval * tv0, struct timeval * tv1)
168 {
169     if ( tv0->tv_sec == tv1->tv_sec && tv0->tv_usec == tv1->tv_usec )
170 	return 1;
171     else
172 	return 0;
173 }
174 
175 double
timeval_diff(struct timeval * tv0,struct timeval * tv1)176 timeval_diff(struct timeval * tv0, struct timeval * tv1)
177 {
178     double time1, time2;
179 
180     time1 = tv0->tv_sec + (tv0->tv_usec / 1000000.0);
181     time2 = tv1->tv_sec + (tv1->tv_usec / 1000000.0);
182 
183     time1 = time1 - time2;
184     if (time1 < 0)
185         time1 = -time1;
186     return time1;
187 }
188 
189 void
cpu_util(double pcpu[3])190 cpu_util(double pcpu[3])
191 {
192     static struct iperf_time last;
193     static clock_t clast;
194     static struct rusage rlast;
195     struct iperf_time now, temp_time;
196     clock_t ctemp;
197     struct rusage rtemp;
198     double timediff;
199     double userdiff;
200     double systemdiff;
201 
202     if (pcpu == NULL) {
203         iperf_time_now(&last);
204         clast = clock();
205 	getrusage(RUSAGE_SELF, &rlast);
206         return;
207     }
208 
209     iperf_time_now(&now);
210     ctemp = clock();
211     getrusage(RUSAGE_SELF, &rtemp);
212 
213     iperf_time_diff(&now, &last, &temp_time);
214     timediff = iperf_time_in_usecs(&temp_time);
215 
216     userdiff = ((rtemp.ru_utime.tv_sec * 1000000.0 + rtemp.ru_utime.tv_usec) -
217                 (rlast.ru_utime.tv_sec * 1000000.0 + rlast.ru_utime.tv_usec));
218     systemdiff = ((rtemp.ru_stime.tv_sec * 1000000.0 + rtemp.ru_stime.tv_usec) -
219                   (rlast.ru_stime.tv_sec * 1000000.0 + rlast.ru_stime.tv_usec));
220 
221     pcpu[0] = (((ctemp - clast) * 1000000.0 / CLOCKS_PER_SEC) / timediff) * 100;
222     pcpu[1] = (userdiff / timediff) * 100;
223     pcpu[2] = (systemdiff / timediff) * 100;
224 }
225 
226 const char *
get_system_info(void)227 get_system_info(void)
228 {
229     static char buf[1024];
230     struct utsname  uts;
231 
232     memset(buf, 0, 1024);
233     uname(&uts);
234 
235     snprintf(buf, sizeof(buf), "%s %s %s %s %s", uts.sysname, uts.nodename,
236 	     uts.release, uts.version, uts.machine);
237 
238     return buf;
239 }
240 
241 
242 const char *
get_optional_features(void)243 get_optional_features(void)
244 {
245     static char features[1024];
246     unsigned int numfeatures = 0;
247 
248     snprintf(features, sizeof(features), "Optional features available: ");
249 
250 #if defined(HAVE_CPU_AFFINITY)
251     if (numfeatures > 0) {
252 	strncat(features, ", ",
253 		sizeof(features) - strlen(features) - 1);
254     }
255     strncat(features, "CPU affinity setting",
256 	sizeof(features) - strlen(features) - 1);
257     numfeatures++;
258 #endif /* HAVE_CPU_AFFINITY */
259 
260 #if defined(HAVE_FLOWLABEL)
261     if (numfeatures > 0) {
262 	strncat(features, ", ",
263 		sizeof(features) - strlen(features) - 1);
264     }
265     strncat(features, "IPv6 flow label",
266 	sizeof(features) - strlen(features) - 1);
267     numfeatures++;
268 #endif /* HAVE_FLOWLABEL */
269 
270 #if defined(HAVE_SCTP_H)
271     if (numfeatures > 0) {
272 	strncat(features, ", ",
273 		sizeof(features) - strlen(features) - 1);
274     }
275     strncat(features, "SCTP",
276 	sizeof(features) - strlen(features) - 1);
277     numfeatures++;
278 #endif /* HAVE_SCTP_H */
279 
280 #if defined(HAVE_TCP_CONGESTION)
281     if (numfeatures > 0) {
282 	strncat(features, ", ",
283 		sizeof(features) - strlen(features) - 1);
284     }
285     strncat(features, "TCP congestion algorithm setting",
286 	sizeof(features) - strlen(features) - 1);
287     numfeatures++;
288 #endif /* HAVE_TCP_CONGESTION */
289 
290 #if defined(HAVE_SENDFILE)
291     if (numfeatures > 0) {
292 	strncat(features, ", ",
293 		sizeof(features) - strlen(features) - 1);
294     }
295     strncat(features, "sendfile / zerocopy",
296 	sizeof(features) - strlen(features) - 1);
297     numfeatures++;
298 #endif /* HAVE_SENDFILE */
299 
300 #if defined(HAVE_SO_MAX_PACING_RATE)
301     if (numfeatures > 0) {
302 	strncat(features, ", ",
303 		sizeof(features) - strlen(features) - 1);
304     }
305     strncat(features, "socket pacing",
306 	sizeof(features) - strlen(features) - 1);
307     numfeatures++;
308 #endif /* HAVE_SO_MAX_PACING_RATE */
309 
310 #if defined(HAVE_SSL)
311     if (numfeatures > 0) {
312 	strncat(features, ", ",
313 		sizeof(features) - strlen(features) - 1);
314     }
315     strncat(features, "authentication",
316 	sizeof(features) - strlen(features) - 1);
317     numfeatures++;
318 #endif /* HAVE_SSL */
319 
320 #if defined(HAVE_SO_BINDTODEVICE)
321     if (numfeatures > 0) {
322 	strncat(features, ", ",
323 		sizeof(features) - strlen(features) - 1);
324     }
325     strncat(features, "bind to device",
326 	sizeof(features) - strlen(features) - 1);
327     numfeatures++;
328 #endif /* HAVE_SO_BINDTODEVICE */
329 
330 #if defined(HAVE_DONT_FRAGMENT)
331     if (numfeatures > 0) {
332 	strncat(features, ", ",
333 		sizeof(features) - strlen(features) - 1);
334     }
335     strncat(features, "support IPv4 don't fragment",
336 	sizeof(features) - strlen(features) - 1);
337     numfeatures++;
338 #endif /* HAVE_DONT_FRAGMENT */
339 
340     if (numfeatures == 0) {
341 	strncat(features, "None",
342 		sizeof(features) - strlen(features) - 1);
343     }
344 
345     return features;
346 }
347 
348 /* Helper routine for building cJSON objects in a printf-like manner.
349 **
350 ** Sample call:
351 **   j = iperf_json_printf("foo: %b  bar: %d  bletch: %f  eep: %s", b, i, f, s);
352 **
353 ** The four formatting characters and the types they expect are:
354 **   %b  boolean           int
355 **   %d  integer           int64_t
356 **   %f  floating point    double
357 **   %s  string            char *
358 ** If the values you're passing in are not these exact types, you must
359 ** cast them, there is no automatic type coercion/widening here.
360 **
361 ** The colons mark the end of field names, and blanks are ignored.
362 **
363 ** This routine is not particularly robust, but it's not part of the API,
364 ** it's just for internal iperf3 use.
365 */
366 cJSON*
iperf_json_printf(const char * format,...)367 iperf_json_printf(const char *format, ...)
368 {
369     cJSON* o;
370     va_list argp;
371     const char *cp;
372     char name[100];
373     char* np;
374     cJSON* j;
375 
376     o = cJSON_CreateObject();
377     if (o == NULL)
378         return NULL;
379     va_start(argp, format);
380     np = name;
381     for (cp = format; *cp != '\0'; ++cp) {
382 	switch (*cp) {
383 	    case ' ':
384 	    break;
385 	    case ':':
386 	    *np = '\0';
387 	    break;
388 	    case '%':
389 	    ++cp;
390 	    switch (*cp) {
391 		case 'b':
392 		j = cJSON_CreateBool(va_arg(argp, int));
393 		break;
394 		case 'd':
395 		j = cJSON_CreateNumber(va_arg(argp, int64_t));
396 		break;
397 		case 'f':
398 		j = cJSON_CreateNumber(va_arg(argp, double));
399 		break;
400 		case 's':
401 		j = cJSON_CreateString(va_arg(argp, char *));
402 		break;
403 		default:
404 		va_end(argp);
405 		return NULL;
406 	    }
407 	    if (j == NULL) {
408 	    	va_end(argp);
409 	    	return NULL;
410 	    }
411 	    cJSON_AddItemToObject(o, name, j);
412 	    np = name;
413 	    break;
414 	    default:
415 	    *np++ = *cp;
416 	    break;
417 	}
418     }
419     va_end(argp);
420     return o;
421 }
422 
423 /* Debugging routine to dump out an fd_set. */
424 void
iperf_dump_fdset(FILE * fp,const char * str,int nfds,fd_set * fds)425 iperf_dump_fdset(FILE *fp, const char *str, int nfds, fd_set *fds)
426 {
427     int fd;
428     int comma;
429 
430     fprintf(fp, "%s: [", str);
431     comma = 0;
432     for (fd = 0; fd < nfds; ++fd) {
433         if (FD_ISSET(fd, fds)) {
434 	    if (comma)
435 		fprintf(fp, ", ");
436 	    fprintf(fp, "%d", fd);
437 	    comma = 1;
438 	}
439     }
440     fprintf(fp, "]\n");
441 }
442 
443 /*
444  * daemon(3) implementation for systems lacking one.
445  * Cobbled together from various daemon(3) implementations,
446  * not intended to be general-purpose. */
447 #ifndef HAVE_DAEMON
daemon(int nochdir,int noclose)448 int daemon(int nochdir, int noclose)
449 {
450     pid_t pid = 0;
451     pid_t sid = 0;
452     int fd;
453 
454     /*
455      * Ignore any possible SIGHUP when the parent process exits.
456      * Note that the iperf3 server process will eventually install
457      * its own signal handler for SIGHUP, so we can be a little
458      * sloppy about not restoring the prior value.  This does not
459      * generalize.
460      */
461     signal(SIGHUP, SIG_IGN);
462 
463     pid = fork();
464     if (pid < 0) {
465 	    return -1;
466     }
467     if (pid > 0) {
468 	/* Use _exit() to avoid doing atexit() stuff. */
469 	_exit(0);
470     }
471 
472     sid = setsid();
473     if (sid < 0) {
474 	return -1;
475     }
476 
477     /*
478      * Fork again to avoid becoming a session leader.
479      * This might only matter on old SVr4-derived OSs.
480      * Note in particular that glibc and FreeBSD libc
481      * only fork once.
482      */
483     pid = fork();
484     if (pid == -1) {
485 	return -1;
486     } else if (pid != 0) {
487 	_exit(0);
488     }
489 
490     if (!nochdir) {
491 	chdir("/");
492     }
493 
494     if (!noclose && (fd = open("/dev/null", O_RDWR, 0)) != -1) {
495 	dup2(fd, STDIN_FILENO);
496 	dup2(fd, STDOUT_FILENO);
497 	dup2(fd, STDERR_FILENO);
498 	if (fd > 2) {
499 	    close(fd);
500 	}
501     }
502     return (0);
503 }
504 #endif /* HAVE_DAEMON */
505 
506 /* Compatibility version of getline(3) for systems that don't have it.. */
507 #ifndef HAVE_GETLINE
508 /* The following code adopted from NetBSD's getline.c, which is: */
509 
510 /*-
511  * Copyright (c) 2011 The NetBSD Foundation, Inc.
512  * All rights reserved.
513  *
514  * This code is derived from software contributed to The NetBSD Foundation
515  * by Christos Zoulas.
516  *
517  * Redistribution and use in source and binary forms, with or without
518  * modification, are permitted provided that the following conditions
519  * are met:
520  * 1. Redistributions of source code must retain the above copyright
521  *    notice, this list of conditions and the following disclaimer.
522  * 2. Redistributions in binary form must reproduce the above copyright
523  *    notice, this list of conditions and the following disclaimer in the
524  *    documentation and/or other materials provided with the distribution.
525  *
526  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
527  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
528  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
529  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
530  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
531  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
532  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
533  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
534  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
535  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
536  * POSSIBILITY OF SUCH DAMAGE.
537  */
538 ssize_t
getdelim(char ** buf,size_t * bufsiz,int delimiter,FILE * fp)539 getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp)
540 {
541 	char *ptr, *eptr;
542 
543 
544 	if (*buf == NULL || *bufsiz == 0) {
545 		*bufsiz = BUFSIZ;
546 		if ((*buf = malloc(*bufsiz)) == NULL)
547 			return -1;
548 	}
549 
550 	for (ptr = *buf, eptr = *buf + *bufsiz;;) {
551 		int c = fgetc(fp);
552 		if (c == -1) {
553 			if (feof(fp)) {
554 				ssize_t diff = (ssize_t)(ptr - *buf);
555 				if (diff != 0) {
556 					*ptr = '\0';
557 					return diff;
558 				}
559 			}
560 			return -1;
561 		}
562 		*ptr++ = c;
563 		if (c == delimiter) {
564 			*ptr = '\0';
565 			return ptr - *buf;
566 		}
567 		if (ptr + 2 >= eptr) {
568 			char *nbuf;
569 			size_t nbufsiz = *bufsiz * 2;
570 			ssize_t d = ptr - *buf;
571 			if ((nbuf = realloc(*buf, nbufsiz)) == NULL)
572 				return -1;
573 			*buf = nbuf;
574 			*bufsiz = nbufsiz;
575 			eptr = nbuf + nbufsiz;
576 			ptr = nbuf + d;
577 		}
578 	}
579 }
580 
581 ssize_t
getline(char ** buf,size_t * bufsiz,FILE * fp)582 getline(char **buf, size_t *bufsiz, FILE *fp)
583 {
584 	return getdelim(buf, bufsiz, '\n', fp);
585 }
586 
587 #endif
588