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