1 /* anet.c -- Basic TCP socket stuff made a bit less boring 2 * 3 * Copyright (c) 2006-2012, Salvatore Sanfilippo <antirez at gmail dot com> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * * Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * * Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * * Neither the name of Redis nor the names of its contributors may be used 15 * to endorse or promote products derived from this software without 16 * specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "fmacros.h" 32 33 #include <sys/types.h> 34 #include <sys/socket.h> 35 #include <sys/stat.h> 36 #include <sys/un.h> 37 #include <netinet/in.h> 38 #include <netinet/tcp.h> 39 #include <arpa/inet.h> 40 #include <unistd.h> 41 #include <fcntl.h> 42 #include <string.h> 43 #include <netdb.h> 44 #include <errno.h> 45 #include <stdarg.h> 46 #include <stdio.h> 47 48 #include "anet.h" 49 50 static void anetSetError(char *err, const char *fmt, ...) 51 { 52 va_list ap; 53 54 if (!err) return; 55 va_start(ap, fmt); 56 vsnprintf(err, ANET_ERR_LEN, fmt, ap); 57 va_end(ap); 58 } 59 60 int anetNonBlock(char *err, int fd) 61 { 62 int flags; 63 64 /* Set the socket non-blocking. 65 * Note that fcntl(2) for F_GETFL and F_SETFL can't be 66 * interrupted by a signal. */ 67 if ((flags = fcntl(fd, F_GETFL)) == -1) { 68 anetSetError(err, "fcntl(F_GETFL): %s", strerror(errno)); 69 return ANET_ERR; 70 } 71 if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) { 72 anetSetError(err, "fcntl(F_SETFL,O_NONBLOCK): %s", strerror(errno)); 73 return ANET_ERR; 74 } 75 return ANET_OK; 76 } 77 78 /* Set TCP keep alive option to detect dead peers. The interval option 79 * is only used for Linux as we are using Linux-specific APIs to set 80 * the probe send time, interval, and count. */ 81 int anetKeepAlive(char *err, int fd, int interval) 82 { 83 int val = 1; 84 85 if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) == -1) 86 { 87 anetSetError(err, "setsockopt SO_KEEPALIVE: %s", strerror(errno)); 88 return ANET_ERR; 89 } 90 91 #ifdef __linux__ 92 /* Default settings are more or less garbage, with the keepalive time 93 * set to 7200 by default on Linux. Modify settings to make the feature 94 * actually useful. */ 95 96 /* Send first probe after interval. */ 97 val = interval; 98 if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &val, sizeof(val)) < 0) { 99 anetSetError(err, "setsockopt TCP_KEEPIDLE: %s\n", strerror(errno)); 100 return ANET_ERR; 101 } 102 103 /* Send next probes after the specified interval. Note that we set the 104 * delay as interval / 3, as we send three probes before detecting 105 * an error (see the next setsockopt call). */ 106 val = interval/3; 107 if (val == 0) val = 1; 108 if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &val, sizeof(val)) < 0) { 109 anetSetError(err, "setsockopt TCP_KEEPINTVL: %s\n", strerror(errno)); 110 return ANET_ERR; 111 } 112 113 /* Consider the socket in error state after three we send three ACK 114 * probes without getting a reply. */ 115 val = 3; 116 if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &val, sizeof(val)) < 0) { 117 anetSetError(err, "setsockopt TCP_KEEPCNT: %s\n", strerror(errno)); 118 return ANET_ERR; 119 } 120 #else 121 ((void) interval); /* Avoid unused var warning for non Linux systems. */ 122 #endif 123 124 return ANET_OK; 125 } 126 127 static int anetSetTcpNoDelay(char *err, int fd, int val) 128 { 129 if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)) == -1) 130 { 131 anetSetError(err, "setsockopt TCP_NODELAY: %s", strerror(errno)); 132 return ANET_ERR; 133 } 134 return ANET_OK; 135 } 136 137 int anetEnableTcpNoDelay(char *err, int fd) 138 { 139 return anetSetTcpNoDelay(err, fd, 1); 140 } 141 142 int anetDisableTcpNoDelay(char *err, int fd) 143 { 144 return anetSetTcpNoDelay(err, fd, 0); 145 } 146 147 148 int anetSetSendBuffer(char *err, int fd, int buffsize) 149 { 150 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buffsize, sizeof(buffsize)) == -1) 151 { 152 anetSetError(err, "setsockopt SO_SNDBUF: %s", strerror(errno)); 153 return ANET_ERR; 154 } 155 return ANET_OK; 156 } 157 158 int anetTcpKeepAlive(char *err, int fd) 159 { 160 int yes = 1; 161 if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &yes, sizeof(yes)) == -1) { 162 anetSetError(err, "setsockopt SO_KEEPALIVE: %s", strerror(errno)); 163 return ANET_ERR; 164 } 165 return ANET_OK; 166 } 167 168 /* anetGenericResolve() is called by anetResolve() and anetResolveIP() to 169 * do the actual work. It resolves the hostname "host" and set the string 170 * representation of the IP address into the buffer pointed by "ipbuf". 171 * 172 * If flags is set to ANET_IP_ONLY the function only resolves hostnames 173 * that are actually already IPv4 or IPv6 addresses. This turns the function 174 * into a validating / normalizing function. */ 175 int anetGenericResolve(char *err, char *host, char *ipbuf, size_t ipbuf_len, 176 int flags) 177 { 178 struct addrinfo hints, *info; 179 int rv; 180 181 memset(&hints,0,sizeof(hints)); 182 if (flags & ANET_IP_ONLY) hints.ai_flags = AI_NUMERICHOST; 183 hints.ai_family = AF_UNSPEC; 184 hints.ai_socktype = SOCK_STREAM; /* specify socktype to avoid dups */ 185 186 if ((rv = getaddrinfo(host, NULL, &hints, &info)) != 0) { 187 anetSetError(err, "%s", gai_strerror(rv)); 188 return ANET_ERR; 189 } 190 if (info->ai_family == AF_INET) { 191 struct sockaddr_in *sa = (struct sockaddr_in *)info->ai_addr; 192 inet_ntop(AF_INET, &(sa->sin_addr), ipbuf, ipbuf_len); 193 } else { 194 struct sockaddr_in6 *sa = (struct sockaddr_in6 *)info->ai_addr; 195 inet_ntop(AF_INET6, &(sa->sin6_addr), ipbuf, ipbuf_len); 196 } 197 198 freeaddrinfo(info); 199 return ANET_OK; 200 } 201 202 int anetResolve(char *err, char *host, char *ipbuf, size_t ipbuf_len) { 203 return anetGenericResolve(err,host,ipbuf,ipbuf_len,ANET_NONE); 204 } 205 206 int anetResolveIP(char *err, char *host, char *ipbuf, size_t ipbuf_len) { 207 return anetGenericResolve(err,host,ipbuf,ipbuf_len,ANET_IP_ONLY); 208 } 209 210 static int anetSetReuseAddr(char *err, int fd) { 211 int yes = 1; 212 /* Make sure connection-intensive things like the redis benckmark 213 * will be able to close/open sockets a zillion of times */ 214 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1) { 215 anetSetError(err, "setsockopt SO_REUSEADDR: %s", strerror(errno)); 216 return ANET_ERR; 217 } 218 return ANET_OK; 219 } 220 221 static int anetCreateSocket(char *err, int domain) { 222 int s; 223 if ((s = socket(domain, SOCK_STREAM, 0)) == -1) { 224 anetSetError(err, "creating socket: %s", strerror(errno)); 225 return ANET_ERR; 226 } 227 228 /* Make sure connection-intensive things like the redis benchmark 229 * will be able to close/open sockets a zillion of times */ 230 if (anetSetReuseAddr(err,s) == ANET_ERR) { 231 close(s); 232 return ANET_ERR; 233 } 234 return s; 235 } 236 237 #define ANET_CONNECT_NONE 0 238 #define ANET_CONNECT_NONBLOCK 1 239 static int anetTcpGenericConnect(char *err, char *addr, int port, 240 char *source_addr, int flags) 241 { 242 int s = ANET_ERR, rv; 243 char portstr[6]; /* strlen("65535") + 1; */ 244 struct addrinfo hints, *servinfo, *bservinfo, *p, *b; 245 246 snprintf(portstr,sizeof(portstr),"%d",port); 247 memset(&hints,0,sizeof(hints)); 248 hints.ai_family = AF_UNSPEC; 249 hints.ai_socktype = SOCK_STREAM; 250 251 if ((rv = getaddrinfo(addr,portstr,&hints,&servinfo)) != 0) { 252 anetSetError(err, "%s", gai_strerror(rv)); 253 return ANET_ERR; 254 } 255 for (p = servinfo; p != NULL; p = p->ai_next) { 256 /* Try to create the socket and to connect it. 257 * If we fail in the socket() call, or on connect(), we retry with 258 * the next entry in servinfo. */ 259 if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == -1) 260 continue; 261 if (anetSetReuseAddr(err,s) == ANET_ERR) goto error; 262 if (flags & ANET_CONNECT_NONBLOCK && anetNonBlock(err,s) != ANET_OK) 263 goto error; 264 if (source_addr) { 265 int bound = 0; 266 /* Using getaddrinfo saves us from self-determining IPv4 vs IPv6 */ 267 if ((rv = getaddrinfo(source_addr, NULL, &hints, &bservinfo)) != 0) 268 { 269 anetSetError(err, "%s", gai_strerror(rv)); 270 goto end; 271 } 272 for (b = bservinfo; b != NULL; b = b->ai_next) { 273 if (bind(s,b->ai_addr,b->ai_addrlen) != -1) { 274 bound = 1; 275 break; 276 } 277 } 278 freeaddrinfo(bservinfo); 279 if (!bound) { 280 anetSetError(err, "bind: %s", strerror(errno)); 281 goto end; 282 } 283 } 284 if (connect(s,p->ai_addr,p->ai_addrlen) == -1) { 285 /* If the socket is non-blocking, it is ok for connect() to 286 * return an EINPROGRESS error here. */ 287 if (errno == EINPROGRESS && flags & ANET_CONNECT_NONBLOCK) 288 goto end; 289 close(s); 290 s = ANET_ERR; 291 continue; 292 } 293 294 /* If we ended an iteration of the for loop without errors, we 295 * have a connected socket. Let's return to the caller. */ 296 goto end; 297 } 298 if (p == NULL) 299 anetSetError(err, "creating socket: %s", strerror(errno)); 300 301 error: 302 if (s != ANET_ERR) { 303 close(s); 304 s = ANET_ERR; 305 } 306 end: 307 freeaddrinfo(servinfo); 308 return s; 309 } 310 311 int anetTcpConnect(char *err, char *addr, int port) 312 { 313 return anetTcpGenericConnect(err,addr,port,NULL,ANET_CONNECT_NONE); 314 } 315 316 int anetTcpNonBlockConnect(char *err, char *addr, int port) 317 { 318 return anetTcpGenericConnect(err,addr,port,NULL,ANET_CONNECT_NONBLOCK); 319 } 320 321 int anetTcpNonBlockBindConnect(char *err, char *addr, int port, char *source_addr) 322 { 323 return anetTcpGenericConnect(err,addr,port,source_addr,ANET_CONNECT_NONBLOCK); 324 } 325 326 int anetUnixGenericConnect(char *err, char *path, int flags) 327 { 328 int s; 329 struct sockaddr_un sa; 330 331 if ((s = anetCreateSocket(err,AF_LOCAL)) == ANET_ERR) 332 return ANET_ERR; 333 334 sa.sun_family = AF_LOCAL; 335 strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1); 336 if (flags & ANET_CONNECT_NONBLOCK) { 337 if (anetNonBlock(err,s) != ANET_OK) 338 return ANET_ERR; 339 } 340 if (connect(s,(struct sockaddr*)&sa,sizeof(sa)) == -1) { 341 if (errno == EINPROGRESS && 342 flags & ANET_CONNECT_NONBLOCK) 343 return s; 344 345 anetSetError(err, "connect: %s", strerror(errno)); 346 close(s); 347 return ANET_ERR; 348 } 349 return s; 350 } 351 352 int anetUnixConnect(char *err, char *path) 353 { 354 return anetUnixGenericConnect(err,path,ANET_CONNECT_NONE); 355 } 356 357 int anetUnixNonBlockConnect(char *err, char *path) 358 { 359 return anetUnixGenericConnect(err,path,ANET_CONNECT_NONBLOCK); 360 } 361 362 /* Like read(2) but make sure 'count' is read before to return 363 * (unless error or EOF condition is encountered) */ 364 int anetRead(int fd, char *buf, int count) 365 { 366 int nread, totlen = 0; 367 while(totlen != count) { 368 nread = read(fd,buf,count-totlen); 369 if (nread == 0) return totlen; 370 if (nread == -1) return -1; 371 totlen += nread; 372 buf += nread; 373 } 374 return totlen; 375 } 376 377 /* Like write(2) but make sure 'count' is read before to return 378 * (unless error is encountered) */ 379 int anetWrite(int fd, char *buf, int count) 380 { 381 int nwritten, totlen = 0; 382 while(totlen != count) { 383 nwritten = write(fd,buf,count-totlen); 384 if (nwritten == 0) return totlen; 385 if (nwritten == -1) return -1; 386 totlen += nwritten; 387 buf += nwritten; 388 } 389 return totlen; 390 } 391 392 static int anetListen(char *err, int s, struct sockaddr *sa, socklen_t len, int backlog) { 393 if (bind(s,sa,len) == -1) { 394 anetSetError(err, "bind: %s", strerror(errno)); 395 close(s); 396 return ANET_ERR; 397 } 398 399 if (listen(s, backlog) == -1) { 400 anetSetError(err, "listen: %s", strerror(errno)); 401 close(s); 402 return ANET_ERR; 403 } 404 return ANET_OK; 405 } 406 407 static int anetV6Only(char *err, int s) { 408 int yes = 1; 409 if (setsockopt(s,IPPROTO_IPV6,IPV6_V6ONLY,&yes,sizeof(yes)) == -1) { 410 anetSetError(err, "setsockopt: %s", strerror(errno)); 411 close(s); 412 return ANET_ERR; 413 } 414 return ANET_OK; 415 } 416 417 static int _anetTcpServer(char *err, int port, char *bindaddr, int af, int backlog) 418 { 419 int s, rv; 420 char _port[6]; /* strlen("65535") */ 421 struct addrinfo hints, *servinfo, *p; 422 423 snprintf(_port,6,"%d",port); 424 memset(&hints,0,sizeof(hints)); 425 hints.ai_family = af; 426 hints.ai_socktype = SOCK_STREAM; 427 hints.ai_flags = AI_PASSIVE; /* No effect if bindaddr != NULL */ 428 429 if ((rv = getaddrinfo(bindaddr,_port,&hints,&servinfo)) != 0) { 430 anetSetError(err, "%s", gai_strerror(rv)); 431 return ANET_ERR; 432 } 433 for (p = servinfo; p != NULL; p = p->ai_next) { 434 if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == -1) 435 continue; 436 437 if (af == AF_INET6 && anetV6Only(err,s) == ANET_ERR) goto error; 438 if (anetSetReuseAddr(err,s) == ANET_ERR) goto error; 439 if (anetListen(err,s,p->ai_addr,p->ai_addrlen,backlog) == ANET_ERR) goto error; 440 goto end; 441 } 442 if (p == NULL) { 443 anetSetError(err, "unable to bind socket"); 444 goto error; 445 } 446 447 error: 448 s = ANET_ERR; 449 end: 450 freeaddrinfo(servinfo); 451 return s; 452 } 453 454 int anetTcpServer(char *err, int port, char *bindaddr, int backlog) 455 { 456 return _anetTcpServer(err, port, bindaddr, AF_INET, backlog); 457 } 458 459 int anetTcp6Server(char *err, int port, char *bindaddr, int backlog) 460 { 461 return _anetTcpServer(err, port, bindaddr, AF_INET6, backlog); 462 } 463 464 int anetUnixServer(char *err, char *path, mode_t perm, int backlog) 465 { 466 int s; 467 struct sockaddr_un sa; 468 469 if ((s = anetCreateSocket(err,AF_LOCAL)) == ANET_ERR) 470 return ANET_ERR; 471 472 memset(&sa,0,sizeof(sa)); 473 sa.sun_family = AF_LOCAL; 474 strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1); 475 if (anetListen(err,s,(struct sockaddr*)&sa,sizeof(sa),backlog) == ANET_ERR) 476 return ANET_ERR; 477 if (perm) 478 chmod(sa.sun_path, perm); 479 return s; 480 } 481 482 static int anetGenericAccept(char *err, int s, struct sockaddr *sa, socklen_t *len) { 483 int fd; 484 while(1) { 485 fd = accept(s,sa,len); 486 if (fd == -1) { 487 if (errno == EINTR) 488 continue; 489 else { 490 anetSetError(err, "accept: %s", strerror(errno)); 491 return ANET_ERR; 492 } 493 } 494 break; 495 } 496 return fd; 497 } 498 499 int anetTcpAccept(char *err, int s, char *ip, size_t ip_len, int *port) { 500 int fd; 501 struct sockaddr_storage sa; 502 socklen_t salen = sizeof(sa); 503 if ((fd = anetGenericAccept(err,s,(struct sockaddr*)&sa,&salen)) == -1) 504 return ANET_ERR; 505 506 if (sa.ss_family == AF_INET) { 507 struct sockaddr_in *s = (struct sockaddr_in *)&sa; 508 if (ip) inet_ntop(AF_INET,(void*)&(s->sin_addr),ip,ip_len); 509 if (port) *port = ntohs(s->sin_port); 510 } else { 511 struct sockaddr_in6 *s = (struct sockaddr_in6 *)&sa; 512 if (ip) inet_ntop(AF_INET6,(void*)&(s->sin6_addr),ip,ip_len); 513 if (port) *port = ntohs(s->sin6_port); 514 } 515 return fd; 516 } 517 518 int anetUnixAccept(char *err, int s) { 519 int fd; 520 struct sockaddr_un sa; 521 socklen_t salen = sizeof(sa); 522 if ((fd = anetGenericAccept(err,s,(struct sockaddr*)&sa,&salen)) == -1) 523 return ANET_ERR; 524 525 return fd; 526 } 527 528 int anetPeerToString(int fd, char *ip, size_t ip_len, int *port) { 529 struct sockaddr_storage sa; 530 socklen_t salen = sizeof(sa); 531 532 if (getpeername(fd,(struct sockaddr*)&sa,&salen) == -1) goto error; 533 if (ip_len == 0) goto error; 534 535 if (sa.ss_family == AF_INET) { 536 struct sockaddr_in *s = (struct sockaddr_in *)&sa; 537 if (ip) inet_ntop(AF_INET,(void*)&(s->sin_addr),ip,ip_len); 538 if (port) *port = ntohs(s->sin_port); 539 } else if (sa.ss_family == AF_INET6) { 540 struct sockaddr_in6 *s = (struct sockaddr_in6 *)&sa; 541 if (ip) inet_ntop(AF_INET6,(void*)&(s->sin6_addr),ip,ip_len); 542 if (port) *port = ntohs(s->sin6_port); 543 } else if (sa.ss_family == AF_UNIX) { 544 if (ip) strncpy(ip,"/unixsocket",ip_len); 545 if (port) *port = 0; 546 } else { 547 goto error; 548 } 549 return 0; 550 551 error: 552 if (ip) { 553 if (ip_len >= 2) { 554 ip[0] = '?'; 555 ip[1] = '\0'; 556 } else if (ip_len == 1) { 557 ip[0] = '\0'; 558 } 559 } 560 if (port) *port = 0; 561 return -1; 562 } 563 564 int anetSockName(int fd, char *ip, size_t ip_len, int *port) { 565 struct sockaddr_storage sa; 566 socklen_t salen = sizeof(sa); 567 568 if (getsockname(fd,(struct sockaddr*)&sa,&salen) == -1) { 569 if (port) *port = 0; 570 ip[0] = '?'; 571 ip[1] = '\0'; 572 return -1; 573 } 574 if (sa.ss_family == AF_INET) { 575 struct sockaddr_in *s = (struct sockaddr_in *)&sa; 576 if (ip) inet_ntop(AF_INET,(void*)&(s->sin_addr),ip,ip_len); 577 if (port) *port = ntohs(s->sin_port); 578 } else { 579 struct sockaddr_in6 *s = (struct sockaddr_in6 *)&sa; 580 if (ip) inet_ntop(AF_INET6,(void*)&(s->sin6_addr),ip,ip_len); 581 if (port) *port = ntohs(s->sin6_port); 582 } 583 return 0; 584 } 585