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 <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 ((gerror = 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 ((gerror = 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 ((gerror = 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