• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * iperf, Copyright (c) 2014-2021, 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 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <errno.h>
31 #include <unistd.h>
32 #include <arpa/inet.h>
33 #include <sys/socket.h>
34 #include <sys/types.h>
35 #include <netinet/in.h>
36 #include <netdb.h>
37 #include <sys/time.h>
38 #include <sys/select.h>
39 #include <limits.h>
40 
41 #include "iperf.h"
42 #include "iperf_api.h"
43 #include "iperf_tcp.h"
44 #include "net.h"
45 #include "cjson.h"
46 
47 #if defined(HAVE_FLOWLABEL)
48 #include "flowlabel.h"
49 #endif /* HAVE_FLOWLABEL */
50 
51 /* iperf_tcp_recv
52  *
53  * receives the data for TCP
54  */
55 int
iperf_tcp_recv(struct iperf_stream * sp)56 iperf_tcp_recv(struct iperf_stream *sp)
57 {
58     int r;
59 
60     r = Nread(sp->socket, sp->buffer, sp->settings->blksize, Ptcp);
61 
62     if (r < 0)
63         return r;
64 
65     /* Only count bytes received while we're in the correct state. */
66     if (sp->test->state == TEST_RUNNING) {
67 	sp->result->bytes_received += r;
68 	sp->result->bytes_received_this_interval += r;
69     }
70     else {
71 	if (sp->test->debug)
72 	    printf("Late receive, state = %d\n", sp->test->state);
73     }
74 
75     return r;
76 }
77 
78 
79 /* iperf_tcp_send
80  *
81  * sends the data for TCP
82  */
83 int
iperf_tcp_send(struct iperf_stream * sp)84 iperf_tcp_send(struct iperf_stream *sp)
85 {
86     int r;
87 
88     if (!sp->pending_size)
89 	sp->pending_size = sp->settings->blksize;
90 
91     if (sp->test->zerocopy)
92 	r = Nsendfile(sp->buffer_fd, sp->socket, sp->buffer, sp->pending_size);
93     else
94 	r = Nwrite(sp->socket, sp->buffer, sp->pending_size, Ptcp);
95 
96     if (r < 0)
97         return r;
98 
99     sp->pending_size -= r;
100     sp->result->bytes_sent += r;
101     sp->result->bytes_sent_this_interval += r;
102 
103     if (sp->test->debug)
104 	printf("sent %d bytes of %d, pending %d, total %" PRIu64 "\n",
105 	    r, sp->settings->blksize, sp->pending_size, sp->result->bytes_sent);
106 
107     return r;
108 }
109 
110 
111 /* iperf_tcp_accept
112  *
113  * accept a new TCP stream connection
114  */
115 int
iperf_tcp_accept(struct iperf_test * test)116 iperf_tcp_accept(struct iperf_test * test)
117 {
118     int     s;
119     signed char rbuf = ACCESS_DENIED;
120     char    cookie[COOKIE_SIZE];
121     socklen_t len;
122     struct sockaddr_storage addr;
123 
124     len = sizeof(addr);
125     if ((s = accept(test->listener, (struct sockaddr *) &addr, &len)) < 0) {
126         i_errno = IESTREAMCONNECT;
127         return -1;
128     }
129 
130     if (Nread(s, cookie, COOKIE_SIZE, Ptcp) < 0) {
131         i_errno = IERECVCOOKIE;
132         return -1;
133     }
134 
135     if (strcmp(test->cookie, cookie) != 0) {
136         if (Nwrite(s, (char*) &rbuf, sizeof(rbuf), Ptcp) < 0) {
137             iperf_err(test, "failed to send access denied from busy server to new connecting client, errno = %d\n", errno);
138         }
139         close(s);
140     }
141 
142     return s;
143 }
144 
145 
146 /* iperf_tcp_listen
147  *
148  * start up a listener for TCP stream connections
149  */
150 int
iperf_tcp_listen(struct iperf_test * test)151 iperf_tcp_listen(struct iperf_test *test)
152 {
153     int s, opt;
154     socklen_t optlen;
155     int saved_errno;
156     int rcvbuf_actual, sndbuf_actual;
157 
158     s = test->listener;
159 
160     /*
161      * If certain parameters are specified (such as socket buffer
162      * size), then throw away the listening socket (the one for which
163      * we just accepted the control connection) and recreate it with
164      * those parameters.  That way, when new data connections are
165      * set, they'll have all the correct parameters in place.
166      *
167      * It's not clear whether this is a requirement or a convenience.
168      */
169     if (test->no_delay || test->settings->mss || test->settings->socket_bufsize) {
170 	struct addrinfo hints, *res;
171 	char portstr[6];
172 
173         FD_CLR(s, &test->read_set);
174         close(s);
175 
176         snprintf(portstr, 6, "%d", test->server_port);
177         memset(&hints, 0, sizeof(hints));
178 
179 	/*
180 	 * If binding to the wildcard address with no explicit address
181 	 * family specified, then force us to get an AF_INET6 socket.
182 	 * More details in the comments in netanounce().
183 	 */
184 	if (test->settings->domain == AF_UNSPEC && !test->bind_address) {
185 	    hints.ai_family = AF_INET6;
186 	}
187 	else {
188 	    hints.ai_family = test->settings->domain;
189 	}
190         hints.ai_socktype = SOCK_STREAM;
191         hints.ai_flags = AI_PASSIVE;
192         if ((gerror = getaddrinfo(test->bind_address, portstr, &hints, &res)) != 0) {
193             i_errno = IESTREAMLISTEN;
194             return -1;
195         }
196 
197         if ((s = socket(res->ai_family, SOCK_STREAM, 0)) < 0) {
198 	    freeaddrinfo(res);
199             i_errno = IESTREAMLISTEN;
200             return -1;
201         }
202 
203         if (test->no_delay) {
204             opt = 1;
205             if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)) < 0) {
206 		saved_errno = errno;
207 		close(s);
208 		freeaddrinfo(res);
209 		errno = saved_errno;
210                 i_errno = IESETNODELAY;
211                 return -1;
212             }
213         }
214         // XXX: Setting MSS is very buggy!
215         if ((opt = test->settings->mss)) {
216             if (setsockopt(s, IPPROTO_TCP, TCP_MAXSEG, &opt, sizeof(opt)) < 0) {
217 		saved_errno = errno;
218 		close(s);
219 		freeaddrinfo(res);
220 		errno = saved_errno;
221                 i_errno = IESETMSS;
222                 return -1;
223             }
224         }
225         if ((opt = test->settings->socket_bufsize)) {
226             if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)) < 0) {
227 		saved_errno = errno;
228 		close(s);
229 		freeaddrinfo(res);
230 		errno = saved_errno;
231                 i_errno = IESETBUF;
232                 return -1;
233             }
234             if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt)) < 0) {
235 		saved_errno = errno;
236 		close(s);
237 		freeaddrinfo(res);
238 		errno = saved_errno;
239                 i_errno = IESETBUF;
240                 return -1;
241             }
242         }
243 #if defined(HAVE_SO_MAX_PACING_RATE)
244     /* If fq socket pacing is specified, enable it. */
245     if (test->settings->fqrate) {
246 	/* Convert bits per second to bytes per second */
247 	unsigned int fqrate = test->settings->fqrate / 8;
248 	if (fqrate > 0) {
249 	    if (test->debug) {
250 		printf("Setting fair-queue socket pacing to %u\n", fqrate);
251 	    }
252 	    if (setsockopt(s, SOL_SOCKET, SO_MAX_PACING_RATE, &fqrate, sizeof(fqrate)) < 0) {
253 		warning("Unable to set socket pacing");
254 	    }
255 	}
256     }
257 #endif /* HAVE_SO_MAX_PACING_RATE */
258     {
259 	unsigned int rate = test->settings->rate / 8;
260 	if (rate > 0) {
261 	    if (test->debug) {
262 		printf("Setting application pacing to %u\n", rate);
263 	    }
264 	}
265     }
266         opt = 1;
267         if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
268 	    saved_errno = errno;
269             close(s);
270 	    freeaddrinfo(res);
271 	    errno = saved_errno;
272             i_errno = IEREUSEADDR;
273             return -1;
274         }
275 
276 	/*
277 	 * If we got an IPv6 socket, figure out if it shoudl accept IPv4
278 	 * connections as well.  See documentation in netannounce() for
279 	 * more details.
280 	 */
281 #if defined(IPV6_V6ONLY) && !defined(__OpenBSD__)
282 	if (res->ai_family == AF_INET6 && (test->settings->domain == AF_UNSPEC || test->settings->domain == AF_INET)) {
283 	    if (test->settings->domain == AF_UNSPEC)
284 		opt = 0;
285 	    else
286 		opt = 1;
287 	    if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
288 			   (char *) &opt, sizeof(opt)) < 0) {
289 		saved_errno = errno;
290 		close(s);
291 		freeaddrinfo(res);
292 		errno = saved_errno;
293 		i_errno = IEV6ONLY;
294 		return -1;
295 	    }
296 	}
297 #endif /* IPV6_V6ONLY */
298 
299         if (bind(s, (struct sockaddr *) res->ai_addr, res->ai_addrlen) < 0) {
300 	    saved_errno = errno;
301             close(s);
302 	    freeaddrinfo(res);
303 	    errno = saved_errno;
304             i_errno = IESTREAMLISTEN;
305             return -1;
306         }
307 
308         freeaddrinfo(res);
309 
310         if (listen(s, INT_MAX) < 0) {
311             i_errno = IESTREAMLISTEN;
312             return -1;
313         }
314 
315         test->listener = s;
316     }
317 
318     /* Read back and verify the sender socket buffer size */
319     optlen = sizeof(sndbuf_actual);
320     if (getsockopt(s, SOL_SOCKET, SO_SNDBUF, &sndbuf_actual, &optlen) < 0) {
321 	saved_errno = errno;
322 	close(s);
323 	errno = saved_errno;
324 	i_errno = IESETBUF;
325 	return -1;
326     }
327     if (test->debug) {
328 	printf("SNDBUF is %u, expecting %u\n", sndbuf_actual, test->settings->socket_bufsize);
329     }
330     if (test->settings->socket_bufsize && test->settings->socket_bufsize > sndbuf_actual) {
331 	i_errno = IESETBUF2;
332 	return -1;
333     }
334 
335     /* Read back and verify the receiver socket buffer size */
336     optlen = sizeof(rcvbuf_actual);
337     if (getsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcvbuf_actual, &optlen) < 0) {
338 	saved_errno = errno;
339 	close(s);
340 	errno = saved_errno;
341 	i_errno = IESETBUF;
342 	return -1;
343     }
344     if (test->debug) {
345 	printf("RCVBUF is %u, expecting %u\n", rcvbuf_actual, test->settings->socket_bufsize);
346     }
347     if (test->settings->socket_bufsize && test->settings->socket_bufsize > rcvbuf_actual) {
348 	i_errno = IESETBUF2;
349 	return -1;
350     }
351 
352     if (test->json_output) {
353 	cJSON_AddNumberToObject(test->json_start, "sock_bufsize", test->settings->socket_bufsize);
354 	cJSON_AddNumberToObject(test->json_start, "sndbuf_actual", sndbuf_actual);
355 	cJSON_AddNumberToObject(test->json_start, "rcvbuf_actual", rcvbuf_actual);
356     }
357 
358     return s;
359 }
360 
361 
362 /* iperf_tcp_connect
363  *
364  * connect to a TCP stream listener
365  * This function is roughly similar to netdial(), and may indeed have
366  * been derived from it at some point, but it sets many TCP-specific
367  * options between socket creation and connection.
368  */
369 int
iperf_tcp_connect(struct iperf_test * test)370 iperf_tcp_connect(struct iperf_test *test)
371 {
372     struct addrinfo hints, *local_res, *server_res;
373     char portstr[6];
374     int s, opt;
375     socklen_t optlen;
376     int saved_errno;
377     int rcvbuf_actual, sndbuf_actual;
378 
379     if (test->bind_address) {
380         memset(&hints, 0, sizeof(hints));
381         hints.ai_family = test->settings->domain;
382         hints.ai_socktype = SOCK_STREAM;
383         if ((gerror = getaddrinfo(test->bind_address, NULL, &hints, &local_res)) != 0) {
384             i_errno = IESTREAMCONNECT;
385             return -1;
386         }
387     }
388 
389     memset(&hints, 0, sizeof(hints));
390     hints.ai_family = test->settings->domain;
391     hints.ai_socktype = SOCK_STREAM;
392     snprintf(portstr, sizeof(portstr), "%d", test->server_port);
393     if ((gerror = getaddrinfo(test->server_hostname, portstr, &hints, &server_res)) != 0) {
394 	if (test->bind_address)
395 	    freeaddrinfo(local_res);
396         i_errno = IESTREAMCONNECT;
397         return -1;
398     }
399 
400     if ((s = socket(server_res->ai_family, SOCK_STREAM, 0)) < 0) {
401 	if (test->bind_address)
402 	    freeaddrinfo(local_res);
403 	freeaddrinfo(server_res);
404         i_errno = IESTREAMCONNECT;
405         return -1;
406     }
407 
408     /*
409      * Various ways to bind the local end of the connection.
410      * 1.  --bind (with or without --cport).
411      */
412     if (test->bind_address) {
413         struct sockaddr_in *lcladdr;
414         lcladdr = (struct sockaddr_in *)local_res->ai_addr;
415         lcladdr->sin_port = htons(test->bind_port);
416 
417         if (bind(s, (struct sockaddr *) local_res->ai_addr, local_res->ai_addrlen) < 0) {
418 	    saved_errno = errno;
419 	    close(s);
420 	    freeaddrinfo(local_res);
421 	    freeaddrinfo(server_res);
422 	    errno = saved_errno;
423             i_errno = IESTREAMCONNECT;
424             return -1;
425         }
426         freeaddrinfo(local_res);
427     }
428     /* --cport, no --bind */
429     else if (test->bind_port) {
430 	size_t addrlen;
431 	struct sockaddr_storage lcl;
432 
433 	/* IPv4 */
434 	if (server_res->ai_family == AF_INET) {
435 	    struct sockaddr_in *lcladdr = (struct sockaddr_in *) &lcl;
436 	    lcladdr->sin_family = AF_INET;
437 	    lcladdr->sin_port = htons(test->bind_port);
438 	    lcladdr->sin_addr.s_addr = INADDR_ANY;
439 	    addrlen = sizeof(struct sockaddr_in);
440 	}
441 	/* IPv6 */
442 	else if (server_res->ai_family == AF_INET6) {
443 	    struct sockaddr_in6 *lcladdr = (struct sockaddr_in6 *) &lcl;
444 	    lcladdr->sin6_family = AF_INET6;
445 	    lcladdr->sin6_port = htons(test->bind_port);
446 	    lcladdr->sin6_addr = in6addr_any;
447 	    addrlen = sizeof(struct sockaddr_in6);
448 	}
449 	/* Unknown protocol */
450 	else {
451 	    saved_errno = errno;
452 	    close(s);
453 	    freeaddrinfo(server_res);
454 	    errno = saved_errno;
455             i_errno = IEPROTOCOL;
456             return -1;
457 	}
458 
459         if (bind(s, (struct sockaddr *) &lcl, addrlen) < 0) {
460 	    saved_errno = errno;
461 	    close(s);
462 	    freeaddrinfo(server_res);
463 	    errno = saved_errno;
464             i_errno = IESTREAMCONNECT;
465             return -1;
466         }
467     }
468 
469     /* Set socket options */
470     if (test->no_delay) {
471         opt = 1;
472         if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)) < 0) {
473 	    saved_errno = errno;
474 	    close(s);
475 	    freeaddrinfo(server_res);
476 	    errno = saved_errno;
477             i_errno = IESETNODELAY;
478             return -1;
479         }
480     }
481     if ((opt = test->settings->mss)) {
482         if (setsockopt(s, IPPROTO_TCP, TCP_MAXSEG, &opt, sizeof(opt)) < 0) {
483 	    saved_errno = errno;
484 	    close(s);
485 	    freeaddrinfo(server_res);
486 	    errno = saved_errno;
487             i_errno = IESETMSS;
488             return -1;
489         }
490     }
491     if ((opt = test->settings->socket_bufsize)) {
492         if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)) < 0) {
493 	    saved_errno = errno;
494 	    close(s);
495 	    freeaddrinfo(server_res);
496 	    errno = saved_errno;
497             i_errno = IESETBUF;
498             return -1;
499         }
500         if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt)) < 0) {
501 	    saved_errno = errno;
502 	    close(s);
503 	    freeaddrinfo(server_res);
504 	    errno = saved_errno;
505             i_errno = IESETBUF;
506             return -1;
507         }
508     }
509 
510     /* Read back and verify the sender socket buffer size */
511     optlen = sizeof(sndbuf_actual);
512     if (getsockopt(s, SOL_SOCKET, SO_SNDBUF, &sndbuf_actual, &optlen) < 0) {
513 	saved_errno = errno;
514 	close(s);
515 	freeaddrinfo(server_res);
516 	errno = saved_errno;
517 	i_errno = IESETBUF;
518 	return -1;
519     }
520     if (test->debug) {
521 	printf("SNDBUF is %u, expecting %u\n", sndbuf_actual, test->settings->socket_bufsize);
522     }
523     if (test->settings->socket_bufsize && test->settings->socket_bufsize > sndbuf_actual) {
524 	i_errno = IESETBUF2;
525 	return -1;
526     }
527 
528     /* Read back and verify the receiver socket buffer size */
529     optlen = sizeof(rcvbuf_actual);
530     if (getsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcvbuf_actual, &optlen) < 0) {
531 	saved_errno = errno;
532 	close(s);
533 	freeaddrinfo(server_res);
534 	errno = saved_errno;
535 	i_errno = IESETBUF;
536 	return -1;
537     }
538     if (test->debug) {
539 	printf("RCVBUF is %u, expecting %u\n", rcvbuf_actual, test->settings->socket_bufsize);
540     }
541     if (test->settings->socket_bufsize && test->settings->socket_bufsize > rcvbuf_actual) {
542 	i_errno = IESETBUF2;
543 	return -1;
544     }
545 
546     if (test->json_output) {
547 	cJSON_AddNumberToObject(test->json_start, "sock_bufsize", test->settings->socket_bufsize);
548 	cJSON_AddNumberToObject(test->json_start, "sndbuf_actual", sndbuf_actual);
549 	cJSON_AddNumberToObject(test->json_start, "rcvbuf_actual", rcvbuf_actual);
550     }
551 
552 #if defined(HAVE_FLOWLABEL)
553     if (test->settings->flowlabel) {
554         if (server_res->ai_addr->sa_family != AF_INET6) {
555 	    saved_errno = errno;
556 	    close(s);
557 	    freeaddrinfo(server_res);
558 	    errno = saved_errno;
559             i_errno = IESETFLOW;
560             return -1;
561 	} else {
562 	    struct sockaddr_in6* sa6P = (struct sockaddr_in6*) server_res->ai_addr;
563             char freq_buf[sizeof(struct in6_flowlabel_req)];
564             struct in6_flowlabel_req *freq = (struct in6_flowlabel_req *)freq_buf;
565             int freq_len = sizeof(*freq);
566 
567             memset(freq, 0, sizeof(*freq));
568             freq->flr_label = htonl(test->settings->flowlabel & IPV6_FLOWINFO_FLOWLABEL);
569             freq->flr_action = IPV6_FL_A_GET;
570             freq->flr_flags = IPV6_FL_F_CREATE;
571             freq->flr_share = IPV6_FL_S_ANY;
572             memcpy(&freq->flr_dst, &sa6P->sin6_addr, 16);
573 
574             if (setsockopt(s, IPPROTO_IPV6, IPV6_FLOWLABEL_MGR, freq, freq_len) < 0) {
575 		saved_errno = errno;
576                 close(s);
577                 freeaddrinfo(server_res);
578 		errno = saved_errno;
579                 i_errno = IESETFLOW;
580                 return -1;
581             }
582             sa6P->sin6_flowinfo = freq->flr_label;
583 
584             opt = 1;
585             if (setsockopt(s, IPPROTO_IPV6, IPV6_FLOWINFO_SEND, &opt, sizeof(opt)) < 0) {
586 		saved_errno = errno;
587                 close(s);
588                 freeaddrinfo(server_res);
589 		errno = saved_errno;
590                 i_errno = IESETFLOW;
591                 return -1;
592             }
593 	}
594     }
595 #endif /* HAVE_FLOWLABEL */
596 
597 #if defined(HAVE_SO_MAX_PACING_RATE)
598     /* If socket pacing is specified try to enable it. */
599     if (test->settings->fqrate) {
600 	/* Convert bits per second to bytes per second */
601 	unsigned int fqrate = test->settings->fqrate / 8;
602 	if (fqrate > 0) {
603 	    if (test->debug) {
604 		printf("Setting fair-queue socket pacing to %u\n", fqrate);
605 	    }
606 	    if (setsockopt(s, SOL_SOCKET, SO_MAX_PACING_RATE, &fqrate, sizeof(fqrate)) < 0) {
607 		warning("Unable to set socket pacing");
608 	    }
609 	}
610     }
611 #endif /* HAVE_SO_MAX_PACING_RATE */
612     {
613 	unsigned int rate = test->settings->rate / 8;
614 	if (rate > 0) {
615 	    if (test->debug) {
616 		printf("Setting application pacing to %u\n", rate);
617 	    }
618 	}
619     }
620 
621     if (connect(s, (struct sockaddr *) server_res->ai_addr, server_res->ai_addrlen) < 0 && errno != EINPROGRESS) {
622 	saved_errno = errno;
623 	close(s);
624 	freeaddrinfo(server_res);
625 	errno = saved_errno;
626         i_errno = IESTREAMCONNECT;
627         return -1;
628     }
629 
630     freeaddrinfo(server_res);
631 
632     /* Send cookie for verification */
633     if (Nwrite(s, test->cookie, COOKIE_SIZE, Ptcp) < 0) {
634 	saved_errno = errno;
635 	close(s);
636 	errno = saved_errno;
637         i_errno = IESENDCOOKIE;
638         return -1;
639     }
640 
641     return s;
642 }
643