1 /*
2 * iperf, Copyright (c) 2014-2022, 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 [email protected].
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_level >= DEBUG_LEVEL_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 should 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 *server_res;
373 int s, opt;
374 socklen_t optlen;
375 int saved_errno;
376 int rcvbuf_actual, sndbuf_actual;
377
378 s = create_socket(test->settings->domain, SOCK_STREAM, test->bind_address, test->bind_dev, test->bind_port, test->server_hostname, test->server_port, &server_res);
379 if (s < 0) {
380 i_errno = IESTREAMCONNECT;
381 return -1;
382 }
383
384 /* Set socket options */
385 if (test->no_delay) {
386 opt = 1;
387 if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)) < 0) {
388 saved_errno = errno;
389 close(s);
390 freeaddrinfo(server_res);
391 errno = saved_errno;
392 i_errno = IESETNODELAY;
393 return -1;
394 }
395 }
396 if ((opt = test->settings->mss)) {
397 if (setsockopt(s, IPPROTO_TCP, TCP_MAXSEG, &opt, sizeof(opt)) < 0) {
398 saved_errno = errno;
399 close(s);
400 freeaddrinfo(server_res);
401 errno = saved_errno;
402 i_errno = IESETMSS;
403 return -1;
404 }
405 }
406 if ((opt = test->settings->socket_bufsize)) {
407 if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)) < 0) {
408 saved_errno = errno;
409 close(s);
410 freeaddrinfo(server_res);
411 errno = saved_errno;
412 i_errno = IESETBUF;
413 return -1;
414 }
415 if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt)) < 0) {
416 saved_errno = errno;
417 close(s);
418 freeaddrinfo(server_res);
419 errno = saved_errno;
420 i_errno = IESETBUF;
421 return -1;
422 }
423 }
424 #if defined(HAVE_TCP_USER_TIMEOUT)
425 if ((opt = test->settings->snd_timeout)) {
426 if (setsockopt(s, IPPROTO_TCP, TCP_USER_TIMEOUT, &opt, sizeof(opt)) < 0) {
427 saved_errno = errno;
428 close(s);
429 freeaddrinfo(server_res);
430 errno = saved_errno;
431 i_errno = IESETUSERTIMEOUT;
432 return -1;
433 }
434 }
435 #endif /* HAVE_TCP_USER_TIMEOUT */
436
437 /* Read back and verify the sender socket buffer size */
438 optlen = sizeof(sndbuf_actual);
439 if (getsockopt(s, SOL_SOCKET, SO_SNDBUF, &sndbuf_actual, &optlen) < 0) {
440 saved_errno = errno;
441 close(s);
442 freeaddrinfo(server_res);
443 errno = saved_errno;
444 i_errno = IESETBUF;
445 return -1;
446 }
447 if (test->debug) {
448 printf("SNDBUF is %u, expecting %u\n", sndbuf_actual, test->settings->socket_bufsize);
449 }
450 if (test->settings->socket_bufsize && test->settings->socket_bufsize > sndbuf_actual) {
451 i_errno = IESETBUF2;
452 return -1;
453 }
454
455 /* Read back and verify the receiver socket buffer size */
456 optlen = sizeof(rcvbuf_actual);
457 if (getsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcvbuf_actual, &optlen) < 0) {
458 saved_errno = errno;
459 close(s);
460 freeaddrinfo(server_res);
461 errno = saved_errno;
462 i_errno = IESETBUF;
463 return -1;
464 }
465 if (test->debug) {
466 printf("RCVBUF is %u, expecting %u\n", rcvbuf_actual, test->settings->socket_bufsize);
467 }
468 if (test->settings->socket_bufsize && test->settings->socket_bufsize > rcvbuf_actual) {
469 i_errno = IESETBUF2;
470 return -1;
471 }
472
473 if (test->json_output) {
474 cJSON_AddNumberToObject(test->json_start, "sock_bufsize", test->settings->socket_bufsize);
475 cJSON_AddNumberToObject(test->json_start, "sndbuf_actual", sndbuf_actual);
476 cJSON_AddNumberToObject(test->json_start, "rcvbuf_actual", rcvbuf_actual);
477 }
478
479 #if defined(HAVE_FLOWLABEL)
480 if (test->settings->flowlabel) {
481 if (server_res->ai_addr->sa_family != AF_INET6) {
482 saved_errno = errno;
483 close(s);
484 freeaddrinfo(server_res);
485 errno = saved_errno;
486 i_errno = IESETFLOW;
487 return -1;
488 } else {
489 struct sockaddr_in6* sa6P = (struct sockaddr_in6*) server_res->ai_addr;
490 char freq_buf[sizeof(struct in6_flowlabel_req)];
491 struct in6_flowlabel_req *freq = (struct in6_flowlabel_req *)freq_buf;
492 int freq_len = sizeof(*freq);
493
494 memset(freq, 0, sizeof(*freq));
495 freq->flr_label = htonl(test->settings->flowlabel & IPV6_FLOWINFO_FLOWLABEL);
496 freq->flr_action = IPV6_FL_A_GET;
497 freq->flr_flags = IPV6_FL_F_CREATE;
498 freq->flr_share = IPV6_FL_S_ANY;
499 memcpy(&freq->flr_dst, &sa6P->sin6_addr, 16);
500
501 if (setsockopt(s, IPPROTO_IPV6, IPV6_FLOWLABEL_MGR, freq, freq_len) < 0) {
502 saved_errno = errno;
503 close(s);
504 freeaddrinfo(server_res);
505 errno = saved_errno;
506 i_errno = IESETFLOW;
507 return -1;
508 }
509 sa6P->sin6_flowinfo = freq->flr_label;
510
511 opt = 1;
512 if (setsockopt(s, IPPROTO_IPV6, IPV6_FLOWINFO_SEND, &opt, sizeof(opt)) < 0) {
513 saved_errno = errno;
514 close(s);
515 freeaddrinfo(server_res);
516 errno = saved_errno;
517 i_errno = IESETFLOW;
518 return -1;
519 }
520 }
521 }
522 #endif /* HAVE_FLOWLABEL */
523
524 #if defined(HAVE_SO_MAX_PACING_RATE)
525 /* If socket pacing is specified try to enable it. */
526 if (test->settings->fqrate) {
527 /* Convert bits per second to bytes per second */
528 unsigned int fqrate = test->settings->fqrate / 8;
529 if (fqrate > 0) {
530 if (test->debug) {
531 printf("Setting fair-queue socket pacing to %u\n", fqrate);
532 }
533 if (setsockopt(s, SOL_SOCKET, SO_MAX_PACING_RATE, &fqrate, sizeof(fqrate)) < 0) {
534 warning("Unable to set socket pacing");
535 }
536 }
537 }
538 #endif /* HAVE_SO_MAX_PACING_RATE */
539 {
540 unsigned int rate = test->settings->rate / 8;
541 if (rate > 0) {
542 if (test->debug) {
543 printf("Setting application pacing to %u\n", rate);
544 }
545 }
546 }
547
548 if (connect(s, (struct sockaddr *) server_res->ai_addr, server_res->ai_addrlen) < 0 && errno != EINPROGRESS) {
549 saved_errno = errno;
550 close(s);
551 freeaddrinfo(server_res);
552 errno = saved_errno;
553 i_errno = IESTREAMCONNECT;
554 return -1;
555 }
556
557 freeaddrinfo(server_res);
558
559 /* Send cookie for verification */
560 if (Nwrite(s, test->cookie, COOKIE_SIZE, Ptcp) < 0) {
561 saved_errno = errno;
562 close(s);
563 errno = saved_errno;
564 i_errno = IESENDCOOKIE;
565 return -1;
566 }
567
568 return s;
569 }
570