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