xref: /aosp_15_r20/external/iperf3/src/net.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 "iperf_config.h"
28*7ab6e6acSAndroid Build Coastguard Worker 
29*7ab6e6acSAndroid Build Coastguard Worker #include <stdio.h>
30*7ab6e6acSAndroid Build Coastguard Worker #include <unistd.h>
31*7ab6e6acSAndroid Build Coastguard Worker #include <errno.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 <netinet/tcp.h>
37*7ab6e6acSAndroid Build Coastguard Worker #include <assert.h>
38*7ab6e6acSAndroid Build Coastguard Worker #include <netdb.h>
39*7ab6e6acSAndroid Build Coastguard Worker #include <string.h>
40*7ab6e6acSAndroid Build Coastguard Worker #include <fcntl.h>
41*7ab6e6acSAndroid Build Coastguard Worker #include <limits.h>
42*7ab6e6acSAndroid Build Coastguard Worker 
43*7ab6e6acSAndroid Build Coastguard Worker #ifdef HAVE_SENDFILE
44*7ab6e6acSAndroid Build Coastguard Worker #ifdef linux
45*7ab6e6acSAndroid Build Coastguard Worker #include <sys/sendfile.h>
46*7ab6e6acSAndroid Build Coastguard Worker #else
47*7ab6e6acSAndroid Build Coastguard Worker #ifdef __FreeBSD__
48*7ab6e6acSAndroid Build Coastguard Worker #include <sys/uio.h>
49*7ab6e6acSAndroid Build Coastguard Worker #else
50*7ab6e6acSAndroid Build Coastguard Worker #if defined(__APPLE__) && defined(__MACH__)	/* OS X */
51*7ab6e6acSAndroid Build Coastguard Worker #include <AvailabilityMacros.h>
52*7ab6e6acSAndroid Build Coastguard Worker #if defined(MAC_OS_X_VERSION_10_6)
53*7ab6e6acSAndroid Build Coastguard Worker #include <sys/uio.h>
54*7ab6e6acSAndroid Build Coastguard Worker #endif
55*7ab6e6acSAndroid Build Coastguard Worker #endif
56*7ab6e6acSAndroid Build Coastguard Worker #endif
57*7ab6e6acSAndroid Build Coastguard Worker #endif
58*7ab6e6acSAndroid Build Coastguard Worker #endif /* HAVE_SENDFILE */
59*7ab6e6acSAndroid Build Coastguard Worker 
60*7ab6e6acSAndroid Build Coastguard Worker #ifdef HAVE_POLL_H
61*7ab6e6acSAndroid Build Coastguard Worker #include <poll.h>
62*7ab6e6acSAndroid Build Coastguard Worker #endif /* HAVE_POLL_H */
63*7ab6e6acSAndroid Build Coastguard Worker 
64*7ab6e6acSAndroid Build Coastguard Worker #include "iperf_util.h"
65*7ab6e6acSAndroid Build Coastguard Worker #include "net.h"
66*7ab6e6acSAndroid Build Coastguard Worker #include "timer.h"
67*7ab6e6acSAndroid Build Coastguard Worker 
68*7ab6e6acSAndroid Build Coastguard Worker /*
69*7ab6e6acSAndroid Build Coastguard Worker  * Declaration of gerror in iperf_error.c.  Most other files in iperf3 can get this
70*7ab6e6acSAndroid Build Coastguard Worker  * by including "iperf.h", but net.c lives "below" this layer.  Clearly the
71*7ab6e6acSAndroid Build Coastguard Worker  * presence of this declaration is a sign we need to revisit this layering.
72*7ab6e6acSAndroid Build Coastguard Worker  */
73*7ab6e6acSAndroid Build Coastguard Worker extern int gerror;
74*7ab6e6acSAndroid Build Coastguard Worker 
75*7ab6e6acSAndroid Build Coastguard Worker /*
76*7ab6e6acSAndroid Build Coastguard Worker  * timeout_connect adapted from netcat, via OpenBSD and FreeBSD
77*7ab6e6acSAndroid Build Coastguard Worker  * Copyright (c) 2001 Eric Jackson <[email protected]>
78*7ab6e6acSAndroid Build Coastguard Worker  */
79*7ab6e6acSAndroid Build Coastguard Worker int
timeout_connect(int s,const struct sockaddr * name,socklen_t namelen,int timeout)80*7ab6e6acSAndroid Build Coastguard Worker timeout_connect(int s, const struct sockaddr *name, socklen_t namelen,
81*7ab6e6acSAndroid Build Coastguard Worker     int timeout)
82*7ab6e6acSAndroid Build Coastguard Worker {
83*7ab6e6acSAndroid Build Coastguard Worker 	struct pollfd pfd;
84*7ab6e6acSAndroid Build Coastguard Worker 	socklen_t optlen;
85*7ab6e6acSAndroid Build Coastguard Worker 	int flags, optval;
86*7ab6e6acSAndroid Build Coastguard Worker 	int ret;
87*7ab6e6acSAndroid Build Coastguard Worker 
88*7ab6e6acSAndroid Build Coastguard Worker 	flags = 0;
89*7ab6e6acSAndroid Build Coastguard Worker 	if (timeout != -1) {
90*7ab6e6acSAndroid Build Coastguard Worker 		flags = fcntl(s, F_GETFL, 0);
91*7ab6e6acSAndroid Build Coastguard Worker 		if (fcntl(s, F_SETFL, flags | O_NONBLOCK) == -1)
92*7ab6e6acSAndroid Build Coastguard Worker 			return -1;
93*7ab6e6acSAndroid Build Coastguard Worker 	}
94*7ab6e6acSAndroid Build Coastguard Worker 
95*7ab6e6acSAndroid Build Coastguard Worker 	if ((ret = connect(s, name, namelen)) != 0 && errno == EINPROGRESS) {
96*7ab6e6acSAndroid Build Coastguard Worker 		pfd.fd = s;
97*7ab6e6acSAndroid Build Coastguard Worker 		pfd.events = POLLOUT;
98*7ab6e6acSAndroid Build Coastguard Worker 		if ((ret = poll(&pfd, 1, timeout)) == 1) {
99*7ab6e6acSAndroid Build Coastguard Worker 			optlen = sizeof(optval);
100*7ab6e6acSAndroid Build Coastguard Worker 			if ((ret = getsockopt(s, SOL_SOCKET, SO_ERROR,
101*7ab6e6acSAndroid Build Coastguard Worker 			    &optval, &optlen)) == 0) {
102*7ab6e6acSAndroid Build Coastguard Worker 				errno = optval;
103*7ab6e6acSAndroid Build Coastguard Worker 				ret = optval == 0 ? 0 : -1;
104*7ab6e6acSAndroid Build Coastguard Worker 			}
105*7ab6e6acSAndroid Build Coastguard Worker 		} else if (ret == 0) {
106*7ab6e6acSAndroid Build Coastguard Worker 			errno = ETIMEDOUT;
107*7ab6e6acSAndroid Build Coastguard Worker 			ret = -1;
108*7ab6e6acSAndroid Build Coastguard Worker 		} else
109*7ab6e6acSAndroid Build Coastguard Worker 			ret = -1;
110*7ab6e6acSAndroid Build Coastguard Worker 	}
111*7ab6e6acSAndroid Build Coastguard Worker 
112*7ab6e6acSAndroid Build Coastguard Worker 	if (timeout != -1 && fcntl(s, F_SETFL, flags) == -1)
113*7ab6e6acSAndroid Build Coastguard Worker 		ret = -1;
114*7ab6e6acSAndroid Build Coastguard Worker 
115*7ab6e6acSAndroid Build Coastguard Worker 	return (ret);
116*7ab6e6acSAndroid Build Coastguard Worker }
117*7ab6e6acSAndroid Build Coastguard Worker 
118*7ab6e6acSAndroid Build Coastguard Worker /* netdial and netannouce code comes from libtask: http://swtch.com/libtask/
119*7ab6e6acSAndroid Build Coastguard Worker  * Copyright: http://swtch.com/libtask/COPYRIGHT
120*7ab6e6acSAndroid Build Coastguard Worker */
121*7ab6e6acSAndroid Build Coastguard Worker 
122*7ab6e6acSAndroid Build Coastguard Worker /* make connection to server */
123*7ab6e6acSAndroid Build Coastguard Worker int
netdial(int domain,int proto,const char * local,int local_port,const char * server,int port,int timeout)124*7ab6e6acSAndroid Build Coastguard Worker netdial(int domain, int proto, const char *local, int local_port, const char *server, int port, int timeout)
125*7ab6e6acSAndroid Build Coastguard Worker {
126*7ab6e6acSAndroid Build Coastguard Worker     struct addrinfo hints, *local_res, *server_res;
127*7ab6e6acSAndroid Build Coastguard Worker     int s, saved_errno;
128*7ab6e6acSAndroid Build Coastguard Worker 
129*7ab6e6acSAndroid Build Coastguard Worker     if (local) {
130*7ab6e6acSAndroid Build Coastguard Worker         memset(&hints, 0, sizeof(hints));
131*7ab6e6acSAndroid Build Coastguard Worker         hints.ai_family = domain;
132*7ab6e6acSAndroid Build Coastguard Worker         hints.ai_socktype = proto;
133*7ab6e6acSAndroid Build Coastguard Worker         if ((gerror = getaddrinfo(local, NULL, &hints, &local_res)) != 0)
134*7ab6e6acSAndroid Build Coastguard Worker             return -1;
135*7ab6e6acSAndroid Build Coastguard Worker     }
136*7ab6e6acSAndroid Build Coastguard Worker 
137*7ab6e6acSAndroid Build Coastguard Worker     memset(&hints, 0, sizeof(hints));
138*7ab6e6acSAndroid Build Coastguard Worker     hints.ai_family = domain;
139*7ab6e6acSAndroid Build Coastguard Worker     hints.ai_socktype = proto;
140*7ab6e6acSAndroid Build Coastguard Worker     if ((gerror = getaddrinfo(server, NULL, &hints, &server_res)) != 0)
141*7ab6e6acSAndroid Build Coastguard Worker         return -1;
142*7ab6e6acSAndroid Build Coastguard Worker 
143*7ab6e6acSAndroid Build Coastguard Worker     s = socket(server_res->ai_family, proto, 0);
144*7ab6e6acSAndroid Build Coastguard Worker     if (s < 0) {
145*7ab6e6acSAndroid Build Coastguard Worker 	if (local)
146*7ab6e6acSAndroid Build Coastguard Worker 	    freeaddrinfo(local_res);
147*7ab6e6acSAndroid Build Coastguard Worker 	freeaddrinfo(server_res);
148*7ab6e6acSAndroid Build Coastguard Worker         return -1;
149*7ab6e6acSAndroid Build Coastguard Worker     }
150*7ab6e6acSAndroid Build Coastguard Worker 
151*7ab6e6acSAndroid Build Coastguard Worker     /* Bind the local address if given a name (with or without --cport) */
152*7ab6e6acSAndroid Build Coastguard Worker     if (local) {
153*7ab6e6acSAndroid Build Coastguard Worker         if (local_port) {
154*7ab6e6acSAndroid Build Coastguard Worker             struct sockaddr_in *lcladdr;
155*7ab6e6acSAndroid Build Coastguard Worker             lcladdr = (struct sockaddr_in *)local_res->ai_addr;
156*7ab6e6acSAndroid Build Coastguard Worker             lcladdr->sin_port = htons(local_port);
157*7ab6e6acSAndroid Build Coastguard Worker         }
158*7ab6e6acSAndroid Build Coastguard Worker 
159*7ab6e6acSAndroid Build Coastguard Worker         if (bind(s, (struct sockaddr *) local_res->ai_addr, local_res->ai_addrlen) < 0) {
160*7ab6e6acSAndroid Build Coastguard Worker 	    saved_errno = errno;
161*7ab6e6acSAndroid Build Coastguard Worker 	    close(s);
162*7ab6e6acSAndroid Build Coastguard Worker 	    freeaddrinfo(local_res);
163*7ab6e6acSAndroid Build Coastguard Worker 	    freeaddrinfo(server_res);
164*7ab6e6acSAndroid Build Coastguard Worker 	    errno = saved_errno;
165*7ab6e6acSAndroid Build Coastguard Worker             return -1;
166*7ab6e6acSAndroid Build Coastguard Worker 	}
167*7ab6e6acSAndroid Build Coastguard Worker         freeaddrinfo(local_res);
168*7ab6e6acSAndroid Build Coastguard Worker     }
169*7ab6e6acSAndroid Build Coastguard Worker     /* No local name, but --cport given */
170*7ab6e6acSAndroid Build Coastguard Worker     else if (local_port) {
171*7ab6e6acSAndroid Build Coastguard Worker 	size_t addrlen;
172*7ab6e6acSAndroid Build Coastguard Worker 	struct sockaddr_storage lcl;
173*7ab6e6acSAndroid Build Coastguard Worker 
174*7ab6e6acSAndroid Build Coastguard Worker 	/* IPv4 */
175*7ab6e6acSAndroid Build Coastguard Worker 	if (server_res->ai_family == AF_INET) {
176*7ab6e6acSAndroid Build Coastguard Worker 	    struct sockaddr_in *lcladdr = (struct sockaddr_in *) &lcl;
177*7ab6e6acSAndroid Build Coastguard Worker 	    lcladdr->sin_family = AF_INET;
178*7ab6e6acSAndroid Build Coastguard Worker 	    lcladdr->sin_port = htons(local_port);
179*7ab6e6acSAndroid Build Coastguard Worker 	    lcladdr->sin_addr.s_addr = INADDR_ANY;
180*7ab6e6acSAndroid Build Coastguard Worker 	    addrlen = sizeof(struct sockaddr_in);
181*7ab6e6acSAndroid Build Coastguard Worker 	}
182*7ab6e6acSAndroid Build Coastguard Worker 	/* IPv6 */
183*7ab6e6acSAndroid Build Coastguard Worker 	else if (server_res->ai_family == AF_INET6) {
184*7ab6e6acSAndroid Build Coastguard Worker 	    struct sockaddr_in6 *lcladdr = (struct sockaddr_in6 *) &lcl;
185*7ab6e6acSAndroid Build Coastguard Worker 	    lcladdr->sin6_family = AF_INET6;
186*7ab6e6acSAndroid Build Coastguard Worker 	    lcladdr->sin6_port = htons(local_port);
187*7ab6e6acSAndroid Build Coastguard Worker 	    lcladdr->sin6_addr = in6addr_any;
188*7ab6e6acSAndroid Build Coastguard Worker 	    addrlen = sizeof(struct sockaddr_in6);
189*7ab6e6acSAndroid Build Coastguard Worker 	}
190*7ab6e6acSAndroid Build Coastguard Worker 	/* Unknown protocol */
191*7ab6e6acSAndroid Build Coastguard Worker 	else {
192*7ab6e6acSAndroid Build Coastguard Worker 	    errno = EAFNOSUPPORT;
193*7ab6e6acSAndroid Build Coastguard Worker             return -1;
194*7ab6e6acSAndroid Build Coastguard Worker 	}
195*7ab6e6acSAndroid Build Coastguard Worker 
196*7ab6e6acSAndroid Build Coastguard Worker         if (bind(s, (struct sockaddr *) &lcl, addrlen) < 0) {
197*7ab6e6acSAndroid Build Coastguard Worker 	    saved_errno = errno;
198*7ab6e6acSAndroid Build Coastguard Worker 	    close(s);
199*7ab6e6acSAndroid Build Coastguard Worker 	    freeaddrinfo(server_res);
200*7ab6e6acSAndroid Build Coastguard Worker 	    errno = saved_errno;
201*7ab6e6acSAndroid Build Coastguard Worker             return -1;
202*7ab6e6acSAndroid Build Coastguard Worker         }
203*7ab6e6acSAndroid Build Coastguard Worker     }
204*7ab6e6acSAndroid Build Coastguard Worker 
205*7ab6e6acSAndroid Build Coastguard Worker     ((struct sockaddr_in *) server_res->ai_addr)->sin_port = htons(port);
206*7ab6e6acSAndroid Build Coastguard Worker     if (timeout_connect(s, (struct sockaddr *) server_res->ai_addr, server_res->ai_addrlen, timeout) < 0 && errno != EINPROGRESS) {
207*7ab6e6acSAndroid Build Coastguard Worker 	saved_errno = errno;
208*7ab6e6acSAndroid Build Coastguard Worker 	close(s);
209*7ab6e6acSAndroid Build Coastguard Worker 	freeaddrinfo(server_res);
210*7ab6e6acSAndroid Build Coastguard Worker 	errno = saved_errno;
211*7ab6e6acSAndroid Build Coastguard Worker         return -1;
212*7ab6e6acSAndroid Build Coastguard Worker     }
213*7ab6e6acSAndroid Build Coastguard Worker 
214*7ab6e6acSAndroid Build Coastguard Worker     freeaddrinfo(server_res);
215*7ab6e6acSAndroid Build Coastguard Worker     return s;
216*7ab6e6acSAndroid Build Coastguard Worker }
217*7ab6e6acSAndroid Build Coastguard Worker 
218*7ab6e6acSAndroid Build Coastguard Worker /***************************************************************/
219*7ab6e6acSAndroid Build Coastguard Worker 
220*7ab6e6acSAndroid Build Coastguard Worker int
netannounce(int domain,int proto,const char * local,int port)221*7ab6e6acSAndroid Build Coastguard Worker netannounce(int domain, int proto, const char *local, int port)
222*7ab6e6acSAndroid Build Coastguard Worker {
223*7ab6e6acSAndroid Build Coastguard Worker     struct addrinfo hints, *res;
224*7ab6e6acSAndroid Build Coastguard Worker     char portstr[6];
225*7ab6e6acSAndroid Build Coastguard Worker     int s, opt, saved_errno;
226*7ab6e6acSAndroid Build Coastguard Worker 
227*7ab6e6acSAndroid Build Coastguard Worker     snprintf(portstr, 6, "%d", port);
228*7ab6e6acSAndroid Build Coastguard Worker     memset(&hints, 0, sizeof(hints));
229*7ab6e6acSAndroid Build Coastguard Worker     /*
230*7ab6e6acSAndroid Build Coastguard Worker      * If binding to the wildcard address with no explicit address
231*7ab6e6acSAndroid Build Coastguard Worker      * family specified, then force us to get an AF_INET6 socket.  On
232*7ab6e6acSAndroid Build Coastguard Worker      * CentOS 6 and MacOS, getaddrinfo(3) with AF_UNSPEC in ai_family,
233*7ab6e6acSAndroid Build Coastguard Worker      * and ai_flags containing AI_PASSIVE returns a result structure
234*7ab6e6acSAndroid Build Coastguard Worker      * with ai_family set to AF_INET, with the result that we create
235*7ab6e6acSAndroid Build Coastguard Worker      * and bind an IPv4 address wildcard address and by default, we
236*7ab6e6acSAndroid Build Coastguard Worker      * can't accept IPv6 connections.
237*7ab6e6acSAndroid Build Coastguard Worker      *
238*7ab6e6acSAndroid Build Coastguard Worker      * On FreeBSD, under the above circumstances, ai_family in the
239*7ab6e6acSAndroid Build Coastguard Worker      * result structure is set to AF_INET6.
240*7ab6e6acSAndroid Build Coastguard Worker      */
241*7ab6e6acSAndroid Build Coastguard Worker     if (domain == AF_UNSPEC && !local) {
242*7ab6e6acSAndroid Build Coastguard Worker 	hints.ai_family = AF_INET6;
243*7ab6e6acSAndroid Build Coastguard Worker     }
244*7ab6e6acSAndroid Build Coastguard Worker     else {
245*7ab6e6acSAndroid Build Coastguard Worker 	hints.ai_family = domain;
246*7ab6e6acSAndroid Build Coastguard Worker     }
247*7ab6e6acSAndroid Build Coastguard Worker     hints.ai_socktype = proto;
248*7ab6e6acSAndroid Build Coastguard Worker     hints.ai_flags = AI_PASSIVE;
249*7ab6e6acSAndroid Build Coastguard Worker     if ((gerror = getaddrinfo(local, portstr, &hints, &res)) != 0)
250*7ab6e6acSAndroid Build Coastguard Worker         return -1;
251*7ab6e6acSAndroid Build Coastguard Worker 
252*7ab6e6acSAndroid Build Coastguard Worker     s = socket(res->ai_family, proto, 0);
253*7ab6e6acSAndroid Build Coastguard Worker     if (s < 0) {
254*7ab6e6acSAndroid Build Coastguard Worker 	freeaddrinfo(res);
255*7ab6e6acSAndroid Build Coastguard Worker         return -1;
256*7ab6e6acSAndroid Build Coastguard Worker     }
257*7ab6e6acSAndroid Build Coastguard Worker 
258*7ab6e6acSAndroid Build Coastguard Worker     opt = 1;
259*7ab6e6acSAndroid Build Coastguard Worker     if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
260*7ab6e6acSAndroid Build Coastguard Worker 		   (char *) &opt, sizeof(opt)) < 0) {
261*7ab6e6acSAndroid Build Coastguard Worker 	saved_errno = errno;
262*7ab6e6acSAndroid Build Coastguard Worker 	close(s);
263*7ab6e6acSAndroid Build Coastguard Worker 	freeaddrinfo(res);
264*7ab6e6acSAndroid Build Coastguard Worker 	errno = saved_errno;
265*7ab6e6acSAndroid Build Coastguard Worker 	return -1;
266*7ab6e6acSAndroid Build Coastguard Worker     }
267*7ab6e6acSAndroid Build Coastguard Worker     /*
268*7ab6e6acSAndroid Build Coastguard Worker      * If we got an IPv6 socket, figure out if it should accept IPv4
269*7ab6e6acSAndroid Build Coastguard Worker      * connections as well.  We do that if and only if no address
270*7ab6e6acSAndroid Build Coastguard Worker      * family was specified explicitly.  Note that we can only
271*7ab6e6acSAndroid Build Coastguard Worker      * do this if the IPV6_V6ONLY socket option is supported.  Also,
272*7ab6e6acSAndroid Build Coastguard Worker      * OpenBSD explicitly omits support for IPv4-mapped addresses,
273*7ab6e6acSAndroid Build Coastguard Worker      * even though it implements IPV6_V6ONLY.
274*7ab6e6acSAndroid Build Coastguard Worker      */
275*7ab6e6acSAndroid Build Coastguard Worker #if defined(IPV6_V6ONLY) && !defined(__OpenBSD__)
276*7ab6e6acSAndroid Build Coastguard Worker     if (res->ai_family == AF_INET6 && (domain == AF_UNSPEC || domain == AF_INET6)) {
277*7ab6e6acSAndroid Build Coastguard Worker 	if (domain == AF_UNSPEC)
278*7ab6e6acSAndroid Build Coastguard Worker 	    opt = 0;
279*7ab6e6acSAndroid Build Coastguard Worker 	else
280*7ab6e6acSAndroid Build Coastguard Worker 	    opt = 1;
281*7ab6e6acSAndroid Build Coastguard Worker 	if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
282*7ab6e6acSAndroid Build Coastguard Worker 		       (char *) &opt, sizeof(opt)) < 0) {
283*7ab6e6acSAndroid Build Coastguard Worker 	    saved_errno = errno;
284*7ab6e6acSAndroid Build Coastguard Worker 	    close(s);
285*7ab6e6acSAndroid Build Coastguard Worker 	    freeaddrinfo(res);
286*7ab6e6acSAndroid Build Coastguard Worker 	    errno = saved_errno;
287*7ab6e6acSAndroid Build Coastguard Worker 	    return -1;
288*7ab6e6acSAndroid Build Coastguard Worker 	}
289*7ab6e6acSAndroid Build Coastguard Worker     }
290*7ab6e6acSAndroid Build Coastguard Worker #endif /* IPV6_V6ONLY */
291*7ab6e6acSAndroid Build Coastguard Worker 
292*7ab6e6acSAndroid Build Coastguard Worker     if (bind(s, (struct sockaddr *) res->ai_addr, res->ai_addrlen) < 0) {
293*7ab6e6acSAndroid Build Coastguard Worker         saved_errno = errno;
294*7ab6e6acSAndroid Build Coastguard Worker         close(s);
295*7ab6e6acSAndroid Build Coastguard Worker 	freeaddrinfo(res);
296*7ab6e6acSAndroid Build Coastguard Worker         errno = saved_errno;
297*7ab6e6acSAndroid Build Coastguard Worker         return -1;
298*7ab6e6acSAndroid Build Coastguard Worker     }
299*7ab6e6acSAndroid Build Coastguard Worker 
300*7ab6e6acSAndroid Build Coastguard Worker     freeaddrinfo(res);
301*7ab6e6acSAndroid Build Coastguard Worker 
302*7ab6e6acSAndroid Build Coastguard Worker     if (proto == SOCK_STREAM) {
303*7ab6e6acSAndroid Build Coastguard Worker         if (listen(s, INT_MAX) < 0) {
304*7ab6e6acSAndroid Build Coastguard Worker 	    saved_errno = errno;
305*7ab6e6acSAndroid Build Coastguard Worker 	    close(s);
306*7ab6e6acSAndroid Build Coastguard Worker 	    errno = saved_errno;
307*7ab6e6acSAndroid Build Coastguard Worker             return -1;
308*7ab6e6acSAndroid Build Coastguard Worker         }
309*7ab6e6acSAndroid Build Coastguard Worker     }
310*7ab6e6acSAndroid Build Coastguard Worker 
311*7ab6e6acSAndroid Build Coastguard Worker     return s;
312*7ab6e6acSAndroid Build Coastguard Worker }
313*7ab6e6acSAndroid Build Coastguard Worker 
314*7ab6e6acSAndroid Build Coastguard Worker 
315*7ab6e6acSAndroid Build Coastguard Worker /*******************************************************************/
316*7ab6e6acSAndroid Build Coastguard Worker /* reads 'count' bytes from a socket  */
317*7ab6e6acSAndroid Build Coastguard Worker /********************************************************************/
318*7ab6e6acSAndroid Build Coastguard Worker 
319*7ab6e6acSAndroid Build Coastguard Worker int
Nread(int fd,char * buf,size_t count,int prot)320*7ab6e6acSAndroid Build Coastguard Worker Nread(int fd, char *buf, size_t count, int prot)
321*7ab6e6acSAndroid Build Coastguard Worker {
322*7ab6e6acSAndroid Build Coastguard Worker     register ssize_t r;
323*7ab6e6acSAndroid Build Coastguard Worker     register size_t nleft = count;
324*7ab6e6acSAndroid Build Coastguard Worker 
325*7ab6e6acSAndroid Build Coastguard Worker     while (nleft > 0) {
326*7ab6e6acSAndroid Build Coastguard Worker         r = read(fd, buf, nleft);
327*7ab6e6acSAndroid Build Coastguard Worker         if (r < 0) {
328*7ab6e6acSAndroid Build Coastguard Worker             if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
329*7ab6e6acSAndroid Build Coastguard Worker                 break;
330*7ab6e6acSAndroid Build Coastguard Worker             else
331*7ab6e6acSAndroid Build Coastguard Worker                 return NET_HARDERROR;
332*7ab6e6acSAndroid Build Coastguard Worker         } else if (r == 0)
333*7ab6e6acSAndroid Build Coastguard Worker             break;
334*7ab6e6acSAndroid Build Coastguard Worker 
335*7ab6e6acSAndroid Build Coastguard Worker         nleft -= r;
336*7ab6e6acSAndroid Build Coastguard Worker         buf += r;
337*7ab6e6acSAndroid Build Coastguard Worker     }
338*7ab6e6acSAndroid Build Coastguard Worker     return count - nleft;
339*7ab6e6acSAndroid Build Coastguard Worker }
340*7ab6e6acSAndroid Build Coastguard Worker 
341*7ab6e6acSAndroid Build Coastguard Worker 
342*7ab6e6acSAndroid Build Coastguard Worker /*
343*7ab6e6acSAndroid Build Coastguard Worker  *                      N W R I T E
344*7ab6e6acSAndroid Build Coastguard Worker  */
345*7ab6e6acSAndroid Build Coastguard Worker 
346*7ab6e6acSAndroid Build Coastguard Worker int
Nwrite(int fd,const char * buf,size_t count,int prot)347*7ab6e6acSAndroid Build Coastguard Worker Nwrite(int fd, const char *buf, size_t count, int prot)
348*7ab6e6acSAndroid Build Coastguard Worker {
349*7ab6e6acSAndroid Build Coastguard Worker     register ssize_t r;
350*7ab6e6acSAndroid Build Coastguard Worker     register size_t nleft = count;
351*7ab6e6acSAndroid Build Coastguard Worker 
352*7ab6e6acSAndroid Build Coastguard Worker     while (nleft > 0) {
353*7ab6e6acSAndroid Build Coastguard Worker 	r = write(fd, buf, nleft);
354*7ab6e6acSAndroid Build Coastguard Worker 	if (r < 0) {
355*7ab6e6acSAndroid Build Coastguard Worker 	    switch (errno) {
356*7ab6e6acSAndroid Build Coastguard Worker 		case EINTR:
357*7ab6e6acSAndroid Build Coastguard Worker 		case EAGAIN:
358*7ab6e6acSAndroid Build Coastguard Worker #if (EAGAIN != EWOULDBLOCK)
359*7ab6e6acSAndroid Build Coastguard Worker 		case EWOULDBLOCK:
360*7ab6e6acSAndroid Build Coastguard Worker #endif
361*7ab6e6acSAndroid Build Coastguard Worker 		return count - nleft;
362*7ab6e6acSAndroid Build Coastguard Worker 
363*7ab6e6acSAndroid Build Coastguard Worker 		case ENOBUFS:
364*7ab6e6acSAndroid Build Coastguard Worker 		return NET_SOFTERROR;
365*7ab6e6acSAndroid Build Coastguard Worker 
366*7ab6e6acSAndroid Build Coastguard Worker 		default:
367*7ab6e6acSAndroid Build Coastguard Worker 		return NET_HARDERROR;
368*7ab6e6acSAndroid Build Coastguard Worker 	    }
369*7ab6e6acSAndroid Build Coastguard Worker 	} else if (r == 0)
370*7ab6e6acSAndroid Build Coastguard Worker 	    return NET_SOFTERROR;
371*7ab6e6acSAndroid Build Coastguard Worker 	nleft -= r;
372*7ab6e6acSAndroid Build Coastguard Worker 	buf += r;
373*7ab6e6acSAndroid Build Coastguard Worker     }
374*7ab6e6acSAndroid Build Coastguard Worker     return count;
375*7ab6e6acSAndroid Build Coastguard Worker }
376*7ab6e6acSAndroid Build Coastguard Worker 
377*7ab6e6acSAndroid Build Coastguard Worker 
378*7ab6e6acSAndroid Build Coastguard Worker int
has_sendfile(void)379*7ab6e6acSAndroid Build Coastguard Worker has_sendfile(void)
380*7ab6e6acSAndroid Build Coastguard Worker {
381*7ab6e6acSAndroid Build Coastguard Worker #if defined(HAVE_SENDFILE)
382*7ab6e6acSAndroid Build Coastguard Worker     return 1;
383*7ab6e6acSAndroid Build Coastguard Worker #else /* HAVE_SENDFILE */
384*7ab6e6acSAndroid Build Coastguard Worker     return 0;
385*7ab6e6acSAndroid Build Coastguard Worker #endif /* HAVE_SENDFILE */
386*7ab6e6acSAndroid Build Coastguard Worker 
387*7ab6e6acSAndroid Build Coastguard Worker }
388*7ab6e6acSAndroid Build Coastguard Worker 
389*7ab6e6acSAndroid Build Coastguard Worker 
390*7ab6e6acSAndroid Build Coastguard Worker /*
391*7ab6e6acSAndroid Build Coastguard Worker  *                      N S E N D F I L E
392*7ab6e6acSAndroid Build Coastguard Worker  */
393*7ab6e6acSAndroid Build Coastguard Worker 
394*7ab6e6acSAndroid Build Coastguard Worker int
Nsendfile(int fromfd,int tofd,const char * buf,size_t count)395*7ab6e6acSAndroid Build Coastguard Worker Nsendfile(int fromfd, int tofd, const char *buf, size_t count)
396*7ab6e6acSAndroid Build Coastguard Worker {
397*7ab6e6acSAndroid Build Coastguard Worker     off_t offset;
398*7ab6e6acSAndroid Build Coastguard Worker #if defined(HAVE_SENDFILE)
399*7ab6e6acSAndroid Build Coastguard Worker #if defined(__FreeBSD__) || (defined(__APPLE__) && defined(__MACH__) && defined(MAC_OS_X_VERSION_10_6))
400*7ab6e6acSAndroid Build Coastguard Worker     off_t sent;
401*7ab6e6acSAndroid Build Coastguard Worker #endif
402*7ab6e6acSAndroid Build Coastguard Worker     register size_t nleft;
403*7ab6e6acSAndroid Build Coastguard Worker     register ssize_t r;
404*7ab6e6acSAndroid Build Coastguard Worker 
405*7ab6e6acSAndroid Build Coastguard Worker     nleft = count;
406*7ab6e6acSAndroid Build Coastguard Worker     while (nleft > 0) {
407*7ab6e6acSAndroid Build Coastguard Worker 	offset = count - nleft;
408*7ab6e6acSAndroid Build Coastguard Worker #ifdef linux
409*7ab6e6acSAndroid Build Coastguard Worker 	r = sendfile(tofd, fromfd, &offset, nleft);
410*7ab6e6acSAndroid Build Coastguard Worker 	if (r > 0)
411*7ab6e6acSAndroid Build Coastguard Worker 	    nleft -= r;
412*7ab6e6acSAndroid Build Coastguard Worker #elif defined(__FreeBSD__)
413*7ab6e6acSAndroid Build Coastguard Worker 	r = sendfile(fromfd, tofd, offset, nleft, NULL, &sent, 0);
414*7ab6e6acSAndroid Build Coastguard Worker 	nleft -= sent;
415*7ab6e6acSAndroid Build Coastguard Worker #elif defined(__APPLE__) && defined(__MACH__) && defined(MAC_OS_X_VERSION_10_6)	/* OS X */
416*7ab6e6acSAndroid Build Coastguard Worker 	sent = nleft;
417*7ab6e6acSAndroid Build Coastguard Worker 	r = sendfile(fromfd, tofd, offset, &sent, NULL, 0);
418*7ab6e6acSAndroid Build Coastguard Worker 	nleft -= sent;
419*7ab6e6acSAndroid Build Coastguard Worker #else
420*7ab6e6acSAndroid Build Coastguard Worker 	/* Shouldn't happen. */
421*7ab6e6acSAndroid Build Coastguard Worker 	r = -1;
422*7ab6e6acSAndroid Build Coastguard Worker 	errno = ENOSYS;
423*7ab6e6acSAndroid Build Coastguard Worker #endif
424*7ab6e6acSAndroid Build Coastguard Worker 	if (r < 0) {
425*7ab6e6acSAndroid Build Coastguard Worker 	    switch (errno) {
426*7ab6e6acSAndroid Build Coastguard Worker 		case EINTR:
427*7ab6e6acSAndroid Build Coastguard Worker 		case EAGAIN:
428*7ab6e6acSAndroid Build Coastguard Worker #if (EAGAIN != EWOULDBLOCK)
429*7ab6e6acSAndroid Build Coastguard Worker 		case EWOULDBLOCK:
430*7ab6e6acSAndroid Build Coastguard Worker #endif
431*7ab6e6acSAndroid Build Coastguard Worker 		if (count == nleft)
432*7ab6e6acSAndroid Build Coastguard Worker 		    return NET_SOFTERROR;
433*7ab6e6acSAndroid Build Coastguard Worker 		return count - nleft;
434*7ab6e6acSAndroid Build Coastguard Worker 
435*7ab6e6acSAndroid Build Coastguard Worker 		case ENOBUFS:
436*7ab6e6acSAndroid Build Coastguard Worker 		case ENOMEM:
437*7ab6e6acSAndroid Build Coastguard Worker 		return NET_SOFTERROR;
438*7ab6e6acSAndroid Build Coastguard Worker 
439*7ab6e6acSAndroid Build Coastguard Worker 		default:
440*7ab6e6acSAndroid Build Coastguard Worker 		return NET_HARDERROR;
441*7ab6e6acSAndroid Build Coastguard Worker 	    }
442*7ab6e6acSAndroid Build Coastguard Worker 	}
443*7ab6e6acSAndroid Build Coastguard Worker #ifdef linux
444*7ab6e6acSAndroid Build Coastguard Worker 	else if (r == 0)
445*7ab6e6acSAndroid Build Coastguard Worker 	    return NET_SOFTERROR;
446*7ab6e6acSAndroid Build Coastguard Worker #endif
447*7ab6e6acSAndroid Build Coastguard Worker     }
448*7ab6e6acSAndroid Build Coastguard Worker     return count;
449*7ab6e6acSAndroid Build Coastguard Worker #else /* HAVE_SENDFILE */
450*7ab6e6acSAndroid Build Coastguard Worker     errno = ENOSYS;	/* error if somehow get called without HAVE_SENDFILE */
451*7ab6e6acSAndroid Build Coastguard Worker     return NET_HARDERROR;
452*7ab6e6acSAndroid Build Coastguard Worker #endif /* HAVE_SENDFILE */
453*7ab6e6acSAndroid Build Coastguard Worker }
454*7ab6e6acSAndroid Build Coastguard Worker 
455*7ab6e6acSAndroid Build Coastguard Worker /*************************************************************************/
456*7ab6e6acSAndroid Build Coastguard Worker 
457*7ab6e6acSAndroid Build Coastguard Worker int
setnonblocking(int fd,int nonblocking)458*7ab6e6acSAndroid Build Coastguard Worker setnonblocking(int fd, int nonblocking)
459*7ab6e6acSAndroid Build Coastguard Worker {
460*7ab6e6acSAndroid Build Coastguard Worker     int flags, newflags;
461*7ab6e6acSAndroid Build Coastguard Worker 
462*7ab6e6acSAndroid Build Coastguard Worker     flags = fcntl(fd, F_GETFL, 0);
463*7ab6e6acSAndroid Build Coastguard Worker     if (flags < 0) {
464*7ab6e6acSAndroid Build Coastguard Worker         perror("fcntl(F_GETFL)");
465*7ab6e6acSAndroid Build Coastguard Worker         return -1;
466*7ab6e6acSAndroid Build Coastguard Worker     }
467*7ab6e6acSAndroid Build Coastguard Worker     if (nonblocking)
468*7ab6e6acSAndroid Build Coastguard Worker 	newflags = flags | (int) O_NONBLOCK;
469*7ab6e6acSAndroid Build Coastguard Worker     else
470*7ab6e6acSAndroid Build Coastguard Worker 	newflags = flags & ~((int) O_NONBLOCK);
471*7ab6e6acSAndroid Build Coastguard Worker     if (newflags != flags)
472*7ab6e6acSAndroid Build Coastguard Worker 	if (fcntl(fd, F_SETFL, newflags) < 0) {
473*7ab6e6acSAndroid Build Coastguard Worker 	    perror("fcntl(F_SETFL)");
474*7ab6e6acSAndroid Build Coastguard Worker 	    return -1;
475*7ab6e6acSAndroid Build Coastguard Worker 	}
476*7ab6e6acSAndroid Build Coastguard Worker     return 0;
477*7ab6e6acSAndroid Build Coastguard Worker }
478*7ab6e6acSAndroid Build Coastguard Worker 
479*7ab6e6acSAndroid Build Coastguard Worker /****************************************************************************/
480*7ab6e6acSAndroid Build Coastguard Worker 
481*7ab6e6acSAndroid Build Coastguard Worker int
getsockdomain(int sock)482*7ab6e6acSAndroid Build Coastguard Worker getsockdomain(int sock)
483*7ab6e6acSAndroid Build Coastguard Worker {
484*7ab6e6acSAndroid Build Coastguard Worker     struct sockaddr_storage sa;
485*7ab6e6acSAndroid Build Coastguard Worker     socklen_t len = sizeof(sa);
486*7ab6e6acSAndroid Build Coastguard Worker 
487*7ab6e6acSAndroid Build Coastguard Worker     if (getsockname(sock, (struct sockaddr *)&sa, &len) < 0) {
488*7ab6e6acSAndroid Build Coastguard Worker         return -1;
489*7ab6e6acSAndroid Build Coastguard Worker     }
490*7ab6e6acSAndroid Build Coastguard Worker     return ((struct sockaddr *) &sa)->sa_family;
491*7ab6e6acSAndroid Build Coastguard Worker }
492