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