1275970Scy/* 2275970Scy * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson 3275970Scy * 4275970Scy * Redistribution and use in source and binary forms, with or without 5275970Scy * modification, are permitted provided that the following conditions 6275970Scy * are met: 7275970Scy * 1. Redistributions of source code must retain the above copyright 8275970Scy * notice, this list of conditions and the following disclaimer. 9275970Scy * 2. Redistributions in binary form must reproduce the above copyright 10275970Scy * notice, this list of conditions and the following disclaimer in the 11275970Scy * documentation and/or other materials provided with the distribution. 12275970Scy * 3. The name of the author may not be used to endorse or promote products 13275970Scy * derived from this software without specific prior written permission. 14275970Scy * 15275970Scy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16275970Scy * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17275970Scy * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18275970Scy * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19275970Scy * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20275970Scy * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21275970Scy * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22275970Scy * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23275970Scy * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24275970Scy * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25275970Scy */ 26275970Scy 27275970Scy#include "event2/event-config.h" 28275970Scy#include "evconfig-private.h" 29275970Scy 30275970Scy#ifdef _WIN32 31275970Scy#include <winsock2.h> 32275970Scy#include <ws2tcpip.h> 33275970Scy#define WIN32_LEAN_AND_MEAN 34275970Scy#include <windows.h> 35275970Scy#undef WIN32_LEAN_AND_MEAN 36275970Scy#include <io.h> 37275970Scy#include <tchar.h> 38275970Scy#include <process.h> 39275970Scy#undef _WIN32_WINNT 40275970Scy/* For structs needed by GetAdaptersAddresses */ 41275970Scy#define _WIN32_WINNT 0x0501 42275970Scy#include <iphlpapi.h> 43275970Scy#endif 44275970Scy 45275970Scy#include <sys/types.h> 46275970Scy#ifdef EVENT__HAVE_SYS_SOCKET_H 47275970Scy#include <sys/socket.h> 48275970Scy#endif 49275970Scy#ifdef EVENT__HAVE_UNISTD_H 50275970Scy#include <unistd.h> 51275970Scy#endif 52275970Scy#ifdef EVENT__HAVE_FCNTL_H 53275970Scy#include <fcntl.h> 54275970Scy#endif 55275970Scy#ifdef EVENT__HAVE_STDLIB_H 56275970Scy#include <stdlib.h> 57275970Scy#endif 58275970Scy#include <errno.h> 59275970Scy#include <limits.h> 60275970Scy#include <stdio.h> 61275970Scy#include <string.h> 62275970Scy#ifdef EVENT__HAVE_NETINET_IN_H 63275970Scy#include <netinet/in.h> 64275970Scy#endif 65275970Scy#ifdef EVENT__HAVE_NETINET_IN6_H 66275970Scy#include <netinet/in6.h> 67275970Scy#endif 68275970Scy#ifdef EVENT__HAVE_NETINET_TCP_H 69275970Scy#include <netinet/tcp.h> 70275970Scy#endif 71275970Scy#ifdef EVENT__HAVE_ARPA_INET_H 72275970Scy#include <arpa/inet.h> 73275970Scy#endif 74275970Scy#include <time.h> 75275970Scy#include <sys/stat.h> 76275970Scy#ifdef EVENT__HAVE_IFADDRS_H 77275970Scy#include <ifaddrs.h> 78275970Scy#endif 79275970Scy 80275970Scy#include "event2/util.h" 81275970Scy#include "util-internal.h" 82275970Scy#include "log-internal.h" 83275970Scy#include "mm-internal.h" 84275970Scy#include "evthread-internal.h" 85275970Scy 86275970Scy#include "strlcpy-internal.h" 87275970Scy#include "ipv6-internal.h" 88275970Scy 89275970Scy#ifdef _WIN32 90275970Scy#define HT_NO_CACHE_HASH_VALUES 91275970Scy#include "ht-internal.h" 92275970Scy#define open _open 93275970Scy#define read _read 94275970Scy#define close _close 95275970Scy#ifndef fstat 96275970Scy#define fstat _fstati64 97275970Scy#endif 98275970Scy#ifndef stat 99275970Scy#define stat _stati64 100275970Scy#endif 101275970Scy#define mode_t int 102275970Scy#endif 103275970Scy 104275970Scyint 105275970Scyevutil_open_closeonexec_(const char *pathname, int flags, unsigned mode) 106275970Scy{ 107275970Scy int fd; 108275970Scy 109275970Scy#ifdef O_CLOEXEC 110275970Scy fd = open(pathname, flags|O_CLOEXEC, (mode_t)mode); 111275970Scy if (fd >= 0 || errno == EINVAL) 112275970Scy return fd; 113275970Scy /* If we got an EINVAL, fall through and try without O_CLOEXEC */ 114275970Scy#endif 115275970Scy fd = open(pathname, flags, (mode_t)mode); 116275970Scy if (fd < 0) 117275970Scy return -1; 118275970Scy 119275970Scy#if defined(FD_CLOEXEC) 120275970Scy if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) { 121275970Scy close(fd); 122275970Scy return -1; 123275970Scy } 124275970Scy#endif 125275970Scy 126275970Scy return fd; 127275970Scy} 128275970Scy 129275970Scy/** 130275970Scy Read the contents of 'filename' into a newly allocated NUL-terminated 131275970Scy string. Set *content_out to hold this string, and *len_out to hold its 132275970Scy length (not including the appended NUL). If 'is_binary', open the file in 133275970Scy binary mode. 134275970Scy 135275970Scy Returns 0 on success, -1 if the open fails, and -2 for all other failures. 136275970Scy 137275970Scy Used internally only; may go away in a future version. 138275970Scy */ 139275970Scyint 140275970Scyevutil_read_file_(const char *filename, char **content_out, size_t *len_out, 141275970Scy int is_binary) 142275970Scy{ 143275970Scy int fd, r; 144275970Scy struct stat st; 145275970Scy char *mem; 146275970Scy size_t read_so_far=0; 147275970Scy int mode = O_RDONLY; 148275970Scy 149275970Scy EVUTIL_ASSERT(content_out); 150275970Scy EVUTIL_ASSERT(len_out); 151275970Scy *content_out = NULL; 152275970Scy *len_out = 0; 153275970Scy 154275970Scy#ifdef O_BINARY 155275970Scy if (is_binary) 156275970Scy mode |= O_BINARY; 157275970Scy#endif 158275970Scy 159275970Scy fd = evutil_open_closeonexec_(filename, mode, 0); 160275970Scy if (fd < 0) 161275970Scy return -1; 162275970Scy if (fstat(fd, &st) || st.st_size < 0 || 163275970Scy st.st_size > EV_SSIZE_MAX-1 ) { 164275970Scy close(fd); 165275970Scy return -2; 166275970Scy } 167275970Scy mem = mm_malloc((size_t)st.st_size + 1); 168275970Scy if (!mem) { 169275970Scy close(fd); 170275970Scy return -2; 171275970Scy } 172275970Scy read_so_far = 0; 173275970Scy#ifdef _WIN32 174275970Scy#define N_TO_READ(x) ((x) > INT_MAX) ? INT_MAX : ((int)(x)) 175275970Scy#else 176275970Scy#define N_TO_READ(x) (x) 177275970Scy#endif 178275970Scy while ((r = read(fd, mem+read_so_far, N_TO_READ(st.st_size - read_so_far))) > 0) { 179275970Scy read_so_far += r; 180275970Scy if (read_so_far >= (size_t)st.st_size) 181275970Scy break; 182275970Scy EVUTIL_ASSERT(read_so_far < (size_t)st.st_size); 183275970Scy } 184275970Scy close(fd); 185275970Scy if (r < 0) { 186275970Scy mm_free(mem); 187275970Scy return -2; 188275970Scy } 189275970Scy mem[read_so_far] = 0; 190275970Scy 191275970Scy *len_out = read_so_far; 192275970Scy *content_out = mem; 193275970Scy return 0; 194275970Scy} 195275970Scy 196275970Scyint 197275970Scyevutil_socketpair(int family, int type, int protocol, evutil_socket_t fd[2]) 198275970Scy{ 199275970Scy#ifndef _WIN32 200275970Scy return socketpair(family, type, protocol, fd); 201275970Scy#else 202275970Scy return evutil_ersatz_socketpair_(family, type, protocol, fd); 203275970Scy#endif 204275970Scy} 205275970Scy 206275970Scyint 207275970Scyevutil_ersatz_socketpair_(int family, int type, int protocol, 208275970Scy evutil_socket_t fd[2]) 209275970Scy{ 210275970Scy /* This code is originally from Tor. Used with permission. */ 211275970Scy 212275970Scy /* This socketpair does not work when localhost is down. So 213275970Scy * it's really not the same thing at all. But it's close enough 214275970Scy * for now, and really, when localhost is down sometimes, we 215275970Scy * have other problems too. 216275970Scy */ 217275970Scy#ifdef _WIN32 218275970Scy#define ERR(e) WSA##e 219275970Scy#else 220275970Scy#define ERR(e) e 221275970Scy#endif 222275970Scy evutil_socket_t listener = -1; 223275970Scy evutil_socket_t connector = -1; 224275970Scy evutil_socket_t acceptor = -1; 225275970Scy struct sockaddr_in listen_addr; 226275970Scy struct sockaddr_in connect_addr; 227275970Scy ev_socklen_t size; 228275970Scy int saved_errno = -1; 229275970Scy 230275970Scy if (protocol 231275970Scy || (family != AF_INET 232275970Scy#ifdef AF_UNIX 233275970Scy && family != AF_UNIX 234275970Scy#endif 235275970Scy )) { 236275970Scy EVUTIL_SET_SOCKET_ERROR(ERR(EAFNOSUPPORT)); 237275970Scy return -1; 238275970Scy } 239275970Scy if (!fd) { 240275970Scy EVUTIL_SET_SOCKET_ERROR(ERR(EINVAL)); 241275970Scy return -1; 242275970Scy } 243275970Scy 244275970Scy listener = socket(AF_INET, type, 0); 245275970Scy if (listener < 0) 246275970Scy return -1; 247275970Scy memset(&listen_addr, 0, sizeof(listen_addr)); 248275970Scy listen_addr.sin_family = AF_INET; 249275970Scy listen_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 250275970Scy listen_addr.sin_port = 0; /* kernel chooses port. */ 251275970Scy if (bind(listener, (struct sockaddr *) &listen_addr, sizeof (listen_addr)) 252275970Scy == -1) 253275970Scy goto tidy_up_and_fail; 254275970Scy if (listen(listener, 1) == -1) 255275970Scy goto tidy_up_and_fail; 256275970Scy 257275970Scy connector = socket(AF_INET, type, 0); 258275970Scy if (connector < 0) 259275970Scy goto tidy_up_and_fail; 260275970Scy /* We want to find out the port number to connect to. */ 261275970Scy size = sizeof(connect_addr); 262275970Scy if (getsockname(listener, (struct sockaddr *) &connect_addr, &size) == -1) 263275970Scy goto tidy_up_and_fail; 264275970Scy if (size != sizeof (connect_addr)) 265275970Scy goto abort_tidy_up_and_fail; 266275970Scy if (connect(connector, (struct sockaddr *) &connect_addr, 267275970Scy sizeof(connect_addr)) == -1) 268275970Scy goto tidy_up_and_fail; 269275970Scy 270275970Scy size = sizeof(listen_addr); 271275970Scy acceptor = accept(listener, (struct sockaddr *) &listen_addr, &size); 272275970Scy if (acceptor < 0) 273275970Scy goto tidy_up_and_fail; 274275970Scy if (size != sizeof(listen_addr)) 275275970Scy goto abort_tidy_up_and_fail; 276275970Scy /* Now check we are talking to ourself by matching port and host on the 277275970Scy two sockets. */ 278275970Scy if (getsockname(connector, (struct sockaddr *) &connect_addr, &size) == -1) 279275970Scy goto tidy_up_and_fail; 280275970Scy if (size != sizeof (connect_addr) 281275970Scy || listen_addr.sin_family != connect_addr.sin_family 282275970Scy || listen_addr.sin_addr.s_addr != connect_addr.sin_addr.s_addr 283275970Scy || listen_addr.sin_port != connect_addr.sin_port) 284275970Scy goto abort_tidy_up_and_fail; 285275970Scy evutil_closesocket(listener); 286275970Scy fd[0] = connector; 287275970Scy fd[1] = acceptor; 288275970Scy 289275970Scy return 0; 290275970Scy 291275970Scy abort_tidy_up_and_fail: 292275970Scy saved_errno = ERR(ECONNABORTED); 293275970Scy tidy_up_and_fail: 294275970Scy if (saved_errno < 0) 295275970Scy saved_errno = EVUTIL_SOCKET_ERROR(); 296275970Scy if (listener != -1) 297275970Scy evutil_closesocket(listener); 298275970Scy if (connector != -1) 299275970Scy evutil_closesocket(connector); 300275970Scy if (acceptor != -1) 301275970Scy evutil_closesocket(acceptor); 302275970Scy 303275970Scy EVUTIL_SET_SOCKET_ERROR(saved_errno); 304275970Scy return -1; 305275970Scy#undef ERR 306275970Scy} 307275970Scy 308275970Scyint 309275970Scyevutil_make_socket_nonblocking(evutil_socket_t fd) 310275970Scy{ 311275970Scy#ifdef _WIN32 312275970Scy { 313275970Scy u_long nonblocking = 1; 314275970Scy if (ioctlsocket(fd, FIONBIO, &nonblocking) == SOCKET_ERROR) { 315275970Scy event_sock_warn(fd, "fcntl(%d, F_GETFL)", (int)fd); 316275970Scy return -1; 317275970Scy } 318275970Scy } 319275970Scy#else 320275970Scy { 321275970Scy int flags; 322275970Scy if ((flags = fcntl(fd, F_GETFL, NULL)) < 0) { 323275970Scy event_warn("fcntl(%d, F_GETFL)", fd); 324275970Scy return -1; 325275970Scy } 326275970Scy if (!(flags & O_NONBLOCK)) { 327275970Scy if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) { 328275970Scy event_warn("fcntl(%d, F_SETFL)", fd); 329275970Scy return -1; 330275970Scy } 331275970Scy } 332275970Scy } 333275970Scy#endif 334275970Scy return 0; 335275970Scy} 336275970Scy 337275970Scy/* Faster version of evutil_make_socket_nonblocking for internal use. 338275970Scy * 339275970Scy * Requires that no F_SETFL flags were previously set on the fd. 340275970Scy */ 341275970Scystatic int 342275970Scyevutil_fast_socket_nonblocking(evutil_socket_t fd) 343275970Scy{ 344275970Scy#ifdef _WIN32 345275970Scy return evutil_make_socket_nonblocking(fd); 346275970Scy#else 347275970Scy if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) { 348275970Scy event_warn("fcntl(%d, F_SETFL)", fd); 349275970Scy return -1; 350275970Scy } 351275970Scy return 0; 352275970Scy#endif 353275970Scy} 354275970Scy 355275970Scyint 356275970Scyevutil_make_listen_socket_reuseable(evutil_socket_t sock) 357275970Scy{ 358275970Scy#ifndef _WIN32 359275970Scy int one = 1; 360275970Scy /* REUSEADDR on Unix means, "don't hang on to this address after the 361275970Scy * listener is closed." On Windows, though, it means "don't keep other 362275970Scy * processes from binding to this address while we're using it. */ 363275970Scy return setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*) &one, 364275970Scy (ev_socklen_t)sizeof(one)); 365275970Scy#else 366275970Scy return 0; 367275970Scy#endif 368275970Scy} 369275970Scy 370275970Scyint 371285612Sdelphijevutil_make_listen_socket_reuseable_port(evutil_socket_t sock) 372285612Sdelphij{ 373285612Sdelphij#if defined __linux__ && defined(SO_REUSEPORT) 374285612Sdelphij int one = 1; 375285612Sdelphij /* REUSEPORT on Linux 3.9+ means, "Multiple servers (processes or 376285612Sdelphij * threads) can bind to the same port if they each set the option. */ 377285612Sdelphij return setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (void*) &one, 378285612Sdelphij (ev_socklen_t)sizeof(one)); 379285612Sdelphij#else 380285612Sdelphij return 0; 381285612Sdelphij#endif 382285612Sdelphij} 383285612Sdelphij 384285612Sdelphijint 385275970Scyevutil_make_tcp_listen_socket_deferred(evutil_socket_t sock) 386275970Scy{ 387275970Scy#if defined(EVENT__HAVE_NETINET_TCP_H) && defined(TCP_DEFER_ACCEPT) 388275970Scy int one = 1; 389275970Scy 390275970Scy /* TCP_DEFER_ACCEPT tells the kernel to call defer accept() only after data 391275970Scy * has arrived and ready to read */ 392275970Scy return setsockopt(sock, IPPROTO_TCP, TCP_DEFER_ACCEPT, &one, 393275970Scy (ev_socklen_t)sizeof(one)); 394275970Scy#endif 395275970Scy return 0; 396275970Scy} 397275970Scy 398275970Scyint 399275970Scyevutil_make_socket_closeonexec(evutil_socket_t fd) 400275970Scy{ 401275970Scy#if !defined(_WIN32) && defined(EVENT__HAVE_SETFD) 402275970Scy int flags; 403275970Scy if ((flags = fcntl(fd, F_GETFD, NULL)) < 0) { 404275970Scy event_warn("fcntl(%d, F_GETFD)", fd); 405275970Scy return -1; 406275970Scy } 407275970Scy if (!(flags & FD_CLOEXEC)) { 408275970Scy if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) { 409275970Scy event_warn("fcntl(%d, F_SETFD)", fd); 410275970Scy return -1; 411275970Scy } 412275970Scy } 413275970Scy#endif 414275970Scy return 0; 415275970Scy} 416275970Scy 417275970Scy/* Faster version of evutil_make_socket_closeonexec for internal use. 418275970Scy * 419275970Scy * Requires that no F_SETFD flags were previously set on the fd. 420275970Scy */ 421275970Scystatic int 422275970Scyevutil_fast_socket_closeonexec(evutil_socket_t fd) 423275970Scy{ 424275970Scy#if !defined(_WIN32) && defined(EVENT__HAVE_SETFD) 425275970Scy if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) { 426275970Scy event_warn("fcntl(%d, F_SETFD)", fd); 427275970Scy return -1; 428275970Scy } 429275970Scy#endif 430275970Scy return 0; 431275970Scy} 432275970Scy 433275970Scyint 434275970Scyevutil_closesocket(evutil_socket_t sock) 435275970Scy{ 436275970Scy#ifndef _WIN32 437275970Scy return close(sock); 438275970Scy#else 439275970Scy return closesocket(sock); 440275970Scy#endif 441275970Scy} 442275970Scy 443275970Scyev_int64_t 444275970Scyevutil_strtoll(const char *s, char **endptr, int base) 445275970Scy{ 446275970Scy#ifdef EVENT__HAVE_STRTOLL 447275970Scy return (ev_int64_t)strtoll(s, endptr, base); 448275970Scy#elif EVENT__SIZEOF_LONG == 8 449275970Scy return (ev_int64_t)strtol(s, endptr, base); 450275970Scy#elif defined(_WIN32) && defined(_MSC_VER) && _MSC_VER < 1300 451275970Scy /* XXXX on old versions of MS APIs, we only support base 452275970Scy * 10. */ 453275970Scy ev_int64_t r; 454275970Scy if (base != 10) 455275970Scy return 0; 456275970Scy r = (ev_int64_t) _atoi64(s); 457275970Scy while (isspace(*s)) 458275970Scy ++s; 459275970Scy if (*s == '-') 460275970Scy ++s; 461275970Scy while (isdigit(*s)) 462275970Scy ++s; 463275970Scy if (endptr) 464275970Scy *endptr = (char*) s; 465275970Scy return r; 466275970Scy#elif defined(_WIN32) 467275970Scy return (ev_int64_t) _strtoi64(s, endptr, base); 468275970Scy#elif defined(EVENT__SIZEOF_LONG_LONG) && EVENT__SIZEOF_LONG_LONG == 8 469275970Scy long long r; 470275970Scy int n; 471275970Scy if (base != 10 && base != 16) 472275970Scy return 0; 473275970Scy if (base == 10) { 474275970Scy n = sscanf(s, "%lld", &r); 475275970Scy } else { 476275970Scy unsigned long long ru=0; 477275970Scy n = sscanf(s, "%llx", &ru); 478275970Scy if (ru > EV_INT64_MAX) 479275970Scy return 0; 480275970Scy r = (long long) ru; 481275970Scy } 482275970Scy if (n != 1) 483275970Scy return 0; 484275970Scy while (EVUTIL_ISSPACE_(*s)) 485275970Scy ++s; 486275970Scy if (*s == '-') 487275970Scy ++s; 488275970Scy if (base == 10) { 489275970Scy while (EVUTIL_ISDIGIT_(*s)) 490275970Scy ++s; 491275970Scy } else { 492275970Scy while (EVUTIL_ISXDIGIT_(*s)) 493275970Scy ++s; 494275970Scy } 495275970Scy if (endptr) 496275970Scy *endptr = (char*) s; 497275970Scy return r; 498275970Scy#else 499275970Scy#error "I don't know how to parse 64-bit integers." 500275970Scy#endif 501275970Scy} 502275970Scy 503275970Scy#ifdef _WIN32 504275970Scyint 505275970Scyevutil_socket_geterror(evutil_socket_t sock) 506275970Scy{ 507275970Scy int optval, optvallen=sizeof(optval); 508275970Scy int err = WSAGetLastError(); 509275970Scy if (err == WSAEWOULDBLOCK && sock >= 0) { 510275970Scy if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)&optval, 511275970Scy &optvallen)) 512275970Scy return err; 513275970Scy if (optval) 514275970Scy return optval; 515275970Scy } 516275970Scy return err; 517275970Scy} 518275970Scy#endif 519275970Scy 520275970Scy/* XXX we should use an enum here. */ 521275970Scy/* 2 for connection refused, 1 for connected, 0 for not yet, -1 for error. */ 522275970Scyint 523275970Scyevutil_socket_connect_(evutil_socket_t *fd_ptr, struct sockaddr *sa, int socklen) 524275970Scy{ 525275970Scy int made_fd = 0; 526275970Scy 527275970Scy if (*fd_ptr < 0) { 528275970Scy if ((*fd_ptr = socket(sa->sa_family, SOCK_STREAM, 0)) < 0) 529275970Scy goto err; 530275970Scy made_fd = 1; 531275970Scy if (evutil_make_socket_nonblocking(*fd_ptr) < 0) { 532275970Scy goto err; 533275970Scy } 534275970Scy } 535275970Scy 536275970Scy if (connect(*fd_ptr, sa, socklen) < 0) { 537275970Scy int e = evutil_socket_geterror(*fd_ptr); 538275970Scy if (EVUTIL_ERR_CONNECT_RETRIABLE(e)) 539275970Scy return 0; 540275970Scy if (EVUTIL_ERR_CONNECT_REFUSED(e)) 541275970Scy return 2; 542275970Scy goto err; 543275970Scy } else { 544275970Scy return 1; 545275970Scy } 546275970Scy 547275970Scyerr: 548275970Scy if (made_fd) { 549275970Scy evutil_closesocket(*fd_ptr); 550275970Scy *fd_ptr = -1; 551275970Scy } 552275970Scy return -1; 553275970Scy} 554275970Scy 555275970Scy/* Check whether a socket on which we called connect() is done 556275970Scy connecting. Return 1 for connected, 0 for not yet, -1 for error. In the 557275970Scy error case, set the current socket errno to the error that happened during 558275970Scy the connect operation. */ 559275970Scyint 560275970Scyevutil_socket_finished_connecting_(evutil_socket_t fd) 561275970Scy{ 562275970Scy int e; 563275970Scy ev_socklen_t elen = sizeof(e); 564275970Scy 565275970Scy if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&e, &elen) < 0) 566275970Scy return -1; 567275970Scy 568275970Scy if (e) { 569275970Scy if (EVUTIL_ERR_CONNECT_RETRIABLE(e)) 570275970Scy return 0; 571275970Scy EVUTIL_SET_SOCKET_ERROR(e); 572275970Scy return -1; 573275970Scy } 574275970Scy 575275970Scy return 1; 576275970Scy} 577275970Scy 578275970Scy#if (EVUTIL_AI_PASSIVE|EVUTIL_AI_CANONNAME|EVUTIL_AI_NUMERICHOST| \ 579275970Scy EVUTIL_AI_NUMERICSERV|EVUTIL_AI_V4MAPPED|EVUTIL_AI_ALL| \ 580275970Scy EVUTIL_AI_ADDRCONFIG) != \ 581275970Scy (EVUTIL_AI_PASSIVE^EVUTIL_AI_CANONNAME^EVUTIL_AI_NUMERICHOST^ \ 582275970Scy EVUTIL_AI_NUMERICSERV^EVUTIL_AI_V4MAPPED^EVUTIL_AI_ALL^ \ 583275970Scy EVUTIL_AI_ADDRCONFIG) 584275970Scy#error "Some of our EVUTIL_AI_* flags seem to overlap with system AI_* flags" 585275970Scy#endif 586275970Scy 587275970Scy/* We sometimes need to know whether we have an ipv4 address and whether we 588275970Scy have an ipv6 address. If 'have_checked_interfaces', then we've already done 589275970Scy the test. If 'had_ipv4_address', then it turns out we had an ipv4 address. 590275970Scy If 'had_ipv6_address', then it turns out we had an ipv6 address. These are 591275970Scy set by evutil_check_interfaces. */ 592275970Scystatic int have_checked_interfaces, had_ipv4_address, had_ipv6_address; 593275970Scy 594275970Scy/* Macro: True iff the IPv4 address 'addr', in host order, is in 127.0.0.0/8 595275970Scy */ 596275970Scy#define EVUTIL_V4ADDR_IS_LOCALHOST(addr) (((addr)>>24) == 127) 597275970Scy 598275970Scy/* Macro: True iff the IPv4 address 'addr', in host order, is a class D 599275970Scy * (multiclass) address. 600275970Scy */ 601275970Scy#define EVUTIL_V4ADDR_IS_CLASSD(addr) ((((addr)>>24) & 0xf0) == 0xe0) 602275970Scy 603275970Scystatic void 604275970Scyevutil_found_ifaddr(const struct sockaddr *sa) 605275970Scy{ 606275970Scy const char ZEROES[] = "\x00\x00\x00\x00\x00\x00\x00\x00" 607275970Scy "\x00\x00\x00\x00\x00\x00\x00\x00"; 608275970Scy 609275970Scy if (sa->sa_family == AF_INET) { 610275970Scy const struct sockaddr_in *sin = (struct sockaddr_in *)sa; 611275970Scy ev_uint32_t addr = ntohl(sin->sin_addr.s_addr); 612275970Scy if (addr == 0 || 613275970Scy EVUTIL_V4ADDR_IS_LOCALHOST(addr) || 614275970Scy EVUTIL_V4ADDR_IS_CLASSD(addr)) { 615275970Scy /* Not actually a usable external address. */ 616275970Scy } else { 617275970Scy event_debug(("Detected an IPv4 interface")); 618275970Scy had_ipv4_address = 1; 619275970Scy } 620275970Scy } else if (sa->sa_family == AF_INET6) { 621275970Scy const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; 622275970Scy const unsigned char *addr = 623275970Scy (unsigned char*)sin6->sin6_addr.s6_addr; 624275970Scy if (!memcmp(addr, ZEROES, 8) || 625275970Scy ((addr[0] & 0xfe) == 0xfc) || 626275970Scy (addr[0] == 0xfe && (addr[1] & 0xc0) == 0x80) || 627275970Scy (addr[0] == 0xfe && (addr[1] & 0xc0) == 0xc0) || 628275970Scy (addr[0] == 0xff)) { 629275970Scy /* This is a reserved, ipv4compat, ipv4map, loopback, 630275970Scy * link-local, multicast, or unspecified address. */ 631275970Scy } else { 632275970Scy event_debug(("Detected an IPv6 interface")); 633275970Scy had_ipv6_address = 1; 634275970Scy } 635275970Scy } 636275970Scy} 637275970Scy 638275970Scy#ifdef _WIN32 639275970Scytypedef ULONG (WINAPI *GetAdaptersAddresses_fn_t)( 640275970Scy ULONG, ULONG, PVOID, PIP_ADAPTER_ADDRESSES, PULONG); 641275970Scy#endif 642275970Scy 643275970Scystatic int 644275970Scyevutil_check_ifaddrs(void) 645275970Scy{ 646275970Scy#if defined(EVENT__HAVE_GETIFADDRS) 647275970Scy /* Most free Unixy systems provide getifaddrs, which gives us a linked list 648275970Scy * of struct ifaddrs. */ 649275970Scy struct ifaddrs *ifa = NULL; 650275970Scy const struct ifaddrs *i; 651275970Scy if (getifaddrs(&ifa) < 0) { 652275970Scy event_warn("Unable to call getifaddrs()"); 653275970Scy return -1; 654275970Scy } 655275970Scy 656275970Scy for (i = ifa; i; i = i->ifa_next) { 657275970Scy if (!i->ifa_addr) 658275970Scy continue; 659275970Scy evutil_found_ifaddr(i->ifa_addr); 660275970Scy } 661275970Scy 662275970Scy freeifaddrs(ifa); 663275970Scy return 0; 664275970Scy#elif defined(_WIN32) 665275970Scy /* Windows XP began to provide GetAdaptersAddresses. Windows 2000 had a 666275970Scy "GetAdaptersInfo", but that's deprecated; let's just try 667275970Scy GetAdaptersAddresses and fall back to connect+getsockname. 668275970Scy */ 669285612Sdelphij HMODULE lib = evutil_load_windows_system_library_(TEXT("ihplapi.dll")); 670275970Scy GetAdaptersAddresses_fn_t fn; 671275970Scy ULONG size, res; 672275970Scy IP_ADAPTER_ADDRESSES *addresses = NULL, *address; 673275970Scy int result = -1; 674275970Scy 675275970Scy#define FLAGS (GAA_FLAG_SKIP_ANYCAST | \ 676275970Scy GAA_FLAG_SKIP_MULTICAST | \ 677275970Scy GAA_FLAG_SKIP_DNS_SERVER) 678275970Scy 679275970Scy if (!lib) 680275970Scy goto done; 681275970Scy 682275970Scy if (!(fn = (GetAdaptersAddresses_fn_t) GetProcAddress(lib, "GetAdaptersAddresses"))) 683275970Scy goto done; 684275970Scy 685275970Scy /* Guess how much space we need. */ 686275970Scy size = 15*1024; 687275970Scy addresses = mm_malloc(size); 688275970Scy if (!addresses) 689275970Scy goto done; 690275970Scy res = fn(AF_UNSPEC, FLAGS, NULL, addresses, &size); 691275970Scy if (res == ERROR_BUFFER_OVERFLOW) { 692275970Scy /* we didn't guess that we needed enough space; try again */ 693275970Scy mm_free(addresses); 694275970Scy addresses = mm_malloc(size); 695275970Scy if (!addresses) 696275970Scy goto done; 697275970Scy res = fn(AF_UNSPEC, FLAGS, NULL, addresses, &size); 698275970Scy } 699275970Scy if (res != NO_ERROR) 700275970Scy goto done; 701275970Scy 702275970Scy for (address = addresses; address; address = address->Next) { 703275970Scy IP_ADAPTER_UNICAST_ADDRESS *a; 704275970Scy for (a = address->FirstUnicastAddress; a; a = a->Next) { 705275970Scy /* Yes, it's a linked list inside a linked list */ 706275970Scy struct sockaddr *sa = a->Address.lpSockaddr; 707275970Scy evutil_found_ifaddr(sa); 708275970Scy } 709275970Scy } 710275970Scy 711275970Scy result = 0; 712275970Scydone: 713275970Scy if (lib) 714275970Scy FreeLibrary(lib); 715275970Scy if (addresses) 716275970Scy mm_free(addresses); 717275970Scy return result; 718275970Scy#else 719275970Scy return -1; 720275970Scy#endif 721275970Scy} 722275970Scy 723275970Scy/* Test whether we have an ipv4 interface and an ipv6 interface. Return 0 if 724275970Scy * the test seemed successful. */ 725275970Scystatic int 726275970Scyevutil_check_interfaces(int force_recheck) 727275970Scy{ 728275970Scy evutil_socket_t fd = -1; 729275970Scy struct sockaddr_in sin, sin_out; 730275970Scy struct sockaddr_in6 sin6, sin6_out; 731275970Scy ev_socklen_t sin_out_len = sizeof(sin_out); 732275970Scy ev_socklen_t sin6_out_len = sizeof(sin6_out); 733275970Scy int r; 734275970Scy if (have_checked_interfaces && !force_recheck) 735275970Scy return 0; 736275970Scy 737275970Scy if (evutil_check_ifaddrs() == 0) { 738275970Scy /* Use a nice sane interface, if this system has one. */ 739275970Scy return 0; 740275970Scy } 741275970Scy 742275970Scy /* Ugh. There was no nice sane interface. So to check whether we have 743275970Scy * an interface open for a given protocol, will try to make a UDP 744275970Scy * 'connection' to a remote host on the internet. We don't actually 745275970Scy * use it, so the address doesn't matter, but we want to pick one that 746275970Scy * keep us from using a host- or link-local interface. */ 747275970Scy memset(&sin, 0, sizeof(sin)); 748275970Scy sin.sin_family = AF_INET; 749275970Scy sin.sin_port = htons(53); 750275970Scy r = evutil_inet_pton(AF_INET, "18.244.0.188", &sin.sin_addr); 751275970Scy EVUTIL_ASSERT(r); 752275970Scy 753275970Scy memset(&sin6, 0, sizeof(sin6)); 754275970Scy sin6.sin6_family = AF_INET6; 755275970Scy sin6.sin6_port = htons(53); 756275970Scy r = evutil_inet_pton(AF_INET6, "2001:4860:b002::68", &sin6.sin6_addr); 757275970Scy EVUTIL_ASSERT(r); 758275970Scy 759275970Scy memset(&sin_out, 0, sizeof(sin_out)); 760275970Scy memset(&sin6_out, 0, sizeof(sin6_out)); 761275970Scy 762275970Scy /* XXX some errnos mean 'no address'; some mean 'not enough sockets'. */ 763275970Scy if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) >= 0 && 764275970Scy connect(fd, (struct sockaddr*)&sin, sizeof(sin)) == 0 && 765275970Scy getsockname(fd, (struct sockaddr*)&sin_out, &sin_out_len) == 0) { 766275970Scy /* We might have an IPv4 interface. */ 767275970Scy evutil_found_ifaddr((struct sockaddr*) &sin_out); 768275970Scy } 769275970Scy if (fd >= 0) 770275970Scy evutil_closesocket(fd); 771275970Scy 772275970Scy if ((fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) >= 0 && 773275970Scy connect(fd, (struct sockaddr*)&sin6, sizeof(sin6)) == 0 && 774275970Scy getsockname(fd, (struct sockaddr*)&sin6_out, &sin6_out_len) == 0) { 775275970Scy /* We might have an IPv6 interface. */ 776275970Scy evutil_found_ifaddr((struct sockaddr*) &sin6_out); 777275970Scy } 778275970Scy 779275970Scy if (fd >= 0) 780275970Scy evutil_closesocket(fd); 781275970Scy 782275970Scy return 0; 783275970Scy} 784275970Scy 785275970Scy/* Internal addrinfo flag. This one is set when we allocate the addrinfo from 786275970Scy * inside libevent. Otherwise, the built-in getaddrinfo() function allocated 787275970Scy * it, and we should trust what they said. 788275970Scy **/ 789275970Scy#define EVUTIL_AI_LIBEVENT_ALLOCATED 0x80000000 790275970Scy 791275970Scy/* Helper: construct a new addrinfo containing the socket address in 792275970Scy * 'sa', which must be a sockaddr_in or a sockaddr_in6. Take the 793275970Scy * socktype and protocol info from hints. If they weren't set, then 794275970Scy * allocate both a TCP and a UDP addrinfo. 795275970Scy */ 796275970Scystruct evutil_addrinfo * 797275970Scyevutil_new_addrinfo_(struct sockaddr *sa, ev_socklen_t socklen, 798275970Scy const struct evutil_addrinfo *hints) 799275970Scy{ 800275970Scy struct evutil_addrinfo *res; 801275970Scy EVUTIL_ASSERT(hints); 802275970Scy 803275970Scy if (hints->ai_socktype == 0 && hints->ai_protocol == 0) { 804275970Scy /* Indecisive user! Give them a UDP and a TCP. */ 805275970Scy struct evutil_addrinfo *r1, *r2; 806275970Scy struct evutil_addrinfo tmp; 807275970Scy memcpy(&tmp, hints, sizeof(tmp)); 808275970Scy tmp.ai_socktype = SOCK_STREAM; tmp.ai_protocol = IPPROTO_TCP; 809275970Scy r1 = evutil_new_addrinfo_(sa, socklen, &tmp); 810275970Scy if (!r1) 811275970Scy return NULL; 812275970Scy tmp.ai_socktype = SOCK_DGRAM; tmp.ai_protocol = IPPROTO_UDP; 813275970Scy r2 = evutil_new_addrinfo_(sa, socklen, &tmp); 814275970Scy if (!r2) { 815275970Scy evutil_freeaddrinfo(r1); 816275970Scy return NULL; 817275970Scy } 818275970Scy r1->ai_next = r2; 819275970Scy return r1; 820275970Scy } 821275970Scy 822275970Scy /* We're going to allocate extra space to hold the sockaddr. */ 823275970Scy res = mm_calloc(1,sizeof(struct evutil_addrinfo)+socklen); 824275970Scy if (!res) 825275970Scy return NULL; 826275970Scy res->ai_addr = (struct sockaddr*) 827275970Scy (((char*)res) + sizeof(struct evutil_addrinfo)); 828275970Scy memcpy(res->ai_addr, sa, socklen); 829275970Scy res->ai_addrlen = socklen; 830275970Scy res->ai_family = sa->sa_family; /* Same or not? XXX */ 831275970Scy res->ai_flags = EVUTIL_AI_LIBEVENT_ALLOCATED; 832275970Scy res->ai_socktype = hints->ai_socktype; 833275970Scy res->ai_protocol = hints->ai_protocol; 834275970Scy 835275970Scy return res; 836275970Scy} 837275970Scy 838275970Scy/* Append the addrinfo 'append' to the end of 'first', and return the start of 839275970Scy * the list. Either element can be NULL, in which case we return the element 840275970Scy * that is not NULL. */ 841275970Scystruct evutil_addrinfo * 842275970Scyevutil_addrinfo_append_(struct evutil_addrinfo *first, 843275970Scy struct evutil_addrinfo *append) 844275970Scy{ 845275970Scy struct evutil_addrinfo *ai = first; 846275970Scy if (!ai) 847275970Scy return append; 848275970Scy while (ai->ai_next) 849275970Scy ai = ai->ai_next; 850275970Scy ai->ai_next = append; 851275970Scy 852275970Scy return first; 853275970Scy} 854275970Scy 855275970Scystatic int 856275970Scyparse_numeric_servname(const char *servname) 857275970Scy{ 858275970Scy int n; 859275970Scy char *endptr=NULL; 860275970Scy n = (int) strtol(servname, &endptr, 10); 861275970Scy if (n>=0 && n <= 65535 && servname[0] && endptr && !endptr[0]) 862275970Scy return n; 863275970Scy else 864275970Scy return -1; 865275970Scy} 866275970Scy 867275970Scy/** Parse a service name in 'servname', which can be a decimal port. 868275970Scy * Return the port number, or -1 on error. 869275970Scy */ 870275970Scystatic int 871275970Scyevutil_parse_servname(const char *servname, const char *protocol, 872275970Scy const struct evutil_addrinfo *hints) 873275970Scy{ 874275970Scy int n = parse_numeric_servname(servname); 875275970Scy if (n>=0) 876275970Scy return n; 877275970Scy#if defined(EVENT__HAVE_GETSERVBYNAME) || defined(_WIN32) 878275970Scy if (!(hints->ai_flags & EVUTIL_AI_NUMERICSERV)) { 879275970Scy struct servent *ent = getservbyname(servname, protocol); 880275970Scy if (ent) { 881275970Scy return ntohs(ent->s_port); 882275970Scy } 883275970Scy } 884275970Scy#endif 885275970Scy return -1; 886275970Scy} 887275970Scy 888275970Scy/* Return a string corresponding to a protocol number that we can pass to 889275970Scy * getservyname. */ 890275970Scystatic const char * 891275970Scyevutil_unparse_protoname(int proto) 892275970Scy{ 893275970Scy switch (proto) { 894275970Scy case 0: 895275970Scy return NULL; 896275970Scy case IPPROTO_TCP: 897275970Scy return "tcp"; 898275970Scy case IPPROTO_UDP: 899275970Scy return "udp"; 900275970Scy#ifdef IPPROTO_SCTP 901275970Scy case IPPROTO_SCTP: 902275970Scy return "sctp"; 903275970Scy#endif 904275970Scy default: 905275970Scy#ifdef EVENT__HAVE_GETPROTOBYNUMBER 906275970Scy { 907275970Scy struct protoent *ent = getprotobynumber(proto); 908275970Scy if (ent) 909275970Scy return ent->p_name; 910275970Scy } 911275970Scy#endif 912275970Scy return NULL; 913275970Scy } 914275970Scy} 915275970Scy 916275970Scystatic void 917275970Scyevutil_getaddrinfo_infer_protocols(struct evutil_addrinfo *hints) 918275970Scy{ 919275970Scy /* If we can guess the protocol from the socktype, do so. */ 920275970Scy if (!hints->ai_protocol && hints->ai_socktype) { 921275970Scy if (hints->ai_socktype == SOCK_DGRAM) 922275970Scy hints->ai_protocol = IPPROTO_UDP; 923275970Scy else if (hints->ai_socktype == SOCK_STREAM) 924275970Scy hints->ai_protocol = IPPROTO_TCP; 925275970Scy } 926275970Scy 927275970Scy /* Set the socktype if it isn't set. */ 928275970Scy if (!hints->ai_socktype && hints->ai_protocol) { 929275970Scy if (hints->ai_protocol == IPPROTO_UDP) 930275970Scy hints->ai_socktype = SOCK_DGRAM; 931275970Scy else if (hints->ai_protocol == IPPROTO_TCP) 932275970Scy hints->ai_socktype = SOCK_STREAM; 933275970Scy#ifdef IPPROTO_SCTP 934275970Scy else if (hints->ai_protocol == IPPROTO_SCTP) 935275970Scy hints->ai_socktype = SOCK_STREAM; 936275970Scy#endif 937275970Scy } 938275970Scy} 939275970Scy 940275970Scy#if AF_UNSPEC != PF_UNSPEC 941275970Scy#error "I cannot build on a system where AF_UNSPEC != PF_UNSPEC" 942275970Scy#endif 943275970Scy 944275970Scy/** Implements the part of looking up hosts by name that's common to both 945275970Scy * the blocking and nonblocking resolver: 946275970Scy * - Adjust 'hints' to have a reasonable socktype and protocol. 947275970Scy * - Look up the port based on 'servname', and store it in *portnum, 948275970Scy * - Handle the nodename==NULL case 949275970Scy * - Handle some invalid arguments cases. 950275970Scy * - Handle the cases where nodename is an IPv4 or IPv6 address. 951275970Scy * 952275970Scy * If we need the resolver to look up the hostname, we return 953275970Scy * EVUTIL_EAI_NEED_RESOLVE. Otherwise, we can completely implement 954275970Scy * getaddrinfo: we return 0 or an appropriate EVUTIL_EAI_* error, and 955275970Scy * set *res as getaddrinfo would. 956275970Scy */ 957275970Scyint 958275970Scyevutil_getaddrinfo_common_(const char *nodename, const char *servname, 959275970Scy struct evutil_addrinfo *hints, struct evutil_addrinfo **res, int *portnum) 960275970Scy{ 961275970Scy int port = 0; 962275970Scy const char *pname; 963275970Scy 964275970Scy if (nodename == NULL && servname == NULL) 965275970Scy return EVUTIL_EAI_NONAME; 966275970Scy 967275970Scy /* We only understand 3 families */ 968275970Scy if (hints->ai_family != PF_UNSPEC && hints->ai_family != PF_INET && 969275970Scy hints->ai_family != PF_INET6) 970275970Scy return EVUTIL_EAI_FAMILY; 971275970Scy 972275970Scy evutil_getaddrinfo_infer_protocols(hints); 973275970Scy 974275970Scy /* Look up the port number and protocol, if possible. */ 975275970Scy pname = evutil_unparse_protoname(hints->ai_protocol); 976275970Scy if (servname) { 977275970Scy /* XXXX We could look at the protocol we got back from 978275970Scy * getservbyname, but it doesn't seem too useful. */ 979275970Scy port = evutil_parse_servname(servname, pname, hints); 980275970Scy if (port < 0) { 981275970Scy return EVUTIL_EAI_NONAME; 982275970Scy } 983275970Scy } 984275970Scy 985275970Scy /* If we have no node name, then we're supposed to bind to 'any' and 986275970Scy * connect to localhost. */ 987275970Scy if (nodename == NULL) { 988275970Scy struct evutil_addrinfo *res4=NULL, *res6=NULL; 989275970Scy if (hints->ai_family != PF_INET) { /* INET6 or UNSPEC. */ 990275970Scy struct sockaddr_in6 sin6; 991275970Scy memset(&sin6, 0, sizeof(sin6)); 992275970Scy sin6.sin6_family = AF_INET6; 993275970Scy sin6.sin6_port = htons(port); 994275970Scy if (hints->ai_flags & EVUTIL_AI_PASSIVE) { 995275970Scy /* Bind to :: */ 996275970Scy } else { 997275970Scy /* connect to ::1 */ 998275970Scy sin6.sin6_addr.s6_addr[15] = 1; 999275970Scy } 1000275970Scy res6 = evutil_new_addrinfo_((struct sockaddr*)&sin6, 1001275970Scy sizeof(sin6), hints); 1002275970Scy if (!res6) 1003275970Scy return EVUTIL_EAI_MEMORY; 1004275970Scy } 1005275970Scy 1006275970Scy if (hints->ai_family != PF_INET6) { /* INET or UNSPEC */ 1007275970Scy struct sockaddr_in sin; 1008275970Scy memset(&sin, 0, sizeof(sin)); 1009275970Scy sin.sin_family = AF_INET; 1010275970Scy sin.sin_port = htons(port); 1011275970Scy if (hints->ai_flags & EVUTIL_AI_PASSIVE) { 1012275970Scy /* Bind to 0.0.0.0 */ 1013275970Scy } else { 1014275970Scy /* connect to 127.0.0.1 */ 1015275970Scy sin.sin_addr.s_addr = htonl(0x7f000001); 1016275970Scy } 1017275970Scy res4 = evutil_new_addrinfo_((struct sockaddr*)&sin, 1018275970Scy sizeof(sin), hints); 1019275970Scy if (!res4) { 1020275970Scy if (res6) 1021275970Scy evutil_freeaddrinfo(res6); 1022275970Scy return EVUTIL_EAI_MEMORY; 1023275970Scy } 1024275970Scy } 1025275970Scy *res = evutil_addrinfo_append_(res4, res6); 1026275970Scy return 0; 1027275970Scy } 1028275970Scy 1029275970Scy /* If we can, we should try to parse the hostname without resolving 1030275970Scy * it. */ 1031275970Scy /* Try ipv6. */ 1032275970Scy if (hints->ai_family == PF_INET6 || hints->ai_family == PF_UNSPEC) { 1033275970Scy struct sockaddr_in6 sin6; 1034275970Scy memset(&sin6, 0, sizeof(sin6)); 1035275970Scy if (1==evutil_inet_pton(AF_INET6, nodename, &sin6.sin6_addr)) { 1036275970Scy /* Got an ipv6 address. */ 1037275970Scy sin6.sin6_family = AF_INET6; 1038275970Scy sin6.sin6_port = htons(port); 1039275970Scy *res = evutil_new_addrinfo_((struct sockaddr*)&sin6, 1040275970Scy sizeof(sin6), hints); 1041275970Scy if (!*res) 1042275970Scy return EVUTIL_EAI_MEMORY; 1043275970Scy return 0; 1044275970Scy } 1045275970Scy } 1046275970Scy 1047275970Scy /* Try ipv4. */ 1048275970Scy if (hints->ai_family == PF_INET || hints->ai_family == PF_UNSPEC) { 1049275970Scy struct sockaddr_in sin; 1050275970Scy memset(&sin, 0, sizeof(sin)); 1051275970Scy if (1==evutil_inet_pton(AF_INET, nodename, &sin.sin_addr)) { 1052275970Scy /* Got an ipv6 address. */ 1053275970Scy sin.sin_family = AF_INET; 1054275970Scy sin.sin_port = htons(port); 1055275970Scy *res = evutil_new_addrinfo_((struct sockaddr*)&sin, 1056275970Scy sizeof(sin), hints); 1057275970Scy if (!*res) 1058275970Scy return EVUTIL_EAI_MEMORY; 1059275970Scy return 0; 1060275970Scy } 1061275970Scy } 1062275970Scy 1063275970Scy 1064275970Scy /* If we have reached this point, we definitely need to do a DNS 1065275970Scy * lookup. */ 1066275970Scy if ((hints->ai_flags & EVUTIL_AI_NUMERICHOST)) { 1067275970Scy /* If we're not allowed to do one, then say so. */ 1068275970Scy return EVUTIL_EAI_NONAME; 1069275970Scy } 1070275970Scy *portnum = port; 1071275970Scy return EVUTIL_EAI_NEED_RESOLVE; 1072275970Scy} 1073275970Scy 1074275970Scy#ifdef EVENT__HAVE_GETADDRINFO 1075275970Scy#define USE_NATIVE_GETADDRINFO 1076275970Scy#endif 1077275970Scy 1078275970Scy#ifdef USE_NATIVE_GETADDRINFO 1079275970Scy/* A mask of all the flags that we declare, so we can clear them before calling 1080275970Scy * the native getaddrinfo */ 1081275970Scystatic const unsigned int ALL_NONNATIVE_AI_FLAGS = 1082275970Scy#ifndef AI_PASSIVE 1083275970Scy EVUTIL_AI_PASSIVE | 1084275970Scy#endif 1085275970Scy#ifndef AI_CANONNAME 1086275970Scy EVUTIL_AI_CANONNAME | 1087275970Scy#endif 1088275970Scy#ifndef AI_NUMERICHOST 1089275970Scy EVUTIL_AI_NUMERICHOST | 1090275970Scy#endif 1091275970Scy#ifndef AI_NUMERICSERV 1092275970Scy EVUTIL_AI_NUMERICSERV | 1093275970Scy#endif 1094275970Scy#ifndef AI_ADDRCONFIG 1095275970Scy EVUTIL_AI_ADDRCONFIG | 1096275970Scy#endif 1097275970Scy#ifndef AI_ALL 1098275970Scy EVUTIL_AI_ALL | 1099275970Scy#endif 1100275970Scy#ifndef AI_V4MAPPED 1101275970Scy EVUTIL_AI_V4MAPPED | 1102275970Scy#endif 1103275970Scy EVUTIL_AI_LIBEVENT_ALLOCATED; 1104275970Scy 1105275970Scystatic const unsigned int ALL_NATIVE_AI_FLAGS = 1106275970Scy#ifdef AI_PASSIVE 1107275970Scy AI_PASSIVE | 1108275970Scy#endif 1109275970Scy#ifdef AI_CANONNAME 1110275970Scy AI_CANONNAME | 1111275970Scy#endif 1112275970Scy#ifdef AI_NUMERICHOST 1113275970Scy AI_NUMERICHOST | 1114275970Scy#endif 1115275970Scy#ifdef AI_NUMERICSERV 1116275970Scy AI_NUMERICSERV | 1117275970Scy#endif 1118275970Scy#ifdef AI_ADDRCONFIG 1119275970Scy AI_ADDRCONFIG | 1120275970Scy#endif 1121275970Scy#ifdef AI_ALL 1122275970Scy AI_ALL | 1123275970Scy#endif 1124275970Scy#ifdef AI_V4MAPPED 1125275970Scy AI_V4MAPPED | 1126275970Scy#endif 1127275970Scy 0; 1128275970Scy#endif 1129275970Scy 1130275970Scy#ifndef USE_NATIVE_GETADDRINFO 1131275970Scy/* Helper for systems with no getaddrinfo(): make one or more addrinfos out of 1132275970Scy * a struct hostent. 1133275970Scy */ 1134275970Scystatic struct evutil_addrinfo * 1135275970Scyaddrinfo_from_hostent(const struct hostent *ent, 1136275970Scy int port, const struct evutil_addrinfo *hints) 1137275970Scy{ 1138275970Scy int i; 1139275970Scy struct sockaddr_in sin; 1140275970Scy struct sockaddr_in6 sin6; 1141275970Scy struct sockaddr *sa; 1142275970Scy int socklen; 1143275970Scy struct evutil_addrinfo *res=NULL, *ai; 1144275970Scy void *addrp; 1145275970Scy 1146275970Scy if (ent->h_addrtype == PF_INET) { 1147275970Scy memset(&sin, 0, sizeof(sin)); 1148275970Scy sin.sin_family = AF_INET; 1149275970Scy sin.sin_port = htons(port); 1150275970Scy sa = (struct sockaddr *)&sin; 1151275970Scy socklen = sizeof(struct sockaddr_in); 1152275970Scy addrp = &sin.sin_addr; 1153275970Scy if (ent->h_length != sizeof(sin.sin_addr)) { 1154275970Scy event_warnx("Weird h_length from gethostbyname"); 1155275970Scy return NULL; 1156275970Scy } 1157275970Scy } else if (ent->h_addrtype == PF_INET6) { 1158275970Scy memset(&sin6, 0, sizeof(sin6)); 1159275970Scy sin6.sin6_family = AF_INET6; 1160275970Scy sin6.sin6_port = htons(port); 1161275970Scy sa = (struct sockaddr *)&sin6; 1162275970Scy socklen = sizeof(struct sockaddr_in); 1163275970Scy addrp = &sin6.sin6_addr; 1164275970Scy if (ent->h_length != sizeof(sin6.sin6_addr)) { 1165275970Scy event_warnx("Weird h_length from gethostbyname"); 1166275970Scy return NULL; 1167275970Scy } 1168275970Scy } else 1169275970Scy return NULL; 1170275970Scy 1171275970Scy for (i = 0; ent->h_addr_list[i]; ++i) { 1172275970Scy memcpy(addrp, ent->h_addr_list[i], ent->h_length); 1173275970Scy ai = evutil_new_addrinfo_(sa, socklen, hints); 1174275970Scy if (!ai) { 1175275970Scy evutil_freeaddrinfo(res); 1176275970Scy return NULL; 1177275970Scy } 1178275970Scy res = evutil_addrinfo_append_(res, ai); 1179275970Scy } 1180275970Scy 1181275970Scy if (res && ((hints->ai_flags & EVUTIL_AI_CANONNAME) && ent->h_name)) { 1182275970Scy res->ai_canonname = mm_strdup(ent->h_name); 1183275970Scy if (res->ai_canonname == NULL) { 1184275970Scy evutil_freeaddrinfo(res); 1185275970Scy return NULL; 1186275970Scy } 1187275970Scy } 1188275970Scy 1189275970Scy return res; 1190275970Scy} 1191275970Scy#endif 1192275970Scy 1193275970Scy/* If the EVUTIL_AI_ADDRCONFIG flag is set on hints->ai_flags, and 1194275970Scy * hints->ai_family is PF_UNSPEC, then revise the value of hints->ai_family so 1195275970Scy * that we'll only get addresses we could maybe connect to. 1196275970Scy */ 1197275970Scyvoid 1198275970Scyevutil_adjust_hints_for_addrconfig_(struct evutil_addrinfo *hints) 1199275970Scy{ 1200275970Scy if (!(hints->ai_flags & EVUTIL_AI_ADDRCONFIG)) 1201275970Scy return; 1202275970Scy if (hints->ai_family != PF_UNSPEC) 1203275970Scy return; 1204275970Scy if (!have_checked_interfaces) 1205275970Scy evutil_check_interfaces(0); 1206275970Scy if (had_ipv4_address && !had_ipv6_address) { 1207275970Scy hints->ai_family = PF_INET; 1208275970Scy } else if (!had_ipv4_address && had_ipv6_address) { 1209275970Scy hints->ai_family = PF_INET6; 1210275970Scy } 1211275970Scy} 1212275970Scy 1213275970Scy#ifdef USE_NATIVE_GETADDRINFO 1214275970Scystatic int need_numeric_port_hack_=0; 1215275970Scystatic int need_socktype_protocol_hack_=0; 1216275970Scystatic int tested_for_getaddrinfo_hacks=0; 1217275970Scy 1218275970Scy/* Some older BSDs (like OpenBSD up to 4.6) used to believe that 1219275970Scy giving a numeric port without giving an ai_socktype was verboten. 1220275970Scy We test for this so we can apply an appropriate workaround. If it 1221275970Scy turns out that the bug is present, then: 1222275970Scy 1223275970Scy - If nodename==NULL and servname is numeric, we build an answer 1224275970Scy ourselves using evutil_getaddrinfo_common_(). 1225275970Scy 1226275970Scy - If nodename!=NULL and servname is numeric, then we set 1227275970Scy servname=NULL when calling getaddrinfo, and post-process the 1228275970Scy result to set the ports on it. 1229275970Scy 1230275970Scy We test for this bug at runtime, since otherwise we can't have the 1231275970Scy same binary run on multiple BSD versions. 1232275970Scy 1233275970Scy - Some versions of Solaris believe that it's nice to leave to protocol 1234275970Scy field set to 0. We test for this so we can apply an appropriate 1235275970Scy workaround. 1236275970Scy*/ 1237275970Scystatic void 1238275970Scytest_for_getaddrinfo_hacks(void) 1239275970Scy{ 1240275970Scy int r, r2; 1241275970Scy struct evutil_addrinfo *ai=NULL, *ai2=NULL; 1242275970Scy struct evutil_addrinfo hints; 1243275970Scy 1244275970Scy memset(&hints,0,sizeof(hints)); 1245275970Scy hints.ai_family = PF_UNSPEC; 1246275970Scy hints.ai_flags = 1247275970Scy#ifdef AI_NUMERICHOST 1248275970Scy AI_NUMERICHOST | 1249275970Scy#endif 1250275970Scy#ifdef AI_NUMERICSERV 1251275970Scy AI_NUMERICSERV | 1252275970Scy#endif 1253275970Scy 0; 1254275970Scy r = getaddrinfo("1.2.3.4", "80", &hints, &ai); 1255275970Scy hints.ai_socktype = SOCK_STREAM; 1256275970Scy r2 = getaddrinfo("1.2.3.4", "80", &hints, &ai2); 1257275970Scy if (r2 == 0 && r != 0) { 1258275970Scy need_numeric_port_hack_=1; 1259275970Scy } 1260275970Scy if (ai2 && ai2->ai_protocol == 0) { 1261275970Scy need_socktype_protocol_hack_=1; 1262275970Scy } 1263275970Scy 1264275970Scy if (ai) 1265275970Scy freeaddrinfo(ai); 1266275970Scy if (ai2) 1267275970Scy freeaddrinfo(ai2); 1268275970Scy tested_for_getaddrinfo_hacks=1; 1269275970Scy} 1270275970Scy 1271275970Scystatic inline int 1272275970Scyneed_numeric_port_hack(void) 1273275970Scy{ 1274275970Scy if (!tested_for_getaddrinfo_hacks) 1275275970Scy test_for_getaddrinfo_hacks(); 1276275970Scy return need_numeric_port_hack_; 1277275970Scy} 1278275970Scy 1279275970Scystatic inline int 1280275970Scyneed_socktype_protocol_hack(void) 1281275970Scy{ 1282275970Scy if (!tested_for_getaddrinfo_hacks) 1283275970Scy test_for_getaddrinfo_hacks(); 1284275970Scy return need_socktype_protocol_hack_; 1285275970Scy} 1286275970Scy 1287275970Scystatic void 1288275970Scyapply_numeric_port_hack(int port, struct evutil_addrinfo **ai) 1289275970Scy{ 1290275970Scy /* Now we run through the list and set the ports on all of the 1291275970Scy * results where ports would make sense. */ 1292275970Scy for ( ; *ai; ai = &(*ai)->ai_next) { 1293275970Scy struct sockaddr *sa = (*ai)->ai_addr; 1294275970Scy if (sa && sa->sa_family == AF_INET) { 1295275970Scy struct sockaddr_in *sin = (struct sockaddr_in*)sa; 1296275970Scy sin->sin_port = htons(port); 1297275970Scy } else if (sa && sa->sa_family == AF_INET6) { 1298275970Scy struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)sa; 1299275970Scy sin6->sin6_port = htons(port); 1300275970Scy } else { 1301275970Scy /* A numeric port makes no sense here; remove this one 1302275970Scy * from the list. */ 1303275970Scy struct evutil_addrinfo *victim = *ai; 1304275970Scy *ai = victim->ai_next; 1305275970Scy victim->ai_next = NULL; 1306275970Scy freeaddrinfo(victim); 1307275970Scy } 1308275970Scy } 1309275970Scy} 1310275970Scy 1311275970Scystatic int 1312275970Scyapply_socktype_protocol_hack(struct evutil_addrinfo *ai) 1313275970Scy{ 1314275970Scy struct evutil_addrinfo *ai_new; 1315275970Scy for (; ai; ai = ai->ai_next) { 1316275970Scy evutil_getaddrinfo_infer_protocols(ai); 1317275970Scy if (ai->ai_socktype || ai->ai_protocol) 1318275970Scy continue; 1319275970Scy ai_new = mm_malloc(sizeof(*ai_new)); 1320275970Scy if (!ai_new) 1321275970Scy return -1; 1322275970Scy memcpy(ai_new, ai, sizeof(*ai_new)); 1323275970Scy ai->ai_socktype = SOCK_STREAM; 1324275970Scy ai->ai_protocol = IPPROTO_TCP; 1325275970Scy ai_new->ai_socktype = SOCK_DGRAM; 1326275970Scy ai_new->ai_protocol = IPPROTO_UDP; 1327275970Scy 1328275970Scy ai_new->ai_next = ai->ai_next; 1329275970Scy ai->ai_next = ai_new; 1330275970Scy } 1331275970Scy return 0; 1332275970Scy} 1333275970Scy#endif 1334275970Scy 1335275970Scyint 1336275970Scyevutil_getaddrinfo(const char *nodename, const char *servname, 1337275970Scy const struct evutil_addrinfo *hints_in, struct evutil_addrinfo **res) 1338275970Scy{ 1339275970Scy#ifdef USE_NATIVE_GETADDRINFO 1340275970Scy struct evutil_addrinfo hints; 1341275970Scy int portnum=-1, need_np_hack, err; 1342275970Scy 1343275970Scy if (hints_in) { 1344275970Scy memcpy(&hints, hints_in, sizeof(hints)); 1345275970Scy } else { 1346275970Scy memset(&hints, 0, sizeof(hints)); 1347275970Scy hints.ai_family = PF_UNSPEC; 1348275970Scy } 1349275970Scy 1350275970Scy#ifndef AI_ADDRCONFIG 1351275970Scy /* Not every system has AI_ADDRCONFIG, so fake it. */ 1352275970Scy if (hints.ai_family == PF_UNSPEC && 1353275970Scy (hints.ai_flags & EVUTIL_AI_ADDRCONFIG)) { 1354275970Scy evutil_adjust_hints_for_addrconfig_(&hints); 1355275970Scy } 1356275970Scy#endif 1357275970Scy 1358275970Scy#ifndef AI_NUMERICSERV 1359275970Scy /* Not every system has AI_NUMERICSERV, so fake it. */ 1360275970Scy if (hints.ai_flags & EVUTIL_AI_NUMERICSERV) { 1361275970Scy if (servname && parse_numeric_servname(servname)<0) 1362275970Scy return EVUTIL_EAI_NONAME; 1363275970Scy } 1364275970Scy#endif 1365275970Scy 1366275970Scy /* Enough operating systems handle enough common non-resolve 1367275970Scy * cases here weirdly enough that we are better off just 1368275970Scy * overriding them. For example: 1369275970Scy * 1370275970Scy * - Windows doesn't like to infer the protocol from the 1371275970Scy * socket type, or fill in socket or protocol types much at 1372275970Scy * all. It also seems to do its own broken implicit 1373275970Scy * always-on version of AI_ADDRCONFIG that keeps it from 1374275970Scy * ever resolving even a literal IPv6 address when 1375275970Scy * ai_addrtype is PF_UNSPEC. 1376275970Scy */ 1377275970Scy#ifdef _WIN32 1378275970Scy { 1379275970Scy int tmp_port; 1380275970Scy err = evutil_getaddrinfo_common_(nodename,servname,&hints, 1381275970Scy res, &tmp_port); 1382275970Scy if (err == 0 || 1383275970Scy err == EVUTIL_EAI_MEMORY || 1384275970Scy err == EVUTIL_EAI_NONAME) 1385275970Scy return err; 1386275970Scy /* If we make it here, the system getaddrinfo can 1387275970Scy * have a crack at it. */ 1388275970Scy } 1389275970Scy#endif 1390275970Scy 1391275970Scy /* See documentation for need_numeric_port_hack above.*/ 1392275970Scy need_np_hack = need_numeric_port_hack() && servname && !hints.ai_socktype 1393275970Scy && ((portnum=parse_numeric_servname(servname)) >= 0); 1394275970Scy if (need_np_hack) { 1395275970Scy if (!nodename) 1396275970Scy return evutil_getaddrinfo_common_( 1397275970Scy NULL,servname,&hints, res, &portnum); 1398275970Scy servname = NULL; 1399275970Scy } 1400275970Scy 1401275970Scy if (need_socktype_protocol_hack()) { 1402275970Scy evutil_getaddrinfo_infer_protocols(&hints); 1403275970Scy } 1404275970Scy 1405275970Scy /* Make sure that we didn't actually steal any AI_FLAGS values that 1406275970Scy * the system is using. (This is a constant expression, and should ge 1407275970Scy * optimized out.) 1408275970Scy * 1409275970Scy * XXXX Turn this into a compile-time failure rather than a run-time 1410275970Scy * failure. 1411275970Scy */ 1412275970Scy EVUTIL_ASSERT((ALL_NONNATIVE_AI_FLAGS & ALL_NATIVE_AI_FLAGS) == 0); 1413275970Scy 1414275970Scy /* Clear any flags that only libevent understands. */ 1415275970Scy hints.ai_flags &= ~ALL_NONNATIVE_AI_FLAGS; 1416275970Scy 1417275970Scy err = getaddrinfo(nodename, servname, &hints, res); 1418275970Scy if (need_np_hack) 1419275970Scy apply_numeric_port_hack(portnum, res); 1420275970Scy 1421275970Scy if (need_socktype_protocol_hack()) { 1422275970Scy if (apply_socktype_protocol_hack(*res) < 0) { 1423275970Scy evutil_freeaddrinfo(*res); 1424275970Scy *res = NULL; 1425275970Scy return EVUTIL_EAI_MEMORY; 1426275970Scy } 1427275970Scy } 1428275970Scy return err; 1429275970Scy#else 1430275970Scy int port=0, err; 1431275970Scy struct hostent *ent = NULL; 1432275970Scy struct evutil_addrinfo hints; 1433275970Scy 1434275970Scy if (hints_in) { 1435275970Scy memcpy(&hints, hints_in, sizeof(hints)); 1436275970Scy } else { 1437275970Scy memset(&hints, 0, sizeof(hints)); 1438275970Scy hints.ai_family = PF_UNSPEC; 1439275970Scy } 1440275970Scy 1441275970Scy evutil_adjust_hints_for_addrconfig_(&hints); 1442275970Scy 1443275970Scy err = evutil_getaddrinfo_common_(nodename, servname, &hints, res, &port); 1444275970Scy if (err != EVUTIL_EAI_NEED_RESOLVE) { 1445275970Scy /* We either succeeded or failed. No need to continue */ 1446275970Scy return err; 1447275970Scy } 1448275970Scy 1449275970Scy err = 0; 1450275970Scy /* Use any of the various gethostbyname_r variants as available. */ 1451275970Scy { 1452275970Scy#ifdef EVENT__HAVE_GETHOSTBYNAME_R_6_ARG 1453275970Scy /* This one is what glibc provides. */ 1454275970Scy char buf[2048]; 1455275970Scy struct hostent hostent; 1456275970Scy int r; 1457275970Scy r = gethostbyname_r(nodename, &hostent, buf, sizeof(buf), &ent, 1458275970Scy &err); 1459275970Scy#elif defined(EVENT__HAVE_GETHOSTBYNAME_R_5_ARG) 1460275970Scy char buf[2048]; 1461275970Scy struct hostent hostent; 1462275970Scy ent = gethostbyname_r(nodename, &hostent, buf, sizeof(buf), 1463275970Scy &err); 1464275970Scy#elif defined(EVENT__HAVE_GETHOSTBYNAME_R_3_ARG) 1465275970Scy struct hostent_data data; 1466275970Scy struct hostent hostent; 1467275970Scy memset(&data, 0, sizeof(data)); 1468275970Scy err = gethostbyname_r(nodename, &hostent, &data); 1469275970Scy ent = err ? NULL : &hostent; 1470275970Scy#else 1471275970Scy /* fall back to gethostbyname. */ 1472275970Scy /* XXXX This needs a lock everywhere but Windows. */ 1473275970Scy ent = gethostbyname(nodename); 1474275970Scy#ifdef _WIN32 1475275970Scy err = WSAGetLastError(); 1476275970Scy#else 1477275970Scy err = h_errno; 1478275970Scy#endif 1479275970Scy#endif 1480275970Scy 1481275970Scy /* Now we have either ent or err set. */ 1482275970Scy if (!ent) { 1483275970Scy /* XXX is this right for windows ? */ 1484275970Scy switch (err) { 1485275970Scy case TRY_AGAIN: 1486275970Scy return EVUTIL_EAI_AGAIN; 1487275970Scy case NO_RECOVERY: 1488275970Scy default: 1489275970Scy return EVUTIL_EAI_FAIL; 1490275970Scy case HOST_NOT_FOUND: 1491275970Scy return EVUTIL_EAI_NONAME; 1492275970Scy case NO_ADDRESS: 1493275970Scy#if NO_DATA != NO_ADDRESS 1494275970Scy case NO_DATA: 1495275970Scy#endif 1496275970Scy return EVUTIL_EAI_NODATA; 1497275970Scy } 1498275970Scy } 1499275970Scy 1500275970Scy if (ent->h_addrtype != hints.ai_family && 1501275970Scy hints.ai_family != PF_UNSPEC) { 1502275970Scy /* This wasn't the type we were hoping for. Too bad 1503275970Scy * we never had a chance to ask gethostbyname for what 1504275970Scy * we wanted. */ 1505275970Scy return EVUTIL_EAI_NONAME; 1506275970Scy } 1507275970Scy 1508275970Scy /* Make sure we got _some_ answers. */ 1509275970Scy if (ent->h_length == 0) 1510275970Scy return EVUTIL_EAI_NODATA; 1511275970Scy 1512275970Scy /* If we got an address type we don't know how to make a 1513275970Scy sockaddr for, give up. */ 1514275970Scy if (ent->h_addrtype != PF_INET && ent->h_addrtype != PF_INET6) 1515275970Scy return EVUTIL_EAI_FAMILY; 1516275970Scy 1517275970Scy *res = addrinfo_from_hostent(ent, port, &hints); 1518275970Scy if (! *res) 1519275970Scy return EVUTIL_EAI_MEMORY; 1520275970Scy } 1521275970Scy 1522275970Scy return 0; 1523275970Scy#endif 1524275970Scy} 1525275970Scy 1526275970Scyvoid 1527275970Scyevutil_freeaddrinfo(struct evutil_addrinfo *ai) 1528275970Scy{ 1529275970Scy#ifdef EVENT__HAVE_GETADDRINFO 1530275970Scy if (!(ai->ai_flags & EVUTIL_AI_LIBEVENT_ALLOCATED)) { 1531275970Scy freeaddrinfo(ai); 1532275970Scy return; 1533275970Scy } 1534275970Scy#endif 1535275970Scy while (ai) { 1536275970Scy struct evutil_addrinfo *next = ai->ai_next; 1537275970Scy if (ai->ai_canonname) 1538275970Scy mm_free(ai->ai_canonname); 1539275970Scy mm_free(ai); 1540275970Scy ai = next; 1541275970Scy } 1542275970Scy} 1543275970Scy 1544275970Scystatic evdns_getaddrinfo_fn evdns_getaddrinfo_impl = NULL; 1545275970Scy 1546275970Scyvoid 1547275970Scyevutil_set_evdns_getaddrinfo_fn_(evdns_getaddrinfo_fn fn) 1548275970Scy{ 1549275970Scy if (!evdns_getaddrinfo_impl) 1550275970Scy evdns_getaddrinfo_impl = fn; 1551275970Scy} 1552275970Scy 1553275970Scy/* Internal helper function: act like evdns_getaddrinfo if dns_base is set; 1554275970Scy * otherwise do a blocking resolve and pass the result to the callback in the 1555275970Scy * way that evdns_getaddrinfo would. 1556275970Scy */ 1557275970Scyint 1558275970Scyevutil_getaddrinfo_async_(struct evdns_base *dns_base, 1559275970Scy const char *nodename, const char *servname, 1560275970Scy const struct evutil_addrinfo *hints_in, 1561275970Scy void (*cb)(int, struct evutil_addrinfo *, void *), void *arg) 1562275970Scy{ 1563275970Scy if (dns_base && evdns_getaddrinfo_impl) { 1564275970Scy evdns_getaddrinfo_impl( 1565275970Scy dns_base, nodename, servname, hints_in, cb, arg); 1566275970Scy } else { 1567275970Scy struct evutil_addrinfo *ai=NULL; 1568275970Scy int err; 1569275970Scy err = evutil_getaddrinfo(nodename, servname, hints_in, &ai); 1570275970Scy cb(err, ai, arg); 1571275970Scy } 1572275970Scy return 0; 1573275970Scy} 1574275970Scy 1575275970Scyconst char * 1576275970Scyevutil_gai_strerror(int err) 1577275970Scy{ 1578275970Scy /* As a sneaky side-benefit, this case statement will get most 1579275970Scy * compilers to tell us if any of the error codes we defined 1580275970Scy * conflict with the platform's native error codes. */ 1581275970Scy switch (err) { 1582275970Scy case EVUTIL_EAI_CANCEL: 1583275970Scy return "Request canceled"; 1584275970Scy case 0: 1585275970Scy return "No error"; 1586275970Scy 1587275970Scy case EVUTIL_EAI_ADDRFAMILY: 1588275970Scy return "address family for nodename not supported"; 1589275970Scy case EVUTIL_EAI_AGAIN: 1590275970Scy return "temporary failure in name resolution"; 1591275970Scy case EVUTIL_EAI_BADFLAGS: 1592275970Scy return "invalid value for ai_flags"; 1593275970Scy case EVUTIL_EAI_FAIL: 1594275970Scy return "non-recoverable failure in name resolution"; 1595275970Scy case EVUTIL_EAI_FAMILY: 1596275970Scy return "ai_family not supported"; 1597275970Scy case EVUTIL_EAI_MEMORY: 1598275970Scy return "memory allocation failure"; 1599275970Scy case EVUTIL_EAI_NODATA: 1600275970Scy return "no address associated with nodename"; 1601275970Scy case EVUTIL_EAI_NONAME: 1602275970Scy return "nodename nor servname provided, or not known"; 1603275970Scy case EVUTIL_EAI_SERVICE: 1604275970Scy return "servname not supported for ai_socktype"; 1605275970Scy case EVUTIL_EAI_SOCKTYPE: 1606275970Scy return "ai_socktype not supported"; 1607275970Scy case EVUTIL_EAI_SYSTEM: 1608275970Scy return "system error"; 1609275970Scy default: 1610275970Scy#if defined(USE_NATIVE_GETADDRINFO) && defined(_WIN32) 1611275970Scy return gai_strerrorA(err); 1612275970Scy#elif defined(USE_NATIVE_GETADDRINFO) 1613275970Scy return gai_strerror(err); 1614275970Scy#else 1615275970Scy return "Unknown error code"; 1616275970Scy#endif 1617275970Scy } 1618275970Scy} 1619275970Scy 1620275970Scy#ifdef _WIN32 1621275970Scy/* destructively remove a trailing line terminator from s */ 1622275970Scystatic void 1623275970Scychomp (char *s) 1624275970Scy{ 1625275970Scy size_t len; 1626275970Scy if (s && (len = strlen (s)) > 0 && s[len - 1] == '\n') { 1627275970Scy s[--len] = 0; 1628275970Scy if (len > 0 && s[len - 1] == '\r') 1629275970Scy s[--len] = 0; 1630275970Scy } 1631275970Scy} 1632275970Scy 1633275970Scy/* FormatMessage returns allocated strings, but evutil_socket_error_to_string 1634275970Scy * is supposed to return a string which is good indefinitely without having 1635275970Scy * to be freed. To make this work without leaking memory, we cache the 1636275970Scy * string the first time FormatMessage is called on a particular error 1637275970Scy * code, and then return the cached string on subsequent calls with the 1638275970Scy * same code. The strings aren't freed until libevent_global_shutdown 1639275970Scy * (or never). We use a linked list to cache the errors, because we 1640275970Scy * only expect there to be a few dozen, and that should be fast enough. 1641275970Scy */ 1642275970Scy 1643275970Scystruct cached_sock_errs_entry { 1644275970Scy HT_ENTRY(cached_sock_errs_entry) node; 1645275970Scy DWORD code; 1646275970Scy char *msg; /* allocated with LocalAlloc; free with LocalFree */ 1647275970Scy}; 1648275970Scy 1649275970Scystatic inline unsigned 1650275970Scyhash_cached_sock_errs(const struct cached_sock_errs_entry *e) 1651275970Scy{ 1652275970Scy /* Use Murmur3's 32-bit finalizer as an integer hash function */ 1653275970Scy DWORD h = e->code; 1654275970Scy h ^= h >> 16; 1655275970Scy h *= 0x85ebca6b; 1656275970Scy h ^= h >> 13; 1657275970Scy h *= 0xc2b2ae35; 1658275970Scy h ^= h >> 16; 1659275970Scy return h; 1660275970Scy} 1661275970Scy 1662275970Scystatic inline int 1663275970Scyeq_cached_sock_errs(const struct cached_sock_errs_entry *a, 1664275970Scy const struct cached_sock_errs_entry *b) 1665275970Scy{ 1666275970Scy return a->code == b->code; 1667275970Scy} 1668275970Scy 1669275970Scy#ifndef EVENT__DISABLE_THREAD_SUPPORT 1670275970Scystatic void *windows_socket_errors_lock_ = NULL; 1671275970Scy#endif 1672275970Scy 1673275970Scystatic HT_HEAD(cached_sock_errs_map, cached_sock_errs_entry) 1674275970Scy windows_socket_errors = HT_INITIALIZER(); 1675275970Scy 1676275970ScyHT_PROTOTYPE(cached_sock_errs_map, 1677275970Scy cached_sock_errs_entry, 1678275970Scy node, 1679275970Scy hash_cached_sock_errs, 1680275970Scy eq_cached_sock_errs); 1681275970Scy 1682275970ScyHT_GENERATE(cached_sock_errs_map, 1683275970Scy cached_sock_errs_entry, 1684275970Scy node, 1685275970Scy hash_cached_sock_errs, 1686275970Scy eq_cached_sock_errs, 1687275970Scy 0.5, 1688275970Scy mm_malloc, 1689275970Scy mm_realloc, 1690275970Scy mm_free); 1691275970Scy 1692275970Scy/** Equivalent to strerror, but for windows socket errors. */ 1693275970Scyconst char * 1694275970Scyevutil_socket_error_to_string(int errcode) 1695275970Scy{ 1696275970Scy struct cached_sock_errs_entry *errs, *newerr, find; 1697275970Scy char *msg = NULL; 1698275970Scy 1699275970Scy EVLOCK_LOCK(windows_socket_errors_lock_, 0); 1700275970Scy 1701275970Scy find.code = errcode; 1702275970Scy errs = HT_FIND(cached_sock_errs_map, &windows_socket_errors, &find); 1703275970Scy if (errs) { 1704275970Scy msg = errs->msg; 1705275970Scy goto done; 1706275970Scy } 1707275970Scy 1708275970Scy if (0 != FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | 1709275970Scy FORMAT_MESSAGE_IGNORE_INSERTS | 1710275970Scy FORMAT_MESSAGE_ALLOCATE_BUFFER, 1711275970Scy NULL, errcode, 0, (LPTSTR)&msg, 0, NULL)) 1712275970Scy chomp (msg); /* because message has trailing newline */ 1713275970Scy else { 1714275970Scy size_t len = 50; 1715275970Scy /* use LocalAlloc because FormatMessage does */ 1716275970Scy msg = LocalAlloc(LMEM_FIXED, len); 1717275970Scy if (!msg) { 1718275970Scy msg = (char *)"LocalAlloc failed during Winsock error"; 1719275970Scy goto done; 1720275970Scy } 1721275970Scy evutil_snprintf(msg, len, "winsock error 0x%08x", errcode); 1722275970Scy } 1723275970Scy 1724275970Scy newerr = (struct cached_sock_errs_entry *) 1725275970Scy mm_malloc(sizeof (struct cached_sock_errs_entry)); 1726275970Scy 1727275970Scy if (!newerr) { 1728275970Scy LocalFree(msg); 1729275970Scy msg = (char *)"malloc failed during Winsock error"; 1730275970Scy goto done; 1731275970Scy } 1732275970Scy 1733275970Scy newerr->code = errcode; 1734275970Scy newerr->msg = msg; 1735275970Scy HT_INSERT(cached_sock_errs_map, &windows_socket_errors, newerr); 1736275970Scy 1737275970Scy done: 1738275970Scy EVLOCK_UNLOCK(windows_socket_errors_lock_, 0); 1739275970Scy 1740275970Scy return msg; 1741275970Scy} 1742275970Scy 1743275970Scy#ifndef EVENT__DISABLE_THREAD_SUPPORT 1744275970Scyint 1745275970Scyevutil_global_setup_locks_(const int enable_locks) 1746275970Scy{ 1747275970Scy EVTHREAD_SETUP_GLOBAL_LOCK(windows_socket_errors_lock_, 0); 1748275970Scy return 0; 1749275970Scy} 1750275970Scy#endif 1751275970Scy 1752275970Scystatic void 1753275970Scyevutil_free_sock_err_globals(void) 1754275970Scy{ 1755275970Scy struct cached_sock_errs_entry **errs, *tofree; 1756275970Scy 1757275970Scy for (errs = HT_START(cached_sock_errs_map, &windows_socket_errors) 1758275970Scy ; errs; ) { 1759275970Scy tofree = *errs; 1760275970Scy errs = HT_NEXT_RMV(cached_sock_errs_map, 1761275970Scy &windows_socket_errors, 1762275970Scy errs); 1763275970Scy LocalFree(tofree->msg); 1764275970Scy mm_free(tofree); 1765275970Scy } 1766275970Scy 1767275970Scy HT_CLEAR(cached_sock_errs_map, &windows_socket_errors); 1768275970Scy 1769275970Scy#ifndef EVENT__DISABLE_THREAD_SUPPORT 1770275970Scy if (windows_socket_errors_lock_ != NULL) { 1771275970Scy EVTHREAD_FREE_LOCK(windows_socket_errors_lock_, 0); 1772275970Scy windows_socket_errors_lock_ = NULL; 1773275970Scy } 1774275970Scy#endif 1775275970Scy} 1776275970Scy 1777275970Scy#else 1778275970Scy 1779275970Scy#ifndef EVENT__DISABLE_THREAD_SUPPORT 1780275970Scyint 1781275970Scyevutil_global_setup_locks_(const int enable_locks) 1782275970Scy{ 1783275970Scy return 0; 1784275970Scy} 1785275970Scy#endif 1786275970Scy 1787275970Scystatic void 1788275970Scyevutil_free_sock_err_globals(void) 1789275970Scy{ 1790275970Scy} 1791275970Scy 1792275970Scy#endif 1793275970Scy 1794275970Scyint 1795275970Scyevutil_snprintf(char *buf, size_t buflen, const char *format, ...) 1796275970Scy{ 1797275970Scy int r; 1798275970Scy va_list ap; 1799275970Scy va_start(ap, format); 1800275970Scy r = evutil_vsnprintf(buf, buflen, format, ap); 1801275970Scy va_end(ap); 1802275970Scy return r; 1803275970Scy} 1804275970Scy 1805275970Scyint 1806275970Scyevutil_vsnprintf(char *buf, size_t buflen, const char *format, va_list ap) 1807275970Scy{ 1808275970Scy int r; 1809275970Scy if (!buflen) 1810275970Scy return 0; 1811275970Scy#if defined(_MSC_VER) || defined(_WIN32) 1812275970Scy r = _vsnprintf(buf, buflen, format, ap); 1813275970Scy if (r < 0) 1814275970Scy r = _vscprintf(format, ap); 1815275970Scy#elif defined(sgi) 1816275970Scy /* Make sure we always use the correct vsnprintf on IRIX */ 1817275970Scy extern int _xpg5_vsnprintf(char * __restrict, 1818275970Scy __SGI_LIBC_NAMESPACE_QUALIFIER size_t, 1819275970Scy const char * __restrict, /* va_list */ char *); 1820275970Scy 1821275970Scy r = _xpg5_vsnprintf(buf, buflen, format, ap); 1822275970Scy#else 1823275970Scy r = vsnprintf(buf, buflen, format, ap); 1824275970Scy#endif 1825275970Scy buf[buflen-1] = '\0'; 1826275970Scy return r; 1827275970Scy} 1828275970Scy 1829275970Scy#define USE_INTERNAL_NTOP 1830275970Scy#define USE_INTERNAL_PTON 1831275970Scy 1832275970Scyconst char * 1833275970Scyevutil_inet_ntop(int af, const void *src, char *dst, size_t len) 1834275970Scy{ 1835275970Scy#if defined(EVENT__HAVE_INET_NTOP) && !defined(USE_INTERNAL_NTOP) 1836275970Scy return inet_ntop(af, src, dst, len); 1837275970Scy#else 1838275970Scy if (af == AF_INET) { 1839275970Scy const struct in_addr *in = src; 1840275970Scy const ev_uint32_t a = ntohl(in->s_addr); 1841275970Scy int r; 1842275970Scy r = evutil_snprintf(dst, len, "%d.%d.%d.%d", 1843275970Scy (int)(ev_uint8_t)((a>>24)&0xff), 1844275970Scy (int)(ev_uint8_t)((a>>16)&0xff), 1845275970Scy (int)(ev_uint8_t)((a>>8 )&0xff), 1846275970Scy (int)(ev_uint8_t)((a )&0xff)); 1847275970Scy if (r<0||(size_t)r>=len) 1848275970Scy return NULL; 1849275970Scy else 1850275970Scy return dst; 1851275970Scy#ifdef AF_INET6 1852275970Scy } else if (af == AF_INET6) { 1853275970Scy const struct in6_addr *addr = src; 1854275970Scy char buf[64], *cp; 1855275970Scy int longestGapLen = 0, longestGapPos = -1, i, 1856275970Scy curGapPos = -1, curGapLen = 0; 1857275970Scy ev_uint16_t words[8]; 1858275970Scy for (i = 0; i < 8; ++i) { 1859275970Scy words[i] = 1860275970Scy (((ev_uint16_t)addr->s6_addr[2*i])<<8) + addr->s6_addr[2*i+1]; 1861275970Scy } 1862275970Scy if (words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && 1863275970Scy words[4] == 0 && ((words[5] == 0 && words[6] && words[7]) || 1864275970Scy (words[5] == 0xffff))) { 1865275970Scy /* This is an IPv4 address. */ 1866275970Scy if (words[5] == 0) { 1867275970Scy evutil_snprintf(buf, sizeof(buf), "::%d.%d.%d.%d", 1868275970Scy addr->s6_addr[12], addr->s6_addr[13], 1869275970Scy addr->s6_addr[14], addr->s6_addr[15]); 1870275970Scy } else { 1871275970Scy evutil_snprintf(buf, sizeof(buf), "::%x:%d.%d.%d.%d", words[5], 1872275970Scy addr->s6_addr[12], addr->s6_addr[13], 1873275970Scy addr->s6_addr[14], addr->s6_addr[15]); 1874275970Scy } 1875275970Scy if (strlen(buf) > len) 1876275970Scy return NULL; 1877275970Scy strlcpy(dst, buf, len); 1878275970Scy return dst; 1879275970Scy } 1880275970Scy i = 0; 1881275970Scy while (i < 8) { 1882275970Scy if (words[i] == 0) { 1883275970Scy curGapPos = i++; 1884275970Scy curGapLen = 1; 1885275970Scy while (i<8 && words[i] == 0) { 1886275970Scy ++i; ++curGapLen; 1887275970Scy } 1888275970Scy if (curGapLen > longestGapLen) { 1889275970Scy longestGapPos = curGapPos; 1890275970Scy longestGapLen = curGapLen; 1891275970Scy } 1892275970Scy } else { 1893275970Scy ++i; 1894275970Scy } 1895275970Scy } 1896275970Scy if (longestGapLen<=1) 1897275970Scy longestGapPos = -1; 1898275970Scy 1899275970Scy cp = buf; 1900275970Scy for (i = 0; i < 8; ++i) { 1901275970Scy if (words[i] == 0 && longestGapPos == i) { 1902275970Scy if (i == 0) 1903275970Scy *cp++ = ':'; 1904275970Scy *cp++ = ':'; 1905275970Scy while (i < 8 && words[i] == 0) 1906275970Scy ++i; 1907275970Scy --i; /* to compensate for loop increment. */ 1908275970Scy } else { 1909275970Scy evutil_snprintf(cp, 1910275970Scy sizeof(buf)-(cp-buf), "%x", (unsigned)words[i]); 1911275970Scy cp += strlen(cp); 1912275970Scy if (i != 7) 1913275970Scy *cp++ = ':'; 1914275970Scy } 1915275970Scy } 1916275970Scy *cp = '\0'; 1917275970Scy if (strlen(buf) > len) 1918275970Scy return NULL; 1919275970Scy strlcpy(dst, buf, len); 1920275970Scy return dst; 1921275970Scy#endif 1922275970Scy } else { 1923275970Scy return NULL; 1924275970Scy } 1925275970Scy#endif 1926275970Scy} 1927275970Scy 1928275970Scyint 1929275970Scyevutil_inet_pton(int af, const char *src, void *dst) 1930275970Scy{ 1931275970Scy#if defined(EVENT__HAVE_INET_PTON) && !defined(USE_INTERNAL_PTON) 1932275970Scy return inet_pton(af, src, dst); 1933275970Scy#else 1934275970Scy if (af == AF_INET) { 1935285612Sdelphij unsigned a,b,c,d; 1936275970Scy char more; 1937275970Scy struct in_addr *addr = dst; 1938285612Sdelphij if (sscanf(src, "%u.%u.%u.%u%c", &a,&b,&c,&d,&more) != 4) 1939275970Scy return 0; 1940285612Sdelphij if (a > 255) return 0; 1941285612Sdelphij if (b > 255) return 0; 1942285612Sdelphij if (c > 255) return 0; 1943285612Sdelphij if (d > 255) return 0; 1944275970Scy addr->s_addr = htonl((a<<24) | (b<<16) | (c<<8) | d); 1945275970Scy return 1; 1946275970Scy#ifdef AF_INET6 1947275970Scy } else if (af == AF_INET6) { 1948275970Scy struct in6_addr *out = dst; 1949275970Scy ev_uint16_t words[8]; 1950275970Scy int gapPos = -1, i, setWords=0; 1951275970Scy const char *dot = strchr(src, '.'); 1952275970Scy const char *eow; /* end of words. */ 1953275970Scy if (dot == src) 1954275970Scy return 0; 1955275970Scy else if (!dot) 1956275970Scy eow = src+strlen(src); 1957275970Scy else { 1958285612Sdelphij unsigned byte1,byte2,byte3,byte4; 1959275970Scy char more; 1960275970Scy for (eow = dot-1; eow >= src && EVUTIL_ISDIGIT_(*eow); --eow) 1961275970Scy ; 1962275970Scy ++eow; 1963275970Scy 1964275970Scy /* We use "scanf" because some platform inet_aton()s are too lax 1965275970Scy * about IPv4 addresses of the form "1.2.3" */ 1966285612Sdelphij if (sscanf(eow, "%u.%u.%u.%u%c", 1967275970Scy &byte1,&byte2,&byte3,&byte4,&more) != 4) 1968275970Scy return 0; 1969275970Scy 1970285612Sdelphij if (byte1 > 255 || 1971285612Sdelphij byte2 > 255 || 1972285612Sdelphij byte3 > 255 || 1973285612Sdelphij byte4 > 255) 1974275970Scy return 0; 1975275970Scy 1976275970Scy words[6] = (byte1<<8) | byte2; 1977275970Scy words[7] = (byte3<<8) | byte4; 1978275970Scy setWords += 2; 1979275970Scy } 1980275970Scy 1981275970Scy i = 0; 1982275970Scy while (src < eow) { 1983275970Scy if (i > 7) 1984275970Scy return 0; 1985275970Scy if (EVUTIL_ISXDIGIT_(*src)) { 1986275970Scy char *next; 1987275970Scy long r = strtol(src, &next, 16); 1988275970Scy if (next > 4+src) 1989275970Scy return 0; 1990275970Scy if (next == src) 1991275970Scy return 0; 1992275970Scy if (r<0 || r>65536) 1993275970Scy return 0; 1994275970Scy 1995275970Scy words[i++] = (ev_uint16_t)r; 1996275970Scy setWords++; 1997275970Scy src = next; 1998275970Scy if (*src != ':' && src != eow) 1999275970Scy return 0; 2000275970Scy ++src; 2001275970Scy } else if (*src == ':' && i > 0 && gapPos==-1) { 2002275970Scy gapPos = i; 2003275970Scy ++src; 2004275970Scy } else if (*src == ':' && i == 0 && src[1] == ':' && gapPos==-1) { 2005275970Scy gapPos = i; 2006275970Scy src += 2; 2007275970Scy } else { 2008275970Scy return 0; 2009275970Scy } 2010275970Scy } 2011275970Scy 2012275970Scy if (setWords > 8 || 2013275970Scy (setWords == 8 && gapPos != -1) || 2014275970Scy (setWords < 8 && gapPos == -1)) 2015275970Scy return 0; 2016275970Scy 2017275970Scy if (gapPos >= 0) { 2018275970Scy int nToMove = setWords - (dot ? 2 : 0) - gapPos; 2019275970Scy int gapLen = 8 - setWords; 2020275970Scy /* assert(nToMove >= 0); */ 2021275970Scy if (nToMove < 0) 2022275970Scy return -1; /* should be impossible */ 2023275970Scy memmove(&words[gapPos+gapLen], &words[gapPos], 2024275970Scy sizeof(ev_uint16_t)*nToMove); 2025275970Scy memset(&words[gapPos], 0, sizeof(ev_uint16_t)*gapLen); 2026275970Scy } 2027275970Scy for (i = 0; i < 8; ++i) { 2028275970Scy out->s6_addr[2*i ] = words[i] >> 8; 2029275970Scy out->s6_addr[2*i+1] = words[i] & 0xff; 2030275970Scy } 2031275970Scy 2032275970Scy return 1; 2033275970Scy#endif 2034275970Scy } else { 2035275970Scy return -1; 2036275970Scy } 2037275970Scy#endif 2038275970Scy} 2039275970Scy 2040275970Scyint 2041275970Scyevutil_parse_sockaddr_port(const char *ip_as_string, struct sockaddr *out, int *outlen) 2042275970Scy{ 2043275970Scy int port; 2044275970Scy char buf[128]; 2045275970Scy const char *cp, *addr_part, *port_part; 2046275970Scy int is_ipv6; 2047275970Scy /* recognized formats are: 2048275970Scy * [ipv6]:port 2049275970Scy * ipv6 2050275970Scy * [ipv6] 2051275970Scy * ipv4:port 2052275970Scy * ipv4 2053275970Scy */ 2054275970Scy 2055275970Scy cp = strchr(ip_as_string, ':'); 2056275970Scy if (*ip_as_string == '[') { 2057275970Scy int len; 2058275970Scy if (!(cp = strchr(ip_as_string, ']'))) { 2059275970Scy return -1; 2060275970Scy } 2061275970Scy len = (int) ( cp-(ip_as_string + 1) ); 2062275970Scy if (len > (int)sizeof(buf)-1) { 2063275970Scy return -1; 2064275970Scy } 2065275970Scy memcpy(buf, ip_as_string+1, len); 2066275970Scy buf[len] = '\0'; 2067275970Scy addr_part = buf; 2068275970Scy if (cp[1] == ':') 2069275970Scy port_part = cp+2; 2070275970Scy else 2071275970Scy port_part = NULL; 2072275970Scy is_ipv6 = 1; 2073275970Scy } else if (cp && strchr(cp+1, ':')) { 2074275970Scy is_ipv6 = 1; 2075275970Scy addr_part = ip_as_string; 2076275970Scy port_part = NULL; 2077275970Scy } else if (cp) { 2078275970Scy is_ipv6 = 0; 2079275970Scy if (cp - ip_as_string > (int)sizeof(buf)-1) { 2080275970Scy return -1; 2081275970Scy } 2082275970Scy memcpy(buf, ip_as_string, cp-ip_as_string); 2083275970Scy buf[cp-ip_as_string] = '\0'; 2084275970Scy addr_part = buf; 2085275970Scy port_part = cp+1; 2086275970Scy } else { 2087275970Scy addr_part = ip_as_string; 2088275970Scy port_part = NULL; 2089275970Scy is_ipv6 = 0; 2090275970Scy } 2091275970Scy 2092275970Scy if (port_part == NULL) { 2093275970Scy port = 0; 2094275970Scy } else { 2095275970Scy port = atoi(port_part); 2096275970Scy if (port <= 0 || port > 65535) { 2097275970Scy return -1; 2098275970Scy } 2099275970Scy } 2100275970Scy 2101275970Scy if (!addr_part) 2102275970Scy return -1; /* Should be impossible. */ 2103275970Scy#ifdef AF_INET6 2104275970Scy if (is_ipv6) 2105275970Scy { 2106275970Scy struct sockaddr_in6 sin6; 2107275970Scy memset(&sin6, 0, sizeof(sin6)); 2108275970Scy#ifdef EVENT__HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN 2109275970Scy sin6.sin6_len = sizeof(sin6); 2110275970Scy#endif 2111275970Scy sin6.sin6_family = AF_INET6; 2112275970Scy sin6.sin6_port = htons(port); 2113275970Scy if (1 != evutil_inet_pton(AF_INET6, addr_part, &sin6.sin6_addr)) 2114275970Scy return -1; 2115275970Scy if ((int)sizeof(sin6) > *outlen) 2116275970Scy return -1; 2117275970Scy memset(out, 0, *outlen); 2118275970Scy memcpy(out, &sin6, sizeof(sin6)); 2119275970Scy *outlen = sizeof(sin6); 2120275970Scy return 0; 2121275970Scy } 2122275970Scy else 2123275970Scy#endif 2124275970Scy { 2125275970Scy struct sockaddr_in sin; 2126275970Scy memset(&sin, 0, sizeof(sin)); 2127275970Scy#ifdef EVENT__HAVE_STRUCT_SOCKADDR_IN_SIN_LEN 2128275970Scy sin.sin_len = sizeof(sin); 2129275970Scy#endif 2130275970Scy sin.sin_family = AF_INET; 2131275970Scy sin.sin_port = htons(port); 2132275970Scy if (1 != evutil_inet_pton(AF_INET, addr_part, &sin.sin_addr)) 2133275970Scy return -1; 2134275970Scy if ((int)sizeof(sin) > *outlen) 2135275970Scy return -1; 2136275970Scy memset(out, 0, *outlen); 2137275970Scy memcpy(out, &sin, sizeof(sin)); 2138275970Scy *outlen = sizeof(sin); 2139275970Scy return 0; 2140275970Scy } 2141275970Scy} 2142275970Scy 2143275970Scyconst char * 2144275970Scyevutil_format_sockaddr_port_(const struct sockaddr *sa, char *out, size_t outlen) 2145275970Scy{ 2146275970Scy char b[128]; 2147275970Scy const char *res=NULL; 2148275970Scy int port; 2149275970Scy if (sa->sa_family == AF_INET) { 2150275970Scy const struct sockaddr_in *sin = (const struct sockaddr_in*)sa; 2151275970Scy res = evutil_inet_ntop(AF_INET, &sin->sin_addr,b,sizeof(b)); 2152275970Scy port = ntohs(sin->sin_port); 2153275970Scy if (res) { 2154275970Scy evutil_snprintf(out, outlen, "%s:%d", b, port); 2155275970Scy return out; 2156275970Scy } 2157275970Scy } else if (sa->sa_family == AF_INET6) { 2158275970Scy const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6*)sa; 2159275970Scy res = evutil_inet_ntop(AF_INET6, &sin6->sin6_addr,b,sizeof(b)); 2160275970Scy port = ntohs(sin6->sin6_port); 2161275970Scy if (res) { 2162275970Scy evutil_snprintf(out, outlen, "[%s]:%d", b, port); 2163275970Scy return out; 2164275970Scy } 2165275970Scy } 2166275970Scy 2167275970Scy evutil_snprintf(out, outlen, "<addr with socktype %d>", 2168275970Scy (int)sa->sa_family); 2169275970Scy return out; 2170275970Scy} 2171275970Scy 2172275970Scyint 2173275970Scyevutil_sockaddr_cmp(const struct sockaddr *sa1, const struct sockaddr *sa2, 2174275970Scy int include_port) 2175275970Scy{ 2176275970Scy int r; 2177275970Scy if (0 != (r = (sa1->sa_family - sa2->sa_family))) 2178275970Scy return r; 2179275970Scy 2180275970Scy if (sa1->sa_family == AF_INET) { 2181275970Scy const struct sockaddr_in *sin1, *sin2; 2182275970Scy sin1 = (const struct sockaddr_in *)sa1; 2183275970Scy sin2 = (const struct sockaddr_in *)sa2; 2184275970Scy if (sin1->sin_addr.s_addr < sin2->sin_addr.s_addr) 2185275970Scy return -1; 2186275970Scy else if (sin1->sin_addr.s_addr > sin2->sin_addr.s_addr) 2187275970Scy return 1; 2188275970Scy else if (include_port && 2189275970Scy (r = ((int)sin1->sin_port - (int)sin2->sin_port))) 2190275970Scy return r; 2191275970Scy else 2192275970Scy return 0; 2193275970Scy } 2194275970Scy#ifdef AF_INET6 2195275970Scy else if (sa1->sa_family == AF_INET6) { 2196275970Scy const struct sockaddr_in6 *sin1, *sin2; 2197275970Scy sin1 = (const struct sockaddr_in6 *)sa1; 2198275970Scy sin2 = (const struct sockaddr_in6 *)sa2; 2199275970Scy if ((r = memcmp(sin1->sin6_addr.s6_addr, sin2->sin6_addr.s6_addr, 16))) 2200275970Scy return r; 2201275970Scy else if (include_port && 2202275970Scy (r = ((int)sin1->sin6_port - (int)sin2->sin6_port))) 2203275970Scy return r; 2204275970Scy else 2205275970Scy return 0; 2206275970Scy } 2207275970Scy#endif 2208275970Scy return 1; 2209275970Scy} 2210275970Scy 2211275970Scy/* Tables to implement ctypes-replacement EVUTIL_IS*() functions. Each table 2212275970Scy * has 256 bits to look up whether a character is in some set or not. This 2213275970Scy * fails on non-ASCII platforms, but so does every other place where we 2214275970Scy * take a char and write it onto the network. 2215275970Scy **/ 2216275970Scystatic const ev_uint32_t EVUTIL_ISALPHA_TABLE[8] = 2217275970Scy { 0, 0, 0x7fffffe, 0x7fffffe, 0, 0, 0, 0 }; 2218275970Scystatic const ev_uint32_t EVUTIL_ISALNUM_TABLE[8] = 2219275970Scy { 0, 0x3ff0000, 0x7fffffe, 0x7fffffe, 0, 0, 0, 0 }; 2220275970Scystatic const ev_uint32_t EVUTIL_ISSPACE_TABLE[8] = { 0x3e00, 0x1, 0, 0, 0, 0, 0, 0 }; 2221275970Scystatic const ev_uint32_t EVUTIL_ISXDIGIT_TABLE[8] = 2222275970Scy { 0, 0x3ff0000, 0x7e, 0x7e, 0, 0, 0, 0 }; 2223275970Scystatic const ev_uint32_t EVUTIL_ISDIGIT_TABLE[8] = { 0, 0x3ff0000, 0, 0, 0, 0, 0, 0 }; 2224275970Scystatic const ev_uint32_t EVUTIL_ISPRINT_TABLE[8] = 2225275970Scy { 0, 0xffffffff, 0xffffffff, 0x7fffffff, 0, 0, 0, 0x0 }; 2226275970Scystatic const ev_uint32_t EVUTIL_ISUPPER_TABLE[8] = { 0, 0, 0x7fffffe, 0, 0, 0, 0, 0 }; 2227275970Scystatic const ev_uint32_t EVUTIL_ISLOWER_TABLE[8] = { 0, 0, 0, 0x7fffffe, 0, 0, 0, 0 }; 2228275970Scy/* Upper-casing and lowercasing tables to map characters to upper/lowercase 2229275970Scy * equivalents. */ 2230275970Scystatic const unsigned char EVUTIL_TOUPPER_TABLE[256] = { 2231275970Scy 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 2232275970Scy 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, 2233275970Scy 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, 2234275970Scy 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63, 2235275970Scy 64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79, 2236275970Scy 80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95, 2237275970Scy 96,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79, 2238275970Scy 80,81,82,83,84,85,86,87,88,89,90,123,124,125,126,127, 2239275970Scy 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, 2240275970Scy 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, 2241275970Scy 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, 2242275970Scy 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, 2243275970Scy 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, 2244275970Scy 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, 2245275970Scy 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, 2246275970Scy 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255, 2247275970Scy}; 2248275970Scystatic const unsigned char EVUTIL_TOLOWER_TABLE[256] = { 2249275970Scy 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 2250275970Scy 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, 2251275970Scy 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, 2252275970Scy 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63, 2253275970Scy 64,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111, 2254275970Scy 112,113,114,115,116,117,118,119,120,121,122,91,92,93,94,95, 2255275970Scy 96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111, 2256275970Scy 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, 2257275970Scy 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, 2258275970Scy 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, 2259275970Scy 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, 2260275970Scy 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, 2261275970Scy 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, 2262275970Scy 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, 2263275970Scy 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, 2264275970Scy 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255, 2265275970Scy}; 2266275970Scy 2267275970Scy#define IMPL_CTYPE_FN(name) \ 2268275970Scy int EVUTIL_##name##_(char c) { \ 2269275970Scy ev_uint8_t u = c; \ 2270275970Scy return !!(EVUTIL_##name##_TABLE[(u >> 5) & 7] & (1 << (u & 31))); \ 2271275970Scy } 2272275970ScyIMPL_CTYPE_FN(ISALPHA) 2273275970ScyIMPL_CTYPE_FN(ISALNUM) 2274275970ScyIMPL_CTYPE_FN(ISSPACE) 2275275970ScyIMPL_CTYPE_FN(ISDIGIT) 2276275970ScyIMPL_CTYPE_FN(ISXDIGIT) 2277275970ScyIMPL_CTYPE_FN(ISPRINT) 2278275970ScyIMPL_CTYPE_FN(ISLOWER) 2279275970ScyIMPL_CTYPE_FN(ISUPPER) 2280275970Scy 2281275970Scychar EVUTIL_TOLOWER_(char c) 2282275970Scy{ 2283275970Scy return ((char)EVUTIL_TOLOWER_TABLE[(ev_uint8_t)c]); 2284275970Scy} 2285275970Scychar EVUTIL_TOUPPER_(char c) 2286275970Scy{ 2287275970Scy return ((char)EVUTIL_TOUPPER_TABLE[(ev_uint8_t)c]); 2288275970Scy} 2289275970Scyint 2290275970Scyevutil_ascii_strcasecmp(const char *s1, const char *s2) 2291275970Scy{ 2292275970Scy char c1, c2; 2293275970Scy while (1) { 2294275970Scy c1 = EVUTIL_TOLOWER_(*s1++); 2295275970Scy c2 = EVUTIL_TOLOWER_(*s2++); 2296275970Scy if (c1 < c2) 2297275970Scy return -1; 2298275970Scy else if (c1 > c2) 2299275970Scy return 1; 2300275970Scy else if (c1 == 0) 2301275970Scy return 0; 2302275970Scy } 2303275970Scy} 2304275970Scyint evutil_ascii_strncasecmp(const char *s1, const char *s2, size_t n) 2305275970Scy{ 2306275970Scy char c1, c2; 2307275970Scy while (n--) { 2308275970Scy c1 = EVUTIL_TOLOWER_(*s1++); 2309275970Scy c2 = EVUTIL_TOLOWER_(*s2++); 2310275970Scy if (c1 < c2) 2311275970Scy return -1; 2312275970Scy else if (c1 > c2) 2313275970Scy return 1; 2314275970Scy else if (c1 == 0) 2315275970Scy return 0; 2316275970Scy } 2317275970Scy return 0; 2318275970Scy} 2319275970Scy 2320275970Scyvoid 2321275970Scyevutil_rtrim_lws_(char *str) 2322275970Scy{ 2323275970Scy char *cp; 2324275970Scy 2325275970Scy if (str == NULL) 2326275970Scy return; 2327275970Scy 2328275970Scy if ((cp = strchr(str, '\0')) == NULL || (cp == str)) 2329275970Scy return; 2330275970Scy 2331275970Scy --cp; 2332275970Scy 2333275970Scy while (*cp == ' ' || *cp == '\t') { 2334275970Scy *cp = '\0'; 2335275970Scy if (cp == str) 2336275970Scy break; 2337275970Scy --cp; 2338275970Scy } 2339275970Scy} 2340275970Scy 2341275970Scystatic int 2342275970Scyevutil_issetugid(void) 2343275970Scy{ 2344275970Scy#ifdef EVENT__HAVE_ISSETUGID 2345275970Scy return issetugid(); 2346275970Scy#else 2347275970Scy 2348275970Scy#ifdef EVENT__HAVE_GETEUID 2349275970Scy if (getuid() != geteuid()) 2350275970Scy return 1; 2351275970Scy#endif 2352275970Scy#ifdef EVENT__HAVE_GETEGID 2353275970Scy if (getgid() != getegid()) 2354275970Scy return 1; 2355275970Scy#endif 2356275970Scy return 0; 2357275970Scy#endif 2358275970Scy} 2359275970Scy 2360275970Scyconst char * 2361275970Scyevutil_getenv_(const char *varname) 2362275970Scy{ 2363275970Scy if (evutil_issetugid()) 2364275970Scy return NULL; 2365275970Scy 2366275970Scy return getenv(varname); 2367275970Scy} 2368275970Scy 2369275970Scyev_uint32_t 2370275970Scyevutil_weakrand_seed_(struct evutil_weakrand_state *state, ev_uint32_t seed) 2371275970Scy{ 2372275970Scy if (seed == 0) { 2373275970Scy struct timeval tv; 2374275970Scy evutil_gettimeofday(&tv, NULL); 2375275970Scy seed = (ev_uint32_t)tv.tv_sec + (ev_uint32_t)tv.tv_usec; 2376275970Scy#ifdef _WIN32 2377275970Scy seed += (ev_uint32_t) _getpid(); 2378275970Scy#else 2379275970Scy seed += (ev_uint32_t) getpid(); 2380275970Scy#endif 2381275970Scy } 2382275970Scy state->seed = seed; 2383275970Scy return seed; 2384275970Scy} 2385275970Scy 2386275970Scyev_int32_t 2387275970Scyevutil_weakrand_(struct evutil_weakrand_state *state) 2388275970Scy{ 2389275970Scy /* This RNG implementation is a linear congruential generator, with 2390275970Scy * modulus 2^31, multiplier 1103515245, and addend 12345. It's also 2391275970Scy * used by OpenBSD, and by Glibc's TYPE_0 RNG. 2392275970Scy * 2393275970Scy * The linear congruential generator is not an industrial-strength 2394275970Scy * RNG! It's fast, but it can have higher-order patterns. Notably, 2395275970Scy * the low bits tend to have periodicity. 2396275970Scy */ 2397275970Scy state->seed = ((state->seed) * 1103515245 + 12345) & 0x7fffffff; 2398275970Scy return (ev_int32_t)(state->seed); 2399275970Scy} 2400275970Scy 2401275970Scyev_int32_t 2402275970Scyevutil_weakrand_range_(struct evutil_weakrand_state *state, ev_int32_t top) 2403275970Scy{ 2404275970Scy ev_int32_t divisor, result; 2405275970Scy 2406275970Scy /* We can't just do weakrand() % top, since the low bits of the LCG 2407275970Scy * are less random than the high ones. (Specifically, since the LCG 2408275970Scy * modulus is 2^N, every 2^m for m<N will divide the modulus, and so 2409275970Scy * therefore the low m bits of the LCG will have period 2^m.) */ 2410275970Scy divisor = EVUTIL_WEAKRAND_MAX / top; 2411275970Scy do { 2412275970Scy result = evutil_weakrand_(state) / divisor; 2413275970Scy } while (result >= top); 2414275970Scy return result; 2415275970Scy} 2416275970Scy 2417275970Scy/** 2418275970Scy * Volatile pointer to memset: we use this to keep the compiler from 2419275970Scy * eliminating our call to memset. 2420275970Scy */ 2421275970Scyvoid * (*volatile evutil_memset_volatile_)(void *, int, size_t) = memset; 2422275970Scy 2423275970Scyvoid 2424275970Scyevutil_memclear_(void *mem, size_t len) 2425275970Scy{ 2426275970Scy evutil_memset_volatile_(mem, 0, len); 2427275970Scy} 2428275970Scy 2429275970Scyint 2430275970Scyevutil_sockaddr_is_loopback_(const struct sockaddr *addr) 2431275970Scy{ 2432275970Scy static const char LOOPBACK_S6[16] = 2433275970Scy "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1"; 2434275970Scy if (addr->sa_family == AF_INET) { 2435275970Scy struct sockaddr_in *sin = (struct sockaddr_in *)addr; 2436275970Scy return (ntohl(sin->sin_addr.s_addr) & 0xff000000) == 0x7f000000; 2437275970Scy } else if (addr->sa_family == AF_INET6) { 2438275970Scy struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr; 2439275970Scy return !memcmp(sin6->sin6_addr.s6_addr, LOOPBACK_S6, 16); 2440275970Scy } 2441275970Scy return 0; 2442275970Scy} 2443275970Scy 2444275970Scyint 2445275970Scyevutil_hex_char_to_int_(char c) 2446275970Scy{ 2447275970Scy switch(c) 2448275970Scy { 2449275970Scy case '0': return 0; 2450275970Scy case '1': return 1; 2451275970Scy case '2': return 2; 2452275970Scy case '3': return 3; 2453275970Scy case '4': return 4; 2454275970Scy case '5': return 5; 2455275970Scy case '6': return 6; 2456275970Scy case '7': return 7; 2457275970Scy case '8': return 8; 2458275970Scy case '9': return 9; 2459275970Scy case 'A': case 'a': return 10; 2460275970Scy case 'B': case 'b': return 11; 2461275970Scy case 'C': case 'c': return 12; 2462275970Scy case 'D': case 'd': return 13; 2463275970Scy case 'E': case 'e': return 14; 2464275970Scy case 'F': case 'f': return 15; 2465275970Scy } 2466275970Scy return -1; 2467275970Scy} 2468275970Scy 2469275970Scy#ifdef _WIN32 2470285612SdelphijHMODULE 2471275970Scyevutil_load_windows_system_library_(const TCHAR *library_name) 2472275970Scy{ 2473275970Scy TCHAR path[MAX_PATH]; 2474275970Scy unsigned n; 2475275970Scy n = GetSystemDirectory(path, MAX_PATH); 2476275970Scy if (n == 0 || n + _tcslen(library_name) + 2 >= MAX_PATH) 2477275970Scy return 0; 2478275970Scy _tcscat(path, TEXT("\\")); 2479275970Scy _tcscat(path, library_name); 2480275970Scy return LoadLibrary(path); 2481275970Scy} 2482275970Scy#endif 2483275970Scy 2484275970Scy/* Internal wrapper around 'socket' to provide Linux-style support for 2485275970Scy * syscall-saving methods where available. 2486275970Scy * 2487275970Scy * In addition to regular socket behavior, you can use a bitwise or to set the 2488275970Scy * flags EVUTIL_SOCK_NONBLOCK and EVUTIL_SOCK_CLOEXEC in the 'type' argument, 2489275970Scy * to make the socket nonblocking or close-on-exec with as few syscalls as 2490275970Scy * possible. 2491275970Scy */ 2492275970Scyevutil_socket_t 2493275970Scyevutil_socket_(int domain, int type, int protocol) 2494275970Scy{ 2495275970Scy evutil_socket_t r; 2496275970Scy#if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC) 2497275970Scy r = socket(domain, type, protocol); 2498275970Scy if (r >= 0) 2499275970Scy return r; 2500275970Scy else if ((type & (SOCK_NONBLOCK|SOCK_CLOEXEC)) == 0) 2501275970Scy return -1; 2502275970Scy#endif 2503275970Scy#define SOCKET_TYPE_MASK (~(EVUTIL_SOCK_NONBLOCK|EVUTIL_SOCK_CLOEXEC)) 2504275970Scy r = socket(domain, type & SOCKET_TYPE_MASK, protocol); 2505275970Scy if (r < 0) 2506275970Scy return -1; 2507275970Scy if (type & EVUTIL_SOCK_NONBLOCK) { 2508275970Scy if (evutil_fast_socket_nonblocking(r) < 0) { 2509275970Scy evutil_closesocket(r); 2510275970Scy return -1; 2511275970Scy } 2512275970Scy } 2513275970Scy if (type & EVUTIL_SOCK_CLOEXEC) { 2514275970Scy if (evutil_fast_socket_closeonexec(r) < 0) { 2515275970Scy evutil_closesocket(r); 2516275970Scy return -1; 2517275970Scy } 2518275970Scy } 2519275970Scy return r; 2520275970Scy} 2521275970Scy 2522275970Scy/* Internal wrapper around 'accept' or 'accept4' to provide Linux-style 2523275970Scy * support for syscall-saving methods where available. 2524275970Scy * 2525275970Scy * In addition to regular accept behavior, you can set one or more of flags 2526275970Scy * EVUTIL_SOCK_NONBLOCK and EVUTIL_SOCK_CLOEXEC in the 'flags' argument, to 2527275970Scy * make the socket nonblocking or close-on-exec with as few syscalls as 2528275970Scy * possible. 2529275970Scy */ 2530275970Scyevutil_socket_t 2531275970Scyevutil_accept4_(evutil_socket_t sockfd, struct sockaddr *addr, 2532275970Scy ev_socklen_t *addrlen, int flags) 2533275970Scy{ 2534275970Scy evutil_socket_t result; 2535275970Scy#if defined(EVENT__HAVE_ACCEPT4) && defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK) 2536275970Scy result = accept4(sockfd, addr, addrlen, flags); 2537275970Scy if (result >= 0 || (errno != EINVAL && errno != ENOSYS)) { 2538275970Scy /* A nonnegative result means that we succeeded, so return. 2539275970Scy * Failing with EINVAL means that an option wasn't supported, 2540275970Scy * and failing with ENOSYS means that the syscall wasn't 2541275970Scy * there: in those cases we want to fall back. Otherwise, we 2542275970Scy * got a real error, and we should return. */ 2543275970Scy return result; 2544275970Scy } 2545275970Scy#endif 2546275970Scy result = accept(sockfd, addr, addrlen); 2547275970Scy if (result < 0) 2548275970Scy return result; 2549275970Scy 2550275970Scy if (flags & EVUTIL_SOCK_CLOEXEC) { 2551275970Scy if (evutil_fast_socket_closeonexec(result) < 0) { 2552275970Scy evutil_closesocket(result); 2553275970Scy return -1; 2554275970Scy } 2555275970Scy } 2556275970Scy if (flags & EVUTIL_SOCK_NONBLOCK) { 2557275970Scy if (evutil_fast_socket_nonblocking(result) < 0) { 2558275970Scy evutil_closesocket(result); 2559275970Scy return -1; 2560275970Scy } 2561275970Scy } 2562275970Scy return result; 2563275970Scy} 2564275970Scy 2565275970Scy/* Internal function: Set fd[0] and fd[1] to a pair of fds such that writes on 2566275970Scy * fd[0] get read from fd[1]. Make both fds nonblocking and close-on-exec. 2567275970Scy * Return 0 on success, -1 on failure. 2568275970Scy */ 2569275970Scyint 2570275970Scyevutil_make_internal_pipe_(evutil_socket_t fd[2]) 2571275970Scy{ 2572275970Scy /* 2573275970Scy Making the second socket nonblocking is a bit subtle, given that we 2574275970Scy ignore any EAGAIN returns when writing to it, and you don't usally 2575275970Scy do that for a nonblocking socket. But if the kernel gives us EAGAIN, 2576275970Scy then there's no need to add any more data to the buffer, since 2577275970Scy the main thread is already either about to wake up and drain it, 2578275970Scy or woken up and in the process of draining it. 2579275970Scy */ 2580275970Scy 2581275970Scy#if defined(EVENT__HAVE_PIPE2) 2582275970Scy if (pipe2(fd, O_NONBLOCK|O_CLOEXEC) == 0) 2583275970Scy return 0; 2584275970Scy#endif 2585275970Scy#if defined(EVENT__HAVE_PIPE) 2586275970Scy if (pipe(fd) == 0) { 2587275970Scy if (evutil_fast_socket_nonblocking(fd[0]) < 0 || 2588275970Scy evutil_fast_socket_nonblocking(fd[1]) < 0 || 2589275970Scy evutil_fast_socket_closeonexec(fd[0]) < 0 || 2590275970Scy evutil_fast_socket_closeonexec(fd[1]) < 0) { 2591275970Scy close(fd[0]); 2592275970Scy close(fd[1]); 2593275970Scy fd[0] = fd[1] = -1; 2594275970Scy return -1; 2595275970Scy } 2596275970Scy return 0; 2597275970Scy } else { 2598275970Scy event_warn("%s: pipe", __func__); 2599275970Scy } 2600275970Scy#endif 2601275970Scy 2602275970Scy#ifdef _WIN32 2603275970Scy#define LOCAL_SOCKETPAIR_AF AF_INET 2604275970Scy#else 2605275970Scy#define LOCAL_SOCKETPAIR_AF AF_UNIX 2606275970Scy#endif 2607275970Scy if (evutil_socketpair(LOCAL_SOCKETPAIR_AF, SOCK_STREAM, 0, fd) == 0) { 2608275970Scy if (evutil_fast_socket_nonblocking(fd[0]) < 0 || 2609275970Scy evutil_fast_socket_nonblocking(fd[1]) < 0 || 2610275970Scy evutil_fast_socket_closeonexec(fd[0]) < 0 || 2611275970Scy evutil_fast_socket_closeonexec(fd[1]) < 0) { 2612275970Scy evutil_closesocket(fd[0]); 2613275970Scy evutil_closesocket(fd[1]); 2614275970Scy fd[0] = fd[1] = -1; 2615275970Scy return -1; 2616275970Scy } 2617275970Scy return 0; 2618275970Scy } 2619275970Scy fd[0] = fd[1] = -1; 2620275970Scy return -1; 2621275970Scy} 2622275970Scy 2623275970Scy/* Wrapper around eventfd on systems that provide it. Unlike the system 2624275970Scy * eventfd, it always supports EVUTIL_EFD_CLOEXEC and EVUTIL_EFD_NONBLOCK as 2625275970Scy * flags. Returns -1 on error or if eventfd is not supported. 2626275970Scy */ 2627275970Scyevutil_socket_t 2628275970Scyevutil_eventfd_(unsigned initval, int flags) 2629275970Scy{ 2630275970Scy#if defined(EVENT__HAVE_EVENTFD) && defined(EVENT__HAVE_SYS_EVENTFD_H) 2631275970Scy int r; 2632275970Scy#if defined(EFD_CLOEXEC) && defined(EFD_NONBLOCK) 2633275970Scy r = eventfd(initval, flags); 2634275970Scy if (r >= 0 || flags == 0) 2635275970Scy return r; 2636275970Scy#endif 2637275970Scy r = eventfd(initval, 0); 2638275970Scy if (r < 0) 2639275970Scy return r; 2640275970Scy if (flags & EVUTIL_EFD_CLOEXEC) { 2641275970Scy if (evutil_fast_socket_closeonexec(r) < 0) { 2642275970Scy evutil_closesocket(r); 2643275970Scy return -1; 2644275970Scy } 2645275970Scy } 2646275970Scy if (flags & EVUTIL_EFD_NONBLOCK) { 2647275970Scy if (evutil_fast_socket_nonblocking(r) < 0) { 2648275970Scy evutil_closesocket(r); 2649275970Scy return -1; 2650275970Scy } 2651275970Scy } 2652275970Scy return r; 2653275970Scy#else 2654275970Scy return -1; 2655275970Scy#endif 2656275970Scy} 2657275970Scy 2658275970Scyvoid 2659275970Scyevutil_free_globals_(void) 2660275970Scy{ 2661275970Scy evutil_free_secure_rng_globals_(); 2662275970Scy evutil_free_sock_err_globals(); 2663275970Scy} 2664