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