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