1 /* 2 * Copyright (c) 2009-2014, The Regents of the University of California, 3 * through Lawrence Berkeley National Laboratory (subject to receipt of any 4 * required approvals from the U.S. Dept. of Energy). All rights reserved. 5 * 6 * This code is distributed under a BSD style license, see the LICENSE file 7 * for complete information. 8 */ 9 #include "iperf_config.h" 10 11 #include <stdio.h> 12 #include <unistd.h> 13 #include <errno.h> 14 #include <sys/socket.h> 15 #include <sys/types.h> 16 #include <sys/errno.h> 17 #include <netinet/in.h> 18 #include <netinet/tcp.h> 19 #include <assert.h> 20 #include <netdb.h> 21 #include <string.h> 22 #include <sys/fcntl.h> 23 24 #ifdef HAVE_SENDFILE 25 #ifdef linux 26 #include <sys/sendfile.h> 27 #else 28 #ifdef __FreeBSD__ 29 #include <sys/uio.h> 30 #else 31 #if defined(__APPLE__) && defined(__MACH__) /* OS X */ 32 #include <AvailabilityMacros.h> 33 #if defined(MAC_OS_X_VERSION_10_6) 34 #include <sys/uio.h> 35 #endif 36 #endif 37 #endif 38 #endif 39 #endif /* HAVE_SENDFILE */ 40 41 #include "iperf_util.h" 42 #include "net.h" 43 #include "timer.h" 44 45 /* netdial and netannouce code comes from libtask: http://swtch.com/libtask/ 46 * Copyright: http://swtch.com/libtask/COPYRIGHT 47 */ 48 49 /* make connection to server */ 50 int 51 netdial(int domain, int proto, char *local, char *server, int port) 52 { 53 struct addrinfo hints, *local_res, *server_res; 54 int s; 55 56 if (local) { 57 memset(&hints, 0, sizeof(hints)); 58 hints.ai_family = domain; 59 hints.ai_socktype = proto; 60 if (getaddrinfo(local, NULL, &hints, &local_res) != 0) 61 return -1; 62 } 63 64 memset(&hints, 0, sizeof(hints)); 65 hints.ai_family = domain; 66 hints.ai_socktype = proto; 67 if (getaddrinfo(server, NULL, &hints, &server_res) != 0) 68 return -1; 69 70 s = socket(server_res->ai_family, proto, 0); 71 if (s < 0) { 72 if (local) 73 freeaddrinfo(local_res); 74 freeaddrinfo(server_res); 75 return -1; 76 } 77 78 if (local) { 79 if (bind(s, (struct sockaddr *) local_res->ai_addr, local_res->ai_addrlen) < 0) { 80 close(s); 81 freeaddrinfo(local_res); 82 freeaddrinfo(server_res); 83 return -1; 84 } 85 freeaddrinfo(local_res); 86 } 87 88 ((struct sockaddr_in *) server_res->ai_addr)->sin_port = htons(port); 89 if (connect(s, (struct sockaddr *) server_res->ai_addr, server_res->ai_addrlen) < 0 && errno != EINPROGRESS) { 90 close(s); 91 freeaddrinfo(server_res); 92 return -1; 93 } 94 95 freeaddrinfo(server_res); 96 return s; 97 } 98 99 /***************************************************************/ 100 101 int 102 netannounce(int domain, int proto, char *local, int port) 103 { 104 struct addrinfo hints, *res; 105 char portstr[6]; 106 int s, opt; 107 108 snprintf(portstr, 6, "%d", port); 109 memset(&hints, 0, sizeof(hints)); 110 hints.ai_family = (domain == AF_UNSPEC ? AF_INET6 : domain); 111 hints.ai_socktype = proto; 112 hints.ai_flags = AI_PASSIVE; 113 if (getaddrinfo(local, portstr, &hints, &res) != 0) 114 return -1; 115 116 s = socket(res->ai_family, proto, 0); 117 if (s < 0) { 118 freeaddrinfo(res); 119 return -1; 120 } 121 122 opt = 1; 123 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, 124 (char *) &opt, sizeof(opt)) < 0) { 125 close(s); 126 freeaddrinfo(res); 127 return -1; 128 } 129 if (domain == AF_UNSPEC || domain == AF_INET6) { 130 if (domain == AF_UNSPEC) 131 opt = 0; 132 else if (domain == AF_INET6) 133 opt = 1; 134 if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, 135 (char *) &opt, sizeof(opt)) < 0) { 136 close(s); 137 freeaddrinfo(res); 138 return -1; 139 } 140 } 141 142 if (bind(s, (struct sockaddr *) res->ai_addr, res->ai_addrlen) < 0) { 143 close(s); 144 freeaddrinfo(res); 145 return -1; 146 } 147 148 freeaddrinfo(res); 149 150 if (proto == SOCK_STREAM) { 151 if (listen(s, 5) < 0) { 152 close(s); 153 return -1; 154 } 155 } 156 157 return s; 158 } 159 160 161 /*******************************************************************/ 162 /* reads 'count' bytes from a socket */ 163 /********************************************************************/ 164 165 int 166 Nread(int fd, char *buf, size_t count, int prot) 167 { 168 register ssize_t r; 169 register size_t nleft = count; 170 171 while (nleft > 0) { 172 r = read(fd, buf, nleft); 173 if (r < 0) { 174 if (errno == EINTR || errno == EAGAIN) 175 break; 176 else 177 return NET_HARDERROR; 178 } else if (r == 0) 179 break; 180 181 nleft -= r; 182 buf += r; 183 } 184 return count - nleft; 185 } 186 187 188 /* 189 * N W R I T E 190 */ 191 192 int 193 Nwrite(int fd, const char *buf, size_t count, int prot) 194 { 195 register ssize_t r; 196 register size_t nleft = count; 197 198 while (nleft > 0) { 199 r = write(fd, buf, nleft); 200 if (r < 0) { 201 switch (errno) { 202 case EINTR: 203 case EAGAIN: 204 return count - nleft; 205 206 case ENOBUFS: 207 return NET_SOFTERROR; 208 209 default: 210 return NET_HARDERROR; 211 } 212 } else if (r == 0) 213 return NET_SOFTERROR; 214 nleft -= r; 215 buf += r; 216 } 217 return count; 218 } 219 220 221 int 222 has_sendfile(void) 223 { 224 #if defined(HAS_SENDFILE) 225 return 1; 226 #else /* HAS_SENDFILE */ 227 return 0; 228 #endif /* HAS_SENDFILE */ 229 230 } 231 232 233 /* 234 * N S E N D F I L E 235 */ 236 237 int 238 Nsendfile(int fromfd, int tofd, const char *buf, size_t count) 239 { 240 off_t offset; 241 #if defined(HAVE_SENDFILE) 242 #if defined(__FreeBSD__) || (defined(__APPLE__) && defined(__MACH__) && defined(MAC_OS_X_VERSION_10_6)) 243 off_t sent; 244 #endif 245 register size_t nleft; 246 register ssize_t r; 247 248 nleft = count; 249 while (nleft > 0) { 250 offset = count - nleft; 251 #ifdef linux 252 r = sendfile(tofd, fromfd, &offset, nleft); 253 #else 254 #ifdef __FreeBSD__ 255 r = sendfile(fromfd, tofd, offset, nleft, NULL, &sent, 0); 256 if (r == 0) 257 r = sent; 258 #else 259 #if defined(__APPLE__) && defined(__MACH__) && defined(MAC_OS_X_VERSION_10_6) /* OS X */ 260 sent = nleft; 261 r = sendfile(fromfd, tofd, offset, &sent, NULL, 0); 262 if (r == 0) 263 r = sent; 264 #else 265 /* Shouldn't happen. */ 266 r = -1; 267 errno = ENOSYS; 268 #endif 269 #endif 270 #endif 271 if (r < 0) { 272 switch (errno) { 273 case EINTR: 274 case EAGAIN: 275 return count - nleft; 276 277 case ENOBUFS: 278 case ENOMEM: 279 return NET_SOFTERROR; 280 281 default: 282 return NET_HARDERROR; 283 } 284 } else if (r == 0) 285 return NET_SOFTERROR; 286 nleft -= r; 287 } 288 return count; 289 #else /* HAVE_SENDFILE */ 290 errno = ENOSYS; /* error if somehow get called without HAVE_SENDFILE */ 291 return -1; 292 #endif /* HAVE_SENDFILE */ 293 } 294 295 /*************************************************************************/ 296 297 /** 298 * getsock_tcp_mss - Returns the MSS size for TCP 299 * 300 */ 301 302 int 303 getsock_tcp_mss(int inSock) 304 { 305 int mss = 0; 306 307 int rc; 308 socklen_t len; 309 310 assert(inSock >= 0); /* print error and exit if this is not true */ 311 312 /* query for mss */ 313 len = sizeof(mss); 314 rc = getsockopt(inSock, IPPROTO_TCP, TCP_MAXSEG, (char *)&mss, &len); 315 if (rc == -1) { 316 perror("getsockopt TCP_MAXSEG"); 317 return -1; 318 } 319 320 return mss; 321 } 322 323 324 325 /*************************************************************/ 326 327 /* sets TCP_NODELAY and TCP_MAXSEG if requested */ 328 // XXX: This function is not being used. 329 330 int 331 set_tcp_options(int sock, int no_delay, int mss) 332 { 333 socklen_t len; 334 int rc; 335 int new_mss; 336 337 if (no_delay == 1) { 338 len = sizeof(no_delay); 339 rc = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&no_delay, len); 340 if (rc == -1) { 341 perror("setsockopt TCP_NODELAY"); 342 return -1; 343 } 344 } 345 #ifdef TCP_MAXSEG 346 if (mss > 0) { 347 len = sizeof(new_mss); 348 assert(sock != -1); 349 350 /* set */ 351 new_mss = mss; 352 len = sizeof(new_mss); 353 rc = setsockopt(sock, IPPROTO_TCP, TCP_MAXSEG, (char *)&new_mss, len); 354 if (rc == -1) { 355 perror("setsockopt TCP_MAXSEG"); 356 return -1; 357 } 358 /* verify results */ 359 rc = getsockopt(sock, IPPROTO_TCP, TCP_MAXSEG, (char *)&new_mss, &len); 360 if (rc == -1) { 361 perror("getsockopt TCP_MAXSEG"); 362 return -1; 363 } 364 if (new_mss != mss) { 365 perror("setsockopt value mismatch"); 366 return -1; 367 } 368 } 369 #endif 370 return 0; 371 } 372 373 /****************************************************************************/ 374 375 int 376 setnonblocking(int fd, int nonblocking) 377 { 378 int flags, newflags; 379 380 flags = fcntl(fd, F_GETFL, 0); 381 if (flags < 0) { 382 perror("fcntl(F_GETFL)"); 383 return -1; 384 } 385 if (nonblocking) 386 newflags = flags | (int) O_NONBLOCK; 387 else 388 newflags = flags & ~((int) O_NONBLOCK); 389 if (newflags != flags) 390 if (fcntl(fd, F_SETFL, newflags) < 0) { 391 perror("fcntl(F_SETFL)"); 392 return -1; 393 } 394 return 0; 395 } 396 397 /****************************************************************************/ 398 399 int 400 getsockdomain(int sock) 401 { 402 struct sockaddr sa; 403 socklen_t len = sizeof(sa); 404 405 if (getsockname(sock, &sa, &len) < 0) 406 return -1; 407 return sa.sa_family; 408 } 409