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