1290001Sglebius/* 2290001Sglebius * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson 3290001Sglebius * 4290001Sglebius * Redistribution and use in source and binary forms, with or without 5290001Sglebius * modification, are permitted provided that the following conditions 6290001Sglebius * are met: 7290001Sglebius * 1. Redistributions of source code must retain the above copyright 8290001Sglebius * notice, this list of conditions and the following disclaimer. 9290001Sglebius * 2. Redistributions in binary form must reproduce the above copyright 10290001Sglebius * notice, this list of conditions and the following disclaimer in the 11290001Sglebius * documentation and/or other materials provided with the distribution. 12290001Sglebius * 3. The name of the author may not be used to endorse or promote products 13290001Sglebius * derived from this software without specific prior written permission. 14290001Sglebius * 15290001Sglebius * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16290001Sglebius * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17290001Sglebius * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18290001Sglebius * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19290001Sglebius * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20290001Sglebius * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21290001Sglebius * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22290001Sglebius * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23290001Sglebius * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24290001Sglebius * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25290001Sglebius */ 26290001Sglebius 27290001Sglebius#include "event2/event-config.h" 28290001Sglebius#include "evconfig-private.h" 29290001Sglebius 30290001Sglebius#ifdef _WIN32 31290001Sglebius#include <winsock2.h> 32290001Sglebius#include <ws2tcpip.h> 33290001Sglebius#define WIN32_LEAN_AND_MEAN 34290001Sglebius#include <windows.h> 35290001Sglebius#undef WIN32_LEAN_AND_MEAN 36290001Sglebius#include <io.h> 37290001Sglebius#include <tchar.h> 38290001Sglebius#include <process.h> 39290001Sglebius#undef _WIN32_WINNT 40290001Sglebius/* For structs needed by GetAdaptersAddresses */ 41290001Sglebius#define _WIN32_WINNT 0x0501 42290001Sglebius#include <iphlpapi.h> 43290001Sglebius#endif 44290001Sglebius 45290001Sglebius#include <sys/types.h> 46290001Sglebius#ifdef EVENT__HAVE_SYS_SOCKET_H 47290001Sglebius#include <sys/socket.h> 48290001Sglebius#endif 49290001Sglebius#ifdef EVENT__HAVE_UNISTD_H 50290001Sglebius#include <unistd.h> 51290001Sglebius#endif 52290001Sglebius#ifdef EVENT__HAVE_FCNTL_H 53290001Sglebius#include <fcntl.h> 54290001Sglebius#endif 55290001Sglebius#ifdef EVENT__HAVE_STDLIB_H 56290001Sglebius#include <stdlib.h> 57290001Sglebius#endif 58290001Sglebius#include <errno.h> 59290001Sglebius#include <limits.h> 60290001Sglebius#include <stdio.h> 61290001Sglebius#include <string.h> 62290001Sglebius#ifdef EVENT__HAVE_NETINET_IN_H 63290001Sglebius#include <netinet/in.h> 64290001Sglebius#endif 65290001Sglebius#ifdef EVENT__HAVE_NETINET_IN6_H 66290001Sglebius#include <netinet/in6.h> 67290001Sglebius#endif 68290001Sglebius#ifdef EVENT__HAVE_NETINET_TCP_H 69290001Sglebius#include <netinet/tcp.h> 70290001Sglebius#endif 71290001Sglebius#ifdef EVENT__HAVE_ARPA_INET_H 72290001Sglebius#include <arpa/inet.h> 73290001Sglebius#endif 74290001Sglebius#include <time.h> 75290001Sglebius#include <sys/stat.h> 76290001Sglebius#ifdef EVENT__HAVE_IFADDRS_H 77290001Sglebius#include <ifaddrs.h> 78290001Sglebius#endif 79290001Sglebius 80290001Sglebius#include "event2/util.h" 81290001Sglebius#include "util-internal.h" 82290001Sglebius#include "log-internal.h" 83290001Sglebius#include "mm-internal.h" 84290001Sglebius#include "evthread-internal.h" 85290001Sglebius 86290001Sglebius#include "strlcpy-internal.h" 87290001Sglebius#include "ipv6-internal.h" 88290001Sglebius 89290001Sglebius#ifdef _WIN32 90290001Sglebius#define HT_NO_CACHE_HASH_VALUES 91290001Sglebius#include "ht-internal.h" 92290001Sglebius#define open _open 93290001Sglebius#define read _read 94290001Sglebius#define close _close 95290001Sglebius#ifndef fstat 96290001Sglebius#define fstat _fstati64 97290001Sglebius#endif 98290001Sglebius#ifndef stat 99290001Sglebius#define stat _stati64 100290001Sglebius#endif 101290001Sglebius#define mode_t int 102290001Sglebius#endif 103290001Sglebius 104290001Sglebiusint 105290001Sglebiusevutil_open_closeonexec_(const char *pathname, int flags, unsigned mode) 106290001Sglebius{ 107290001Sglebius int fd; 108290001Sglebius 109290001Sglebius#ifdef O_CLOEXEC 110290001Sglebius fd = open(pathname, flags|O_CLOEXEC, (mode_t)mode); 111290001Sglebius if (fd >= 0 || errno == EINVAL) 112290001Sglebius return fd; 113290001Sglebius /* If we got an EINVAL, fall through and try without O_CLOEXEC */ 114290001Sglebius#endif 115290001Sglebius fd = open(pathname, flags, (mode_t)mode); 116290001Sglebius if (fd < 0) 117290001Sglebius return -1; 118290001Sglebius 119290001Sglebius#if defined(FD_CLOEXEC) 120290001Sglebius if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) { 121290001Sglebius close(fd); 122290001Sglebius return -1; 123290001Sglebius } 124290001Sglebius#endif 125290001Sglebius 126290001Sglebius return fd; 127290001Sglebius} 128290001Sglebius 129290001Sglebius/** 130290001Sglebius Read the contents of 'filename' into a newly allocated NUL-terminated 131290001Sglebius string. Set *content_out to hold this string, and *len_out to hold its 132290001Sglebius length (not including the appended NUL). If 'is_binary', open the file in 133290001Sglebius binary mode. 134290001Sglebius 135290001Sglebius Returns 0 on success, -1 if the open fails, and -2 for all other failures. 136290001Sglebius 137290001Sglebius Used internally only; may go away in a future version. 138290001Sglebius */ 139290001Sglebiusint 140290001Sglebiusevutil_read_file_(const char *filename, char **content_out, size_t *len_out, 141290001Sglebius int is_binary) 142290001Sglebius{ 143290001Sglebius int fd, r; 144290001Sglebius struct stat st; 145290001Sglebius char *mem; 146290001Sglebius size_t read_so_far=0; 147290001Sglebius int mode = O_RDONLY; 148290001Sglebius 149290001Sglebius EVUTIL_ASSERT(content_out); 150290001Sglebius EVUTIL_ASSERT(len_out); 151290001Sglebius *content_out = NULL; 152290001Sglebius *len_out = 0; 153290001Sglebius 154290001Sglebius#ifdef O_BINARY 155290001Sglebius if (is_binary) 156290001Sglebius mode |= O_BINARY; 157290001Sglebius#endif 158290001Sglebius 159290001Sglebius fd = evutil_open_closeonexec_(filename, mode, 0); 160290001Sglebius if (fd < 0) 161290001Sglebius return -1; 162290001Sglebius if (fstat(fd, &st) || st.st_size < 0 || 163290001Sglebius st.st_size > EV_SSIZE_MAX-1 ) { 164290001Sglebius close(fd); 165290001Sglebius return -2; 166290001Sglebius } 167290001Sglebius mem = mm_malloc((size_t)st.st_size + 1); 168290001Sglebius if (!mem) { 169290001Sglebius close(fd); 170290001Sglebius return -2; 171290001Sglebius } 172290001Sglebius read_so_far = 0; 173290001Sglebius#ifdef _WIN32 174290001Sglebius#define N_TO_READ(x) ((x) > INT_MAX) ? INT_MAX : ((int)(x)) 175290001Sglebius#else 176290001Sglebius#define N_TO_READ(x) (x) 177290001Sglebius#endif 178290001Sglebius while ((r = read(fd, mem+read_so_far, N_TO_READ(st.st_size - read_so_far))) > 0) { 179290001Sglebius read_so_far += r; 180290001Sglebius if (read_so_far >= (size_t)st.st_size) 181290001Sglebius break; 182290001Sglebius EVUTIL_ASSERT(read_so_far < (size_t)st.st_size); 183290001Sglebius } 184290001Sglebius close(fd); 185290001Sglebius if (r < 0) { 186290001Sglebius mm_free(mem); 187290001Sglebius return -2; 188290001Sglebius } 189290001Sglebius mem[read_so_far] = 0; 190290001Sglebius 191290001Sglebius *len_out = read_so_far; 192290001Sglebius *content_out = mem; 193290001Sglebius return 0; 194290001Sglebius} 195290001Sglebius 196290001Sglebiusint 197290001Sglebiusevutil_socketpair(int family, int type, int protocol, evutil_socket_t fd[2]) 198290001Sglebius{ 199290001Sglebius#ifndef _WIN32 200290001Sglebius return socketpair(family, type, protocol, fd); 201290001Sglebius#else 202290001Sglebius return evutil_ersatz_socketpair_(family, type, protocol, fd); 203290001Sglebius#endif 204290001Sglebius} 205290001Sglebius 206290001Sglebiusint 207290001Sglebiusevutil_ersatz_socketpair_(int family, int type, int protocol, 208290001Sglebius evutil_socket_t fd[2]) 209290001Sglebius{ 210290001Sglebius /* This code is originally from Tor. Used with permission. */ 211290001Sglebius 212290001Sglebius /* This socketpair does not work when localhost is down. So 213290001Sglebius * it's really not the same thing at all. But it's close enough 214290001Sglebius * for now, and really, when localhost is down sometimes, we 215290001Sglebius * have other problems too. 216290001Sglebius */ 217290001Sglebius#ifdef _WIN32 218290001Sglebius#define ERR(e) WSA##e 219290001Sglebius#else 220290001Sglebius#define ERR(e) e 221290001Sglebius#endif 222290001Sglebius evutil_socket_t listener = -1; 223290001Sglebius evutil_socket_t connector = -1; 224290001Sglebius evutil_socket_t acceptor = -1; 225290001Sglebius struct sockaddr_in listen_addr; 226290001Sglebius struct sockaddr_in connect_addr; 227290001Sglebius ev_socklen_t size; 228290001Sglebius int saved_errno = -1; 229290001Sglebius 230290001Sglebius if (protocol 231290001Sglebius || (family != AF_INET 232290001Sglebius#ifdef AF_UNIX 233290001Sglebius && family != AF_UNIX 234290001Sglebius#endif 235290001Sglebius )) { 236290001Sglebius EVUTIL_SET_SOCKET_ERROR(ERR(EAFNOSUPPORT)); 237290001Sglebius return -1; 238290001Sglebius } 239290001Sglebius if (!fd) { 240290001Sglebius EVUTIL_SET_SOCKET_ERROR(ERR(EINVAL)); 241290001Sglebius return -1; 242290001Sglebius } 243290001Sglebius 244290001Sglebius listener = socket(AF_INET, type, 0); 245290001Sglebius if (listener < 0) 246290001Sglebius return -1; 247290001Sglebius memset(&listen_addr, 0, sizeof(listen_addr)); 248290001Sglebius listen_addr.sin_family = AF_INET; 249290001Sglebius listen_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 250290001Sglebius listen_addr.sin_port = 0; /* kernel chooses port. */ 251290001Sglebius if (bind(listener, (struct sockaddr *) &listen_addr, sizeof (listen_addr)) 252290001Sglebius == -1) 253290001Sglebius goto tidy_up_and_fail; 254290001Sglebius if (listen(listener, 1) == -1) 255290001Sglebius goto tidy_up_and_fail; 256290001Sglebius 257290001Sglebius connector = socket(AF_INET, type, 0); 258290001Sglebius if (connector < 0) 259290001Sglebius goto tidy_up_and_fail; 260290001Sglebius /* We want to find out the port number to connect to. */ 261290001Sglebius size = sizeof(connect_addr); 262290001Sglebius if (getsockname(listener, (struct sockaddr *) &connect_addr, &size) == -1) 263290001Sglebius goto tidy_up_and_fail; 264290001Sglebius if (size != sizeof (connect_addr)) 265290001Sglebius goto abort_tidy_up_and_fail; 266290001Sglebius if (connect(connector, (struct sockaddr *) &connect_addr, 267290001Sglebius sizeof(connect_addr)) == -1) 268290001Sglebius goto tidy_up_and_fail; 269290001Sglebius 270290001Sglebius size = sizeof(listen_addr); 271290001Sglebius acceptor = accept(listener, (struct sockaddr *) &listen_addr, &size); 272290001Sglebius if (acceptor < 0) 273290001Sglebius goto tidy_up_and_fail; 274290001Sglebius if (size != sizeof(listen_addr)) 275290001Sglebius goto abort_tidy_up_and_fail; 276290001Sglebius /* Now check we are talking to ourself by matching port and host on the 277290001Sglebius two sockets. */ 278290001Sglebius if (getsockname(connector, (struct sockaddr *) &connect_addr, &size) == -1) 279290001Sglebius goto tidy_up_and_fail; 280290001Sglebius if (size != sizeof (connect_addr) 281290001Sglebius || listen_addr.sin_family != connect_addr.sin_family 282290001Sglebius || listen_addr.sin_addr.s_addr != connect_addr.sin_addr.s_addr 283290001Sglebius || listen_addr.sin_port != connect_addr.sin_port) 284290001Sglebius goto abort_tidy_up_and_fail; 285290001Sglebius evutil_closesocket(listener); 286290001Sglebius fd[0] = connector; 287290001Sglebius fd[1] = acceptor; 288290001Sglebius 289290001Sglebius return 0; 290290001Sglebius 291290001Sglebius abort_tidy_up_and_fail: 292290001Sglebius saved_errno = ERR(ECONNABORTED); 293290001Sglebius tidy_up_and_fail: 294290001Sglebius if (saved_errno < 0) 295290001Sglebius saved_errno = EVUTIL_SOCKET_ERROR(); 296290001Sglebius if (listener != -1) 297290001Sglebius evutil_closesocket(listener); 298290001Sglebius if (connector != -1) 299290001Sglebius evutil_closesocket(connector); 300290001Sglebius if (acceptor != -1) 301290001Sglebius evutil_closesocket(acceptor); 302290001Sglebius 303290001Sglebius EVUTIL_SET_SOCKET_ERROR(saved_errno); 304290001Sglebius return -1; 305290001Sglebius#undef ERR 306290001Sglebius} 307290001Sglebius 308290001Sglebiusint 309290001Sglebiusevutil_make_socket_nonblocking(evutil_socket_t fd) 310290001Sglebius{ 311290001Sglebius#ifdef _WIN32 312290001Sglebius { 313290001Sglebius u_long nonblocking = 1; 314290001Sglebius if (ioctlsocket(fd, FIONBIO, &nonblocking) == SOCKET_ERROR) { 315290001Sglebius event_sock_warn(fd, "fcntl(%d, F_GETFL)", (int)fd); 316290001Sglebius return -1; 317290001Sglebius } 318290001Sglebius } 319290001Sglebius#else 320290001Sglebius { 321290001Sglebius int flags; 322290001Sglebius if ((flags = fcntl(fd, F_GETFL, NULL)) < 0) { 323290001Sglebius event_warn("fcntl(%d, F_GETFL)", fd); 324290001Sglebius return -1; 325290001Sglebius } 326290001Sglebius if (!(flags & O_NONBLOCK)) { 327290001Sglebius if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) { 328290001Sglebius event_warn("fcntl(%d, F_SETFL)", fd); 329290001Sglebius return -1; 330290001Sglebius } 331290001Sglebius } 332290001Sglebius } 333290001Sglebius#endif 334290001Sglebius return 0; 335290001Sglebius} 336290001Sglebius 337290001Sglebius/* Faster version of evutil_make_socket_nonblocking for internal use. 338290001Sglebius * 339290001Sglebius * Requires that no F_SETFL flags were previously set on the fd. 340290001Sglebius */ 341290001Sglebiusstatic int 342290001Sglebiusevutil_fast_socket_nonblocking(evutil_socket_t fd) 343290001Sglebius{ 344290001Sglebius#ifdef _WIN32 345290001Sglebius return evutil_make_socket_nonblocking(fd); 346290001Sglebius#else 347290001Sglebius if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) { 348290001Sglebius event_warn("fcntl(%d, F_SETFL)", fd); 349290001Sglebius return -1; 350290001Sglebius } 351290001Sglebius return 0; 352290001Sglebius#endif 353290001Sglebius} 354290001Sglebius 355290001Sglebiusint 356290001Sglebiusevutil_make_listen_socket_reuseable(evutil_socket_t sock) 357290001Sglebius{ 358290001Sglebius#ifndef _WIN32 359290001Sglebius int one = 1; 360290001Sglebius /* REUSEADDR on Unix means, "don't hang on to this address after the 361290001Sglebius * listener is closed." On Windows, though, it means "don't keep other 362290001Sglebius * processes from binding to this address while we're using it. */ 363290001Sglebius return setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*) &one, 364290001Sglebius (ev_socklen_t)sizeof(one)); 365290001Sglebius#else 366290001Sglebius return 0; 367290001Sglebius#endif 368290001Sglebius} 369290001Sglebius 370290001Sglebiusint 371290001Sglebiusevutil_make_listen_socket_reuseable_port(evutil_socket_t sock) 372290001Sglebius{ 373290001Sglebius#if defined __linux__ && defined(SO_REUSEPORT) 374290001Sglebius int one = 1; 375290001Sglebius /* REUSEPORT on Linux 3.9+ means, "Multiple servers (processes or 376290001Sglebius * threads) can bind to the same port if they each set the option. */ 377290001Sglebius return setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (void*) &one, 378290001Sglebius (ev_socklen_t)sizeof(one)); 379290001Sglebius#else 380290001Sglebius return 0; 381290001Sglebius#endif 382290001Sglebius} 383290001Sglebius 384290001Sglebiusint 385290001Sglebiusevutil_make_tcp_listen_socket_deferred(evutil_socket_t sock) 386290001Sglebius{ 387290001Sglebius#if defined(EVENT__HAVE_NETINET_TCP_H) && defined(TCP_DEFER_ACCEPT) 388290001Sglebius int one = 1; 389290001Sglebius 390290001Sglebius /* TCP_DEFER_ACCEPT tells the kernel to call defer accept() only after data 391290001Sglebius * has arrived and ready to read */ 392290001Sglebius return setsockopt(sock, IPPROTO_TCP, TCP_DEFER_ACCEPT, &one, 393290001Sglebius (ev_socklen_t)sizeof(one)); 394290001Sglebius#endif 395290001Sglebius return 0; 396290001Sglebius} 397290001Sglebius 398290001Sglebiusint 399290001Sglebiusevutil_make_socket_closeonexec(evutil_socket_t fd) 400290001Sglebius{ 401290001Sglebius#if !defined(_WIN32) && defined(EVENT__HAVE_SETFD) 402290001Sglebius int flags; 403290001Sglebius if ((flags = fcntl(fd, F_GETFD, NULL)) < 0) { 404290001Sglebius event_warn("fcntl(%d, F_GETFD)", fd); 405290001Sglebius return -1; 406290001Sglebius } 407290001Sglebius if (!(flags & FD_CLOEXEC)) { 408290001Sglebius if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) { 409290001Sglebius event_warn("fcntl(%d, F_SETFD)", fd); 410290001Sglebius return -1; 411290001Sglebius } 412290001Sglebius } 413290001Sglebius#endif 414290001Sglebius return 0; 415290001Sglebius} 416290001Sglebius 417290001Sglebius/* Faster version of evutil_make_socket_closeonexec for internal use. 418290001Sglebius * 419290001Sglebius * Requires that no F_SETFD flags were previously set on the fd. 420290001Sglebius */ 421290001Sglebiusstatic int 422290001Sglebiusevutil_fast_socket_closeonexec(evutil_socket_t fd) 423290001Sglebius{ 424290001Sglebius#if !defined(_WIN32) && defined(EVENT__HAVE_SETFD) 425290001Sglebius if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) { 426290001Sglebius event_warn("fcntl(%d, F_SETFD)", fd); 427290001Sglebius return -1; 428290001Sglebius } 429290001Sglebius#endif 430290001Sglebius return 0; 431290001Sglebius} 432290001Sglebius 433290001Sglebiusint 434290001Sglebiusevutil_closesocket(evutil_socket_t sock) 435290001Sglebius{ 436290001Sglebius#ifndef _WIN32 437290001Sglebius return close(sock); 438290001Sglebius#else 439290001Sglebius return closesocket(sock); 440290001Sglebius#endif 441290001Sglebius} 442290001Sglebius 443290001Sglebiusev_int64_t 444290001Sglebiusevutil_strtoll(const char *s, char **endptr, int base) 445290001Sglebius{ 446290001Sglebius#ifdef EVENT__HAVE_STRTOLL 447290001Sglebius return (ev_int64_t)strtoll(s, endptr, base); 448290001Sglebius#elif EVENT__SIZEOF_LONG == 8 449290001Sglebius return (ev_int64_t)strtol(s, endptr, base); 450290001Sglebius#elif defined(_WIN32) && defined(_MSC_VER) && _MSC_VER < 1300 451290001Sglebius /* XXXX on old versions of MS APIs, we only support base 452290001Sglebius * 10. */ 453290001Sglebius ev_int64_t r; 454290001Sglebius if (base != 10) 455290001Sglebius return 0; 456290001Sglebius r = (ev_int64_t) _atoi64(s); 457290001Sglebius while (isspace(*s)) 458290001Sglebius ++s; 459290001Sglebius if (*s == '-') 460290001Sglebius ++s; 461290001Sglebius while (isdigit(*s)) 462290001Sglebius ++s; 463290001Sglebius if (endptr) 464290001Sglebius *endptr = (char*) s; 465290001Sglebius return r; 466290001Sglebius#elif defined(_WIN32) 467290001Sglebius return (ev_int64_t) _strtoi64(s, endptr, base); 468290001Sglebius#elif defined(EVENT__SIZEOF_LONG_LONG) && EVENT__SIZEOF_LONG_LONG == 8 469290001Sglebius long long r; 470290001Sglebius int n; 471290001Sglebius if (base != 10 && base != 16) 472290001Sglebius return 0; 473290001Sglebius if (base == 10) { 474290001Sglebius n = sscanf(s, "%lld", &r); 475290001Sglebius } else { 476290001Sglebius unsigned long long ru=0; 477290001Sglebius n = sscanf(s, "%llx", &ru); 478290001Sglebius if (ru > EV_INT64_MAX) 479290001Sglebius return 0; 480290001Sglebius r = (long long) ru; 481290001Sglebius } 482290001Sglebius if (n != 1) 483290001Sglebius return 0; 484290001Sglebius while (EVUTIL_ISSPACE_(*s)) 485290001Sglebius ++s; 486290001Sglebius if (*s == '-') 487290001Sglebius ++s; 488290001Sglebius if (base == 10) { 489290001Sglebius while (EVUTIL_ISDIGIT_(*s)) 490290001Sglebius ++s; 491290001Sglebius } else { 492290001Sglebius while (EVUTIL_ISXDIGIT_(*s)) 493290001Sglebius ++s; 494290001Sglebius } 495290001Sglebius if (endptr) 496290001Sglebius *endptr = (char*) s; 497290001Sglebius return r; 498290001Sglebius#else 499290001Sglebius#error "I don't know how to parse 64-bit integers." 500290001Sglebius#endif 501290001Sglebius} 502290001Sglebius 503290001Sglebius#ifdef _WIN32 504290001Sglebiusint 505290001Sglebiusevutil_socket_geterror(evutil_socket_t sock) 506290001Sglebius{ 507290001Sglebius int optval, optvallen=sizeof(optval); 508290001Sglebius int err = WSAGetLastError(); 509290001Sglebius if (err == WSAEWOULDBLOCK && sock >= 0) { 510290001Sglebius if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)&optval, 511290001Sglebius &optvallen)) 512290001Sglebius return err; 513290001Sglebius if (optval) 514290001Sglebius return optval; 515290001Sglebius } 516290001Sglebius return err; 517290001Sglebius} 518290001Sglebius#endif 519290001Sglebius 520290001Sglebius/* XXX we should use an enum here. */ 521290001Sglebius/* 2 for connection refused, 1 for connected, 0 for not yet, -1 for error. */ 522290001Sglebiusint 523290001Sglebiusevutil_socket_connect_(evutil_socket_t *fd_ptr, struct sockaddr *sa, int socklen) 524290001Sglebius{ 525290001Sglebius int made_fd = 0; 526290001Sglebius 527290001Sglebius if (*fd_ptr < 0) { 528290001Sglebius if ((*fd_ptr = socket(sa->sa_family, SOCK_STREAM, 0)) < 0) 529290001Sglebius goto err; 530290001Sglebius made_fd = 1; 531290001Sglebius if (evutil_make_socket_nonblocking(*fd_ptr) < 0) { 532290001Sglebius goto err; 533290001Sglebius } 534290001Sglebius } 535290001Sglebius 536290001Sglebius if (connect(*fd_ptr, sa, socklen) < 0) { 537290001Sglebius int e = evutil_socket_geterror(*fd_ptr); 538290001Sglebius if (EVUTIL_ERR_CONNECT_RETRIABLE(e)) 539290001Sglebius return 0; 540290001Sglebius if (EVUTIL_ERR_CONNECT_REFUSED(e)) 541290001Sglebius return 2; 542290001Sglebius goto err; 543290001Sglebius } else { 544290001Sglebius return 1; 545290001Sglebius } 546290001Sglebius 547290001Sglebiuserr: 548290001Sglebius if (made_fd) { 549290001Sglebius evutil_closesocket(*fd_ptr); 550290001Sglebius *fd_ptr = -1; 551290001Sglebius } 552290001Sglebius return -1; 553290001Sglebius} 554290001Sglebius 555290001Sglebius/* Check whether a socket on which we called connect() is done 556290001Sglebius connecting. Return 1 for connected, 0 for not yet, -1 for error. In the 557290001Sglebius error case, set the current socket errno to the error that happened during 558290001Sglebius the connect operation. */ 559290001Sglebiusint 560290001Sglebiusevutil_socket_finished_connecting_(evutil_socket_t fd) 561290001Sglebius{ 562290001Sglebius int e; 563290001Sglebius ev_socklen_t elen = sizeof(e); 564290001Sglebius 565290001Sglebius if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&e, &elen) < 0) 566290001Sglebius return -1; 567290001Sglebius 568290001Sglebius if (e) { 569290001Sglebius if (EVUTIL_ERR_CONNECT_RETRIABLE(e)) 570290001Sglebius return 0; 571290001Sglebius EVUTIL_SET_SOCKET_ERROR(e); 572290001Sglebius return -1; 573290001Sglebius } 574290001Sglebius 575290001Sglebius return 1; 576290001Sglebius} 577290001Sglebius 578290001Sglebius#if (EVUTIL_AI_PASSIVE|EVUTIL_AI_CANONNAME|EVUTIL_AI_NUMERICHOST| \ 579290001Sglebius EVUTIL_AI_NUMERICSERV|EVUTIL_AI_V4MAPPED|EVUTIL_AI_ALL| \ 580290001Sglebius EVUTIL_AI_ADDRCONFIG) != \ 581290001Sglebius (EVUTIL_AI_PASSIVE^EVUTIL_AI_CANONNAME^EVUTIL_AI_NUMERICHOST^ \ 582290001Sglebius EVUTIL_AI_NUMERICSERV^EVUTIL_AI_V4MAPPED^EVUTIL_AI_ALL^ \ 583290001Sglebius EVUTIL_AI_ADDRCONFIG) 584290001Sglebius#error "Some of our EVUTIL_AI_* flags seem to overlap with system AI_* flags" 585290001Sglebius#endif 586290001Sglebius 587290001Sglebius/* We sometimes need to know whether we have an ipv4 address and whether we 588290001Sglebius have an ipv6 address. If 'have_checked_interfaces', then we've already done 589290001Sglebius the test. If 'had_ipv4_address', then it turns out we had an ipv4 address. 590290001Sglebius If 'had_ipv6_address', then it turns out we had an ipv6 address. These are 591290001Sglebius set by evutil_check_interfaces. */ 592290001Sglebiusstatic int have_checked_interfaces, had_ipv4_address, had_ipv6_address; 593290001Sglebius 594290001Sglebius/* Macro: True iff the IPv4 address 'addr', in host order, is in 127.0.0.0/8 595290001Sglebius */ 596290001Sglebius#define EVUTIL_V4ADDR_IS_LOCALHOST(addr) (((addr)>>24) == 127) 597290001Sglebius 598290001Sglebius/* Macro: True iff the IPv4 address 'addr', in host order, is a class D 599290001Sglebius * (multiclass) address. 600290001Sglebius */ 601290001Sglebius#define EVUTIL_V4ADDR_IS_CLASSD(addr) ((((addr)>>24) & 0xf0) == 0xe0) 602290001Sglebius 603290001Sglebiusstatic void 604290001Sglebiusevutil_found_ifaddr(const struct sockaddr *sa) 605290001Sglebius{ 606290001Sglebius const char ZEROES[] = "\x00\x00\x00\x00\x00\x00\x00\x00" 607290001Sglebius "\x00\x00\x00\x00\x00\x00\x00\x00"; 608290001Sglebius 609290001Sglebius if (sa->sa_family == AF_INET) { 610290001Sglebius const struct sockaddr_in *sin = (struct sockaddr_in *)sa; 611290001Sglebius ev_uint32_t addr = ntohl(sin->sin_addr.s_addr); 612290001Sglebius if (addr == 0 || 613290001Sglebius EVUTIL_V4ADDR_IS_LOCALHOST(addr) || 614290001Sglebius EVUTIL_V4ADDR_IS_CLASSD(addr)) { 615290001Sglebius /* Not actually a usable external address. */ 616290001Sglebius } else { 617290001Sglebius event_debug(("Detected an IPv4 interface")); 618290001Sglebius had_ipv4_address = 1; 619290001Sglebius } 620290001Sglebius } else if (sa->sa_family == AF_INET6) { 621290001Sglebius const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; 622290001Sglebius const unsigned char *addr = 623290001Sglebius (unsigned char*)sin6->sin6_addr.s6_addr; 624290001Sglebius if (!memcmp(addr, ZEROES, 8) || 625290001Sglebius ((addr[0] & 0xfe) == 0xfc) || 626290001Sglebius (addr[0] == 0xfe && (addr[1] & 0xc0) == 0x80) || 627290001Sglebius (addr[0] == 0xfe && (addr[1] & 0xc0) == 0xc0) || 628290001Sglebius (addr[0] == 0xff)) { 629290001Sglebius /* This is a reserved, ipv4compat, ipv4map, loopback, 630290001Sglebius * link-local, multicast, or unspecified address. */ 631290001Sglebius } else { 632290001Sglebius event_debug(("Detected an IPv6 interface")); 633290001Sglebius had_ipv6_address = 1; 634290001Sglebius } 635290001Sglebius } 636290001Sglebius} 637290001Sglebius 638290001Sglebius#ifdef _WIN32 639290001Sglebiustypedef ULONG (WINAPI *GetAdaptersAddresses_fn_t)( 640290001Sglebius ULONG, ULONG, PVOID, PIP_ADAPTER_ADDRESSES, PULONG); 641290001Sglebius#endif 642290001Sglebius 643290001Sglebiusstatic int 644290001Sglebiusevutil_check_ifaddrs(void) 645290001Sglebius{ 646290001Sglebius#if defined(EVENT__HAVE_GETIFADDRS) 647290001Sglebius /* Most free Unixy systems provide getifaddrs, which gives us a linked list 648290001Sglebius * of struct ifaddrs. */ 649290001Sglebius struct ifaddrs *ifa = NULL; 650290001Sglebius const struct ifaddrs *i; 651290001Sglebius if (getifaddrs(&ifa) < 0) { 652290001Sglebius event_warn("Unable to call getifaddrs()"); 653290001Sglebius return -1; 654290001Sglebius } 655290001Sglebius 656290001Sglebius for (i = ifa; i; i = i->ifa_next) { 657290001Sglebius if (!i->ifa_addr) 658290001Sglebius continue; 659290001Sglebius evutil_found_ifaddr(i->ifa_addr); 660290001Sglebius } 661290001Sglebius 662290001Sglebius freeifaddrs(ifa); 663290001Sglebius return 0; 664290001Sglebius#elif defined(_WIN32) 665290001Sglebius /* Windows XP began to provide GetAdaptersAddresses. Windows 2000 had a 666290001Sglebius "GetAdaptersInfo", but that's deprecated; let's just try 667290001Sglebius GetAdaptersAddresses and fall back to connect+getsockname. 668290001Sglebius */ 669290001Sglebius HMODULE lib = evutil_load_windows_system_library_(TEXT("ihplapi.dll")); 670290001Sglebius GetAdaptersAddresses_fn_t fn; 671290001Sglebius ULONG size, res; 672290001Sglebius IP_ADAPTER_ADDRESSES *addresses = NULL, *address; 673290001Sglebius int result = -1; 674290001Sglebius 675290001Sglebius#define FLAGS (GAA_FLAG_SKIP_ANYCAST | \ 676290001Sglebius GAA_FLAG_SKIP_MULTICAST | \ 677290001Sglebius GAA_FLAG_SKIP_DNS_SERVER) 678290001Sglebius 679290001Sglebius if (!lib) 680290001Sglebius goto done; 681290001Sglebius 682290001Sglebius if (!(fn = (GetAdaptersAddresses_fn_t) GetProcAddress(lib, "GetAdaptersAddresses"))) 683290001Sglebius goto done; 684290001Sglebius 685290001Sglebius /* Guess how much space we need. */ 686290001Sglebius size = 15*1024; 687290001Sglebius addresses = mm_malloc(size); 688290001Sglebius if (!addresses) 689290001Sglebius goto done; 690290001Sglebius res = fn(AF_UNSPEC, FLAGS, NULL, addresses, &size); 691290001Sglebius if (res == ERROR_BUFFER_OVERFLOW) { 692290001Sglebius /* we didn't guess that we needed enough space; try again */ 693290001Sglebius mm_free(addresses); 694290001Sglebius addresses = mm_malloc(size); 695290001Sglebius if (!addresses) 696290001Sglebius goto done; 697290001Sglebius res = fn(AF_UNSPEC, FLAGS, NULL, addresses, &size); 698290001Sglebius } 699290001Sglebius if (res != NO_ERROR) 700290001Sglebius goto done; 701290001Sglebius 702290001Sglebius for (address = addresses; address; address = address->Next) { 703290001Sglebius IP_ADAPTER_UNICAST_ADDRESS *a; 704290001Sglebius for (a = address->FirstUnicastAddress; a; a = a->Next) { 705290001Sglebius /* Yes, it's a linked list inside a linked list */ 706290001Sglebius struct sockaddr *sa = a->Address.lpSockaddr; 707290001Sglebius evutil_found_ifaddr(sa); 708290001Sglebius } 709290001Sglebius } 710290001Sglebius 711290001Sglebius result = 0; 712290001Sglebiusdone: 713290001Sglebius if (lib) 714290001Sglebius FreeLibrary(lib); 715290001Sglebius if (addresses) 716290001Sglebius mm_free(addresses); 717290001Sglebius return result; 718290001Sglebius#else 719290001Sglebius return -1; 720290001Sglebius#endif 721290001Sglebius} 722290001Sglebius 723290001Sglebius/* Test whether we have an ipv4 interface and an ipv6 interface. Return 0 if 724290001Sglebius * the test seemed successful. */ 725290001Sglebiusstatic int 726290001Sglebiusevutil_check_interfaces(int force_recheck) 727290001Sglebius{ 728290001Sglebius evutil_socket_t fd = -1; 729290001Sglebius struct sockaddr_in sin, sin_out; 730290001Sglebius struct sockaddr_in6 sin6, sin6_out; 731290001Sglebius ev_socklen_t sin_out_len = sizeof(sin_out); 732290001Sglebius ev_socklen_t sin6_out_len = sizeof(sin6_out); 733290001Sglebius int r; 734290001Sglebius if (have_checked_interfaces && !force_recheck) 735290001Sglebius return 0; 736290001Sglebius 737290001Sglebius if (evutil_check_ifaddrs() == 0) { 738290001Sglebius /* Use a nice sane interface, if this system has one. */ 739290001Sglebius return 0; 740290001Sglebius } 741290001Sglebius 742290001Sglebius /* Ugh. There was no nice sane interface. So to check whether we have 743290001Sglebius * an interface open for a given protocol, will try to make a UDP 744290001Sglebius * 'connection' to a remote host on the internet. We don't actually 745290001Sglebius * use it, so the address doesn't matter, but we want to pick one that 746290001Sglebius * keep us from using a host- or link-local interface. */ 747290001Sglebius memset(&sin, 0, sizeof(sin)); 748290001Sglebius sin.sin_family = AF_INET; 749290001Sglebius sin.sin_port = htons(53); 750290001Sglebius r = evutil_inet_pton(AF_INET, "18.244.0.188", &sin.sin_addr); 751290001Sglebius EVUTIL_ASSERT(r); 752290001Sglebius 753290001Sglebius memset(&sin6, 0, sizeof(sin6)); 754290001Sglebius sin6.sin6_family = AF_INET6; 755290001Sglebius sin6.sin6_port = htons(53); 756290001Sglebius r = evutil_inet_pton(AF_INET6, "2001:4860:b002::68", &sin6.sin6_addr); 757290001Sglebius EVUTIL_ASSERT(r); 758290001Sglebius 759290001Sglebius memset(&sin_out, 0, sizeof(sin_out)); 760290001Sglebius memset(&sin6_out, 0, sizeof(sin6_out)); 761290001Sglebius 762290001Sglebius /* XXX some errnos mean 'no address'; some mean 'not enough sockets'. */ 763290001Sglebius if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) >= 0 && 764290001Sglebius connect(fd, (struct sockaddr*)&sin, sizeof(sin)) == 0 && 765290001Sglebius getsockname(fd, (struct sockaddr*)&sin_out, &sin_out_len) == 0) { 766290001Sglebius /* We might have an IPv4 interface. */ 767290001Sglebius evutil_found_ifaddr((struct sockaddr*) &sin_out); 768290001Sglebius } 769290001Sglebius if (fd >= 0) 770290001Sglebius evutil_closesocket(fd); 771290001Sglebius 772290001Sglebius if ((fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) >= 0 && 773290001Sglebius connect(fd, (struct sockaddr*)&sin6, sizeof(sin6)) == 0 && 774290001Sglebius getsockname(fd, (struct sockaddr*)&sin6_out, &sin6_out_len) == 0) { 775290001Sglebius /* We might have an IPv6 interface. */ 776290001Sglebius evutil_found_ifaddr((struct sockaddr*) &sin6_out); 777290001Sglebius } 778290001Sglebius 779290001Sglebius if (fd >= 0) 780290001Sglebius evutil_closesocket(fd); 781290001Sglebius 782290001Sglebius return 0; 783290001Sglebius} 784290001Sglebius 785290001Sglebius/* Internal addrinfo flag. This one is set when we allocate the addrinfo from 786290001Sglebius * inside libevent. Otherwise, the built-in getaddrinfo() function allocated 787290001Sglebius * it, and we should trust what they said. 788290001Sglebius **/ 789290001Sglebius#define EVUTIL_AI_LIBEVENT_ALLOCATED 0x80000000 790290001Sglebius 791290001Sglebius/* Helper: construct a new addrinfo containing the socket address in 792290001Sglebius * 'sa', which must be a sockaddr_in or a sockaddr_in6. Take the 793290001Sglebius * socktype and protocol info from hints. If they weren't set, then 794290001Sglebius * allocate both a TCP and a UDP addrinfo. 795290001Sglebius */ 796290001Sglebiusstruct evutil_addrinfo * 797290001Sglebiusevutil_new_addrinfo_(struct sockaddr *sa, ev_socklen_t socklen, 798290001Sglebius const struct evutil_addrinfo *hints) 799290001Sglebius{ 800290001Sglebius struct evutil_addrinfo *res; 801290001Sglebius EVUTIL_ASSERT(hints); 802290001Sglebius 803290001Sglebius if (hints->ai_socktype == 0 && hints->ai_protocol == 0) { 804290001Sglebius /* Indecisive user! Give them a UDP and a TCP. */ 805290001Sglebius struct evutil_addrinfo *r1, *r2; 806290001Sglebius struct evutil_addrinfo tmp; 807290001Sglebius memcpy(&tmp, hints, sizeof(tmp)); 808290001Sglebius tmp.ai_socktype = SOCK_STREAM; tmp.ai_protocol = IPPROTO_TCP; 809290001Sglebius r1 = evutil_new_addrinfo_(sa, socklen, &tmp); 810290001Sglebius if (!r1) 811290001Sglebius return NULL; 812290001Sglebius tmp.ai_socktype = SOCK_DGRAM; tmp.ai_protocol = IPPROTO_UDP; 813290001Sglebius r2 = evutil_new_addrinfo_(sa, socklen, &tmp); 814290001Sglebius if (!r2) { 815290001Sglebius evutil_freeaddrinfo(r1); 816290001Sglebius return NULL; 817290001Sglebius } 818290001Sglebius r1->ai_next = r2; 819290001Sglebius return r1; 820290001Sglebius } 821290001Sglebius 822290001Sglebius /* We're going to allocate extra space to hold the sockaddr. */ 823290001Sglebius res = mm_calloc(1,sizeof(struct evutil_addrinfo)+socklen); 824290001Sglebius if (!res) 825290001Sglebius return NULL; 826290001Sglebius res->ai_addr = (struct sockaddr*) 827290001Sglebius (((char*)res) + sizeof(struct evutil_addrinfo)); 828290001Sglebius memcpy(res->ai_addr, sa, socklen); 829290001Sglebius res->ai_addrlen = socklen; 830290001Sglebius res->ai_family = sa->sa_family; /* Same or not? XXX */ 831290001Sglebius res->ai_flags = EVUTIL_AI_LIBEVENT_ALLOCATED; 832290001Sglebius res->ai_socktype = hints->ai_socktype; 833290001Sglebius res->ai_protocol = hints->ai_protocol; 834290001Sglebius 835290001Sglebius return res; 836290001Sglebius} 837290001Sglebius 838290001Sglebius/* Append the addrinfo 'append' to the end of 'first', and return the start of 839290001Sglebius * the list. Either element can be NULL, in which case we return the element 840290001Sglebius * that is not NULL. */ 841290001Sglebiusstruct evutil_addrinfo * 842290001Sglebiusevutil_addrinfo_append_(struct evutil_addrinfo *first, 843290001Sglebius struct evutil_addrinfo *append) 844290001Sglebius{ 845290001Sglebius struct evutil_addrinfo *ai = first; 846290001Sglebius if (!ai) 847290001Sglebius return append; 848290001Sglebius while (ai->ai_next) 849290001Sglebius ai = ai->ai_next; 850290001Sglebius ai->ai_next = append; 851290001Sglebius 852290001Sglebius return first; 853290001Sglebius} 854290001Sglebius 855290001Sglebiusstatic int 856290001Sglebiusparse_numeric_servname(const char *servname) 857290001Sglebius{ 858290001Sglebius int n; 859290001Sglebius char *endptr=NULL; 860290001Sglebius n = (int) strtol(servname, &endptr, 10); 861290001Sglebius if (n>=0 && n <= 65535 && servname[0] && endptr && !endptr[0]) 862290001Sglebius return n; 863290001Sglebius else 864290001Sglebius return -1; 865290001Sglebius} 866290001Sglebius 867290001Sglebius/** Parse a service name in 'servname', which can be a decimal port. 868290001Sglebius * Return the port number, or -1 on error. 869290001Sglebius */ 870290001Sglebiusstatic int 871290001Sglebiusevutil_parse_servname(const char *servname, const char *protocol, 872290001Sglebius const struct evutil_addrinfo *hints) 873290001Sglebius{ 874290001Sglebius int n = parse_numeric_servname(servname); 875290001Sglebius if (n>=0) 876290001Sglebius return n; 877290001Sglebius#if defined(EVENT__HAVE_GETSERVBYNAME) || defined(_WIN32) 878290001Sglebius if (!(hints->ai_flags & EVUTIL_AI_NUMERICSERV)) { 879290001Sglebius struct servent *ent = getservbyname(servname, protocol); 880290001Sglebius if (ent) { 881290001Sglebius return ntohs(ent->s_port); 882290001Sglebius } 883290001Sglebius } 884290001Sglebius#endif 885290001Sglebius return -1; 886290001Sglebius} 887290001Sglebius 888290001Sglebius/* Return a string corresponding to a protocol number that we can pass to 889290001Sglebius * getservyname. */ 890290001Sglebiusstatic const char * 891290001Sglebiusevutil_unparse_protoname(int proto) 892290001Sglebius{ 893290001Sglebius switch (proto) { 894290001Sglebius case 0: 895290001Sglebius return NULL; 896290001Sglebius case IPPROTO_TCP: 897290001Sglebius return "tcp"; 898290001Sglebius case IPPROTO_UDP: 899290001Sglebius return "udp"; 900290001Sglebius#ifdef IPPROTO_SCTP 901290001Sglebius case IPPROTO_SCTP: 902290001Sglebius return "sctp"; 903290001Sglebius#endif 904290001Sglebius default: 905290001Sglebius#ifdef EVENT__HAVE_GETPROTOBYNUMBER 906290001Sglebius { 907290001Sglebius struct protoent *ent = getprotobynumber(proto); 908290001Sglebius if (ent) 909290001Sglebius return ent->p_name; 910290001Sglebius } 911290001Sglebius#endif 912290001Sglebius return NULL; 913290001Sglebius } 914290001Sglebius} 915290001Sglebius 916290001Sglebiusstatic void 917290001Sglebiusevutil_getaddrinfo_infer_protocols(struct evutil_addrinfo *hints) 918290001Sglebius{ 919290001Sglebius /* If we can guess the protocol from the socktype, do so. */ 920290001Sglebius if (!hints->ai_protocol && hints->ai_socktype) { 921290001Sglebius if (hints->ai_socktype == SOCK_DGRAM) 922290001Sglebius hints->ai_protocol = IPPROTO_UDP; 923290001Sglebius else if (hints->ai_socktype == SOCK_STREAM) 924290001Sglebius hints->ai_protocol = IPPROTO_TCP; 925290001Sglebius } 926290001Sglebius 927290001Sglebius /* Set the socktype if it isn't set. */ 928290001Sglebius if (!hints->ai_socktype && hints->ai_protocol) { 929290001Sglebius if (hints->ai_protocol == IPPROTO_UDP) 930290001Sglebius hints->ai_socktype = SOCK_DGRAM; 931290001Sglebius else if (hints->ai_protocol == IPPROTO_TCP) 932290001Sglebius hints->ai_socktype = SOCK_STREAM; 933290001Sglebius#ifdef IPPROTO_SCTP 934290001Sglebius else if (hints->ai_protocol == IPPROTO_SCTP) 935290001Sglebius hints->ai_socktype = SOCK_STREAM; 936290001Sglebius#endif 937290001Sglebius } 938290001Sglebius} 939290001Sglebius 940290001Sglebius#if AF_UNSPEC != PF_UNSPEC 941290001Sglebius#error "I cannot build on a system where AF_UNSPEC != PF_UNSPEC" 942290001Sglebius#endif 943290001Sglebius 944290001Sglebius/** Implements the part of looking up hosts by name that's common to both 945290001Sglebius * the blocking and nonblocking resolver: 946290001Sglebius * - Adjust 'hints' to have a reasonable socktype and protocol. 947290001Sglebius * - Look up the port based on 'servname', and store it in *portnum, 948290001Sglebius * - Handle the nodename==NULL case 949290001Sglebius * - Handle some invalid arguments cases. 950290001Sglebius * - Handle the cases where nodename is an IPv4 or IPv6 address. 951290001Sglebius * 952290001Sglebius * If we need the resolver to look up the hostname, we return 953290001Sglebius * EVUTIL_EAI_NEED_RESOLVE. Otherwise, we can completely implement 954290001Sglebius * getaddrinfo: we return 0 or an appropriate EVUTIL_EAI_* error, and 955290001Sglebius * set *res as getaddrinfo would. 956290001Sglebius */ 957290001Sglebiusint 958290001Sglebiusevutil_getaddrinfo_common_(const char *nodename, const char *servname, 959290001Sglebius struct evutil_addrinfo *hints, struct evutil_addrinfo **res, int *portnum) 960290001Sglebius{ 961290001Sglebius int port = 0; 962290001Sglebius const char *pname; 963290001Sglebius 964290001Sglebius if (nodename == NULL && servname == NULL) 965290001Sglebius return EVUTIL_EAI_NONAME; 966290001Sglebius 967290001Sglebius /* We only understand 3 families */ 968290001Sglebius if (hints->ai_family != PF_UNSPEC && hints->ai_family != PF_INET && 969290001Sglebius hints->ai_family != PF_INET6) 970290001Sglebius return EVUTIL_EAI_FAMILY; 971290001Sglebius 972290001Sglebius evutil_getaddrinfo_infer_protocols(hints); 973290001Sglebius 974290001Sglebius /* Look up the port number and protocol, if possible. */ 975290001Sglebius pname = evutil_unparse_protoname(hints->ai_protocol); 976290001Sglebius if (servname) { 977290001Sglebius /* XXXX We could look at the protocol we got back from 978290001Sglebius * getservbyname, but it doesn't seem too useful. */ 979290001Sglebius port = evutil_parse_servname(servname, pname, hints); 980290001Sglebius if (port < 0) { 981290001Sglebius return EVUTIL_EAI_NONAME; 982290001Sglebius } 983290001Sglebius } 984290001Sglebius 985290001Sglebius /* If we have no node name, then we're supposed to bind to 'any' and 986290001Sglebius * connect to localhost. */ 987290001Sglebius if (nodename == NULL) { 988290001Sglebius struct evutil_addrinfo *res4=NULL, *res6=NULL; 989290001Sglebius if (hints->ai_family != PF_INET) { /* INET6 or UNSPEC. */ 990290001Sglebius struct sockaddr_in6 sin6; 991290001Sglebius memset(&sin6, 0, sizeof(sin6)); 992290001Sglebius sin6.sin6_family = AF_INET6; 993290001Sglebius sin6.sin6_port = htons(port); 994290001Sglebius if (hints->ai_flags & EVUTIL_AI_PASSIVE) { 995290001Sglebius /* Bind to :: */ 996290001Sglebius } else { 997290001Sglebius /* connect to ::1 */ 998290001Sglebius sin6.sin6_addr.s6_addr[15] = 1; 999290001Sglebius } 1000290001Sglebius res6 = evutil_new_addrinfo_((struct sockaddr*)&sin6, 1001290001Sglebius sizeof(sin6), hints); 1002290001Sglebius if (!res6) 1003290001Sglebius return EVUTIL_EAI_MEMORY; 1004290001Sglebius } 1005290001Sglebius 1006290001Sglebius if (hints->ai_family != PF_INET6) { /* INET or UNSPEC */ 1007290001Sglebius struct sockaddr_in sin; 1008290001Sglebius memset(&sin, 0, sizeof(sin)); 1009290001Sglebius sin.sin_family = AF_INET; 1010290001Sglebius sin.sin_port = htons(port); 1011290001Sglebius if (hints->ai_flags & EVUTIL_AI_PASSIVE) { 1012290001Sglebius /* Bind to 0.0.0.0 */ 1013290001Sglebius } else { 1014290001Sglebius /* connect to 127.0.0.1 */ 1015290001Sglebius sin.sin_addr.s_addr = htonl(0x7f000001); 1016290001Sglebius } 1017290001Sglebius res4 = evutil_new_addrinfo_((struct sockaddr*)&sin, 1018290001Sglebius sizeof(sin), hints); 1019290001Sglebius if (!res4) { 1020290001Sglebius if (res6) 1021290001Sglebius evutil_freeaddrinfo(res6); 1022290001Sglebius return EVUTIL_EAI_MEMORY; 1023290001Sglebius } 1024290001Sglebius } 1025290001Sglebius *res = evutil_addrinfo_append_(res4, res6); 1026290001Sglebius return 0; 1027290001Sglebius } 1028290001Sglebius 1029290001Sglebius /* If we can, we should try to parse the hostname without resolving 1030290001Sglebius * it. */ 1031290001Sglebius /* Try ipv6. */ 1032290001Sglebius if (hints->ai_family == PF_INET6 || hints->ai_family == PF_UNSPEC) { 1033290001Sglebius struct sockaddr_in6 sin6; 1034290001Sglebius memset(&sin6, 0, sizeof(sin6)); 1035290001Sglebius if (1==evutil_inet_pton(AF_INET6, nodename, &sin6.sin6_addr)) { 1036290001Sglebius /* Got an ipv6 address. */ 1037290001Sglebius sin6.sin6_family = AF_INET6; 1038290001Sglebius sin6.sin6_port = htons(port); 1039290001Sglebius *res = evutil_new_addrinfo_((struct sockaddr*)&sin6, 1040290001Sglebius sizeof(sin6), hints); 1041290001Sglebius if (!*res) 1042290001Sglebius return EVUTIL_EAI_MEMORY; 1043290001Sglebius return 0; 1044290001Sglebius } 1045290001Sglebius } 1046290001Sglebius 1047290001Sglebius /* Try ipv4. */ 1048290001Sglebius if (hints->ai_family == PF_INET || hints->ai_family == PF_UNSPEC) { 1049290001Sglebius struct sockaddr_in sin; 1050290001Sglebius memset(&sin, 0, sizeof(sin)); 1051290001Sglebius if (1==evutil_inet_pton(AF_INET, nodename, &sin.sin_addr)) { 1052290001Sglebius /* Got an ipv6 address. */ 1053290001Sglebius sin.sin_family = AF_INET; 1054290001Sglebius sin.sin_port = htons(port); 1055290001Sglebius *res = evutil_new_addrinfo_((struct sockaddr*)&sin, 1056290001Sglebius sizeof(sin), hints); 1057290001Sglebius if (!*res) 1058290001Sglebius return EVUTIL_EAI_MEMORY; 1059290001Sglebius return 0; 1060290001Sglebius } 1061290001Sglebius } 1062290001Sglebius 1063290001Sglebius 1064290001Sglebius /* If we have reached this point, we definitely need to do a DNS 1065290001Sglebius * lookup. */ 1066290001Sglebius if ((hints->ai_flags & EVUTIL_AI_NUMERICHOST)) { 1067290001Sglebius /* If we're not allowed to do one, then say so. */ 1068290001Sglebius return EVUTIL_EAI_NONAME; 1069290001Sglebius } 1070290001Sglebius *portnum = port; 1071290001Sglebius return EVUTIL_EAI_NEED_RESOLVE; 1072290001Sglebius} 1073290001Sglebius 1074290001Sglebius#ifdef EVENT__HAVE_GETADDRINFO 1075290001Sglebius#define USE_NATIVE_GETADDRINFO 1076290001Sglebius#endif 1077290001Sglebius 1078290001Sglebius#ifdef USE_NATIVE_GETADDRINFO 1079290001Sglebius/* A mask of all the flags that we declare, so we can clear them before calling 1080290001Sglebius * the native getaddrinfo */ 1081290001Sglebiusstatic const unsigned int ALL_NONNATIVE_AI_FLAGS = 1082290001Sglebius#ifndef AI_PASSIVE 1083290001Sglebius EVUTIL_AI_PASSIVE | 1084290001Sglebius#endif 1085290001Sglebius#ifndef AI_CANONNAME 1086290001Sglebius EVUTIL_AI_CANONNAME | 1087290001Sglebius#endif 1088290001Sglebius#ifndef AI_NUMERICHOST 1089290001Sglebius EVUTIL_AI_NUMERICHOST | 1090290001Sglebius#endif 1091290001Sglebius#ifndef AI_NUMERICSERV 1092290001Sglebius EVUTIL_AI_NUMERICSERV | 1093290001Sglebius#endif 1094290001Sglebius#ifndef AI_ADDRCONFIG 1095290001Sglebius EVUTIL_AI_ADDRCONFIG | 1096290001Sglebius#endif 1097290001Sglebius#ifndef AI_ALL 1098290001Sglebius EVUTIL_AI_ALL | 1099290001Sglebius#endif 1100290001Sglebius#ifndef AI_V4MAPPED 1101290001Sglebius EVUTIL_AI_V4MAPPED | 1102290001Sglebius#endif 1103290001Sglebius EVUTIL_AI_LIBEVENT_ALLOCATED; 1104290001Sglebius 1105290001Sglebiusstatic const unsigned int ALL_NATIVE_AI_FLAGS = 1106290001Sglebius#ifdef AI_PASSIVE 1107290001Sglebius AI_PASSIVE | 1108290001Sglebius#endif 1109290001Sglebius#ifdef AI_CANONNAME 1110290001Sglebius AI_CANONNAME | 1111290001Sglebius#endif 1112290001Sglebius#ifdef AI_NUMERICHOST 1113290001Sglebius AI_NUMERICHOST | 1114290001Sglebius#endif 1115290001Sglebius#ifdef AI_NUMERICSERV 1116290001Sglebius AI_NUMERICSERV | 1117290001Sglebius#endif 1118290001Sglebius#ifdef AI_ADDRCONFIG 1119290001Sglebius AI_ADDRCONFIG | 1120290001Sglebius#endif 1121290001Sglebius#ifdef AI_ALL 1122290001Sglebius AI_ALL | 1123290001Sglebius#endif 1124290001Sglebius#ifdef AI_V4MAPPED 1125290001Sglebius AI_V4MAPPED | 1126290001Sglebius#endif 1127290001Sglebius 0; 1128290001Sglebius#endif 1129290001Sglebius 1130290001Sglebius#ifndef USE_NATIVE_GETADDRINFO 1131290001Sglebius/* Helper for systems with no getaddrinfo(): make one or more addrinfos out of 1132290001Sglebius * a struct hostent. 1133290001Sglebius */ 1134290001Sglebiusstatic struct evutil_addrinfo * 1135290001Sglebiusaddrinfo_from_hostent(const struct hostent *ent, 1136290001Sglebius int port, const struct evutil_addrinfo *hints) 1137290001Sglebius{ 1138290001Sglebius int i; 1139290001Sglebius struct sockaddr_in sin; 1140290001Sglebius struct sockaddr_in6 sin6; 1141290001Sglebius struct sockaddr *sa; 1142290001Sglebius int socklen; 1143290001Sglebius struct evutil_addrinfo *res=NULL, *ai; 1144290001Sglebius void *addrp; 1145290001Sglebius 1146290001Sglebius if (ent->h_addrtype == PF_INET) { 1147290001Sglebius memset(&sin, 0, sizeof(sin)); 1148290001Sglebius sin.sin_family = AF_INET; 1149290001Sglebius sin.sin_port = htons(port); 1150290001Sglebius sa = (struct sockaddr *)&sin; 1151290001Sglebius socklen = sizeof(struct sockaddr_in); 1152290001Sglebius addrp = &sin.sin_addr; 1153290001Sglebius if (ent->h_length != sizeof(sin.sin_addr)) { 1154290001Sglebius event_warnx("Weird h_length from gethostbyname"); 1155290001Sglebius return NULL; 1156290001Sglebius } 1157290001Sglebius } else if (ent->h_addrtype == PF_INET6) { 1158290001Sglebius memset(&sin6, 0, sizeof(sin6)); 1159290001Sglebius sin6.sin6_family = AF_INET6; 1160290001Sglebius sin6.sin6_port = htons(port); 1161290001Sglebius sa = (struct sockaddr *)&sin6; 1162290001Sglebius socklen = sizeof(struct sockaddr_in); 1163290001Sglebius addrp = &sin6.sin6_addr; 1164290001Sglebius if (ent->h_length != sizeof(sin6.sin6_addr)) { 1165290001Sglebius event_warnx("Weird h_length from gethostbyname"); 1166290001Sglebius return NULL; 1167290001Sglebius } 1168290001Sglebius } else 1169290001Sglebius return NULL; 1170290001Sglebius 1171290001Sglebius for (i = 0; ent->h_addr_list[i]; ++i) { 1172290001Sglebius memcpy(addrp, ent->h_addr_list[i], ent->h_length); 1173290001Sglebius ai = evutil_new_addrinfo_(sa, socklen, hints); 1174290001Sglebius if (!ai) { 1175290001Sglebius evutil_freeaddrinfo(res); 1176290001Sglebius return NULL; 1177290001Sglebius } 1178290001Sglebius res = evutil_addrinfo_append_(res, ai); 1179290001Sglebius } 1180290001Sglebius 1181290001Sglebius if (res && ((hints->ai_flags & EVUTIL_AI_CANONNAME) && ent->h_name)) { 1182290001Sglebius res->ai_canonname = mm_strdup(ent->h_name); 1183290001Sglebius if (res->ai_canonname == NULL) { 1184290001Sglebius evutil_freeaddrinfo(res); 1185290001Sglebius return NULL; 1186290001Sglebius } 1187290001Sglebius } 1188290001Sglebius 1189290001Sglebius return res; 1190290001Sglebius} 1191290001Sglebius#endif 1192290001Sglebius 1193290001Sglebius/* If the EVUTIL_AI_ADDRCONFIG flag is set on hints->ai_flags, and 1194290001Sglebius * hints->ai_family is PF_UNSPEC, then revise the value of hints->ai_family so 1195290001Sglebius * that we'll only get addresses we could maybe connect to. 1196290001Sglebius */ 1197290001Sglebiusvoid 1198290001Sglebiusevutil_adjust_hints_for_addrconfig_(struct evutil_addrinfo *hints) 1199290001Sglebius{ 1200290001Sglebius if (!(hints->ai_flags & EVUTIL_AI_ADDRCONFIG)) 1201290001Sglebius return; 1202290001Sglebius if (hints->ai_family != PF_UNSPEC) 1203290001Sglebius return; 1204290001Sglebius if (!have_checked_interfaces) 1205290001Sglebius evutil_check_interfaces(0); 1206290001Sglebius if (had_ipv4_address && !had_ipv6_address) { 1207290001Sglebius hints->ai_family = PF_INET; 1208290001Sglebius } else if (!had_ipv4_address && had_ipv6_address) { 1209290001Sglebius hints->ai_family = PF_INET6; 1210290001Sglebius } 1211290001Sglebius} 1212290001Sglebius 1213290001Sglebius#ifdef USE_NATIVE_GETADDRINFO 1214290001Sglebiusstatic int need_numeric_port_hack_=0; 1215290001Sglebiusstatic int need_socktype_protocol_hack_=0; 1216290001Sglebiusstatic int tested_for_getaddrinfo_hacks=0; 1217290001Sglebius 1218290001Sglebius/* Some older BSDs (like OpenBSD up to 4.6) used to believe that 1219290001Sglebius giving a numeric port without giving an ai_socktype was verboten. 1220290001Sglebius We test for this so we can apply an appropriate workaround. If it 1221290001Sglebius turns out that the bug is present, then: 1222290001Sglebius 1223290001Sglebius - If nodename==NULL and servname is numeric, we build an answer 1224290001Sglebius ourselves using evutil_getaddrinfo_common_(). 1225290001Sglebius 1226290001Sglebius - If nodename!=NULL and servname is numeric, then we set 1227290001Sglebius servname=NULL when calling getaddrinfo, and post-process the 1228290001Sglebius result to set the ports on it. 1229290001Sglebius 1230290001Sglebius We test for this bug at runtime, since otherwise we can't have the 1231290001Sglebius same binary run on multiple BSD versions. 1232290001Sglebius 1233290001Sglebius - Some versions of Solaris believe that it's nice to leave to protocol 1234290001Sglebius field set to 0. We test for this so we can apply an appropriate 1235290001Sglebius workaround. 1236290001Sglebius*/ 1237290001Sglebiusstatic void 1238290001Sglebiustest_for_getaddrinfo_hacks(void) 1239290001Sglebius{ 1240290001Sglebius int r, r2; 1241290001Sglebius struct evutil_addrinfo *ai=NULL, *ai2=NULL; 1242290001Sglebius struct evutil_addrinfo hints; 1243290001Sglebius 1244290001Sglebius memset(&hints,0,sizeof(hints)); 1245290001Sglebius hints.ai_family = PF_UNSPEC; 1246290001Sglebius hints.ai_flags = 1247290001Sglebius#ifdef AI_NUMERICHOST 1248290001Sglebius AI_NUMERICHOST | 1249290001Sglebius#endif 1250290001Sglebius#ifdef AI_NUMERICSERV 1251290001Sglebius AI_NUMERICSERV | 1252290001Sglebius#endif 1253290001Sglebius 0; 1254290001Sglebius r = getaddrinfo("1.2.3.4", "80", &hints, &ai); 1255290001Sglebius hints.ai_socktype = SOCK_STREAM; 1256290001Sglebius r2 = getaddrinfo("1.2.3.4", "80", &hints, &ai2); 1257290001Sglebius if (r2 == 0 && r != 0) { 1258290001Sglebius need_numeric_port_hack_=1; 1259290001Sglebius } 1260290001Sglebius if (ai2 && ai2->ai_protocol == 0) { 1261290001Sglebius need_socktype_protocol_hack_=1; 1262290001Sglebius } 1263290001Sglebius 1264290001Sglebius if (ai) 1265290001Sglebius freeaddrinfo(ai); 1266290001Sglebius if (ai2) 1267290001Sglebius freeaddrinfo(ai2); 1268290001Sglebius tested_for_getaddrinfo_hacks=1; 1269290001Sglebius} 1270290001Sglebius 1271290001Sglebiusstatic inline int 1272290001Sglebiusneed_numeric_port_hack(void) 1273290001Sglebius{ 1274290001Sglebius if (!tested_for_getaddrinfo_hacks) 1275290001Sglebius test_for_getaddrinfo_hacks(); 1276290001Sglebius return need_numeric_port_hack_; 1277290001Sglebius} 1278290001Sglebius 1279290001Sglebiusstatic inline int 1280290001Sglebiusneed_socktype_protocol_hack(void) 1281290001Sglebius{ 1282290001Sglebius if (!tested_for_getaddrinfo_hacks) 1283290001Sglebius test_for_getaddrinfo_hacks(); 1284290001Sglebius return need_socktype_protocol_hack_; 1285290001Sglebius} 1286290001Sglebius 1287290001Sglebiusstatic void 1288290001Sglebiusapply_numeric_port_hack(int port, struct evutil_addrinfo **ai) 1289290001Sglebius{ 1290290001Sglebius /* Now we run through the list and set the ports on all of the 1291290001Sglebius * results where ports would make sense. */ 1292290001Sglebius for ( ; *ai; ai = &(*ai)->ai_next) { 1293290001Sglebius struct sockaddr *sa = (*ai)->ai_addr; 1294290001Sglebius if (sa && sa->sa_family == AF_INET) { 1295290001Sglebius struct sockaddr_in *sin = (struct sockaddr_in*)sa; 1296290001Sglebius sin->sin_port = htons(port); 1297290001Sglebius } else if (sa && sa->sa_family == AF_INET6) { 1298290001Sglebius struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)sa; 1299290001Sglebius sin6->sin6_port = htons(port); 1300290001Sglebius } else { 1301290001Sglebius /* A numeric port makes no sense here; remove this one 1302290001Sglebius * from the list. */ 1303290001Sglebius struct evutil_addrinfo *victim = *ai; 1304290001Sglebius *ai = victim->ai_next; 1305290001Sglebius victim->ai_next = NULL; 1306290001Sglebius freeaddrinfo(victim); 1307290001Sglebius } 1308290001Sglebius } 1309290001Sglebius} 1310290001Sglebius 1311290001Sglebiusstatic int 1312290001Sglebiusapply_socktype_protocol_hack(struct evutil_addrinfo *ai) 1313290001Sglebius{ 1314290001Sglebius struct evutil_addrinfo *ai_new; 1315290001Sglebius for (; ai; ai = ai->ai_next) { 1316290001Sglebius evutil_getaddrinfo_infer_protocols(ai); 1317290001Sglebius if (ai->ai_socktype || ai->ai_protocol) 1318290001Sglebius continue; 1319290001Sglebius ai_new = mm_malloc(sizeof(*ai_new)); 1320290001Sglebius if (!ai_new) 1321290001Sglebius return -1; 1322290001Sglebius memcpy(ai_new, ai, sizeof(*ai_new)); 1323290001Sglebius ai->ai_socktype = SOCK_STREAM; 1324290001Sglebius ai->ai_protocol = IPPROTO_TCP; 1325290001Sglebius ai_new->ai_socktype = SOCK_DGRAM; 1326290001Sglebius ai_new->ai_protocol = IPPROTO_UDP; 1327290001Sglebius 1328290001Sglebius ai_new->ai_next = ai->ai_next; 1329290001Sglebius ai->ai_next = ai_new; 1330290001Sglebius } 1331290001Sglebius return 0; 1332290001Sglebius} 1333290001Sglebius#endif 1334290001Sglebius 1335290001Sglebiusint 1336290001Sglebiusevutil_getaddrinfo(const char *nodename, const char *servname, 1337290001Sglebius const struct evutil_addrinfo *hints_in, struct evutil_addrinfo **res) 1338290001Sglebius{ 1339290001Sglebius#ifdef USE_NATIVE_GETADDRINFO 1340290001Sglebius struct evutil_addrinfo hints; 1341290001Sglebius int portnum=-1, need_np_hack, err; 1342290001Sglebius 1343290001Sglebius if (hints_in) { 1344290001Sglebius memcpy(&hints, hints_in, sizeof(hints)); 1345290001Sglebius } else { 1346290001Sglebius memset(&hints, 0, sizeof(hints)); 1347290001Sglebius hints.ai_family = PF_UNSPEC; 1348290001Sglebius } 1349290001Sglebius 1350290001Sglebius#ifndef AI_ADDRCONFIG 1351290001Sglebius /* Not every system has AI_ADDRCONFIG, so fake it. */ 1352290001Sglebius if (hints.ai_family == PF_UNSPEC && 1353290001Sglebius (hints.ai_flags & EVUTIL_AI_ADDRCONFIG)) { 1354290001Sglebius evutil_adjust_hints_for_addrconfig_(&hints); 1355290001Sglebius } 1356290001Sglebius#endif 1357290001Sglebius 1358290001Sglebius#ifndef AI_NUMERICSERV 1359290001Sglebius /* Not every system has AI_NUMERICSERV, so fake it. */ 1360290001Sglebius if (hints.ai_flags & EVUTIL_AI_NUMERICSERV) { 1361290001Sglebius if (servname && parse_numeric_servname(servname)<0) 1362290001Sglebius return EVUTIL_EAI_NONAME; 1363290001Sglebius } 1364290001Sglebius#endif 1365290001Sglebius 1366290001Sglebius /* Enough operating systems handle enough common non-resolve 1367290001Sglebius * cases here weirdly enough that we are better off just 1368290001Sglebius * overriding them. For example: 1369290001Sglebius * 1370290001Sglebius * - Windows doesn't like to infer the protocol from the 1371290001Sglebius * socket type, or fill in socket or protocol types much at 1372290001Sglebius * all. It also seems to do its own broken implicit 1373290001Sglebius * always-on version of AI_ADDRCONFIG that keeps it from 1374290001Sglebius * ever resolving even a literal IPv6 address when 1375290001Sglebius * ai_addrtype is PF_UNSPEC. 1376290001Sglebius */ 1377290001Sglebius#ifdef _WIN32 1378290001Sglebius { 1379290001Sglebius int tmp_port; 1380290001Sglebius err = evutil_getaddrinfo_common_(nodename,servname,&hints, 1381290001Sglebius res, &tmp_port); 1382290001Sglebius if (err == 0 || 1383290001Sglebius err == EVUTIL_EAI_MEMORY || 1384290001Sglebius err == EVUTIL_EAI_NONAME) 1385290001Sglebius return err; 1386290001Sglebius /* If we make it here, the system getaddrinfo can 1387290001Sglebius * have a crack at it. */ 1388290001Sglebius } 1389290001Sglebius#endif 1390290001Sglebius 1391290001Sglebius /* See documentation for need_numeric_port_hack above.*/ 1392290001Sglebius need_np_hack = need_numeric_port_hack() && servname && !hints.ai_socktype 1393290001Sglebius && ((portnum=parse_numeric_servname(servname)) >= 0); 1394290001Sglebius if (need_np_hack) { 1395290001Sglebius if (!nodename) 1396290001Sglebius return evutil_getaddrinfo_common_( 1397290001Sglebius NULL,servname,&hints, res, &portnum); 1398290001Sglebius servname = NULL; 1399290001Sglebius } 1400290001Sglebius 1401290001Sglebius if (need_socktype_protocol_hack()) { 1402290001Sglebius evutil_getaddrinfo_infer_protocols(&hints); 1403290001Sglebius } 1404290001Sglebius 1405290001Sglebius /* Make sure that we didn't actually steal any AI_FLAGS values that 1406290001Sglebius * the system is using. (This is a constant expression, and should ge 1407290001Sglebius * optimized out.) 1408290001Sglebius * 1409290001Sglebius * XXXX Turn this into a compile-time failure rather than a run-time 1410290001Sglebius * failure. 1411290001Sglebius */ 1412290001Sglebius EVUTIL_ASSERT((ALL_NONNATIVE_AI_FLAGS & ALL_NATIVE_AI_FLAGS) == 0); 1413290001Sglebius 1414290001Sglebius /* Clear any flags that only libevent understands. */ 1415290001Sglebius hints.ai_flags &= ~ALL_NONNATIVE_AI_FLAGS; 1416290001Sglebius 1417290001Sglebius err = getaddrinfo(nodename, servname, &hints, res); 1418290001Sglebius if (need_np_hack) 1419290001Sglebius apply_numeric_port_hack(portnum, res); 1420290001Sglebius 1421290001Sglebius if (need_socktype_protocol_hack()) { 1422290001Sglebius if (apply_socktype_protocol_hack(*res) < 0) { 1423290001Sglebius evutil_freeaddrinfo(*res); 1424290001Sglebius *res = NULL; 1425290001Sglebius return EVUTIL_EAI_MEMORY; 1426290001Sglebius } 1427290001Sglebius } 1428290001Sglebius return err; 1429290001Sglebius#else 1430290001Sglebius int port=0, err; 1431290001Sglebius struct hostent *ent = NULL; 1432290001Sglebius struct evutil_addrinfo hints; 1433290001Sglebius 1434290001Sglebius if (hints_in) { 1435290001Sglebius memcpy(&hints, hints_in, sizeof(hints)); 1436290001Sglebius } else { 1437290001Sglebius memset(&hints, 0, sizeof(hints)); 1438290001Sglebius hints.ai_family = PF_UNSPEC; 1439290001Sglebius } 1440290001Sglebius 1441290001Sglebius evutil_adjust_hints_for_addrconfig_(&hints); 1442290001Sglebius 1443290001Sglebius err = evutil_getaddrinfo_common_(nodename, servname, &hints, res, &port); 1444290001Sglebius if (err != EVUTIL_EAI_NEED_RESOLVE) { 1445290001Sglebius /* We either succeeded or failed. No need to continue */ 1446290001Sglebius return err; 1447290001Sglebius } 1448290001Sglebius 1449290001Sglebius err = 0; 1450290001Sglebius /* Use any of the various gethostbyname_r variants as available. */ 1451290001Sglebius { 1452290001Sglebius#ifdef EVENT__HAVE_GETHOSTBYNAME_R_6_ARG 1453290001Sglebius /* This one is what glibc provides. */ 1454290001Sglebius char buf[2048]; 1455290001Sglebius struct hostent hostent; 1456290001Sglebius int r; 1457290001Sglebius r = gethostbyname_r(nodename, &hostent, buf, sizeof(buf), &ent, 1458290001Sglebius &err); 1459290001Sglebius#elif defined(EVENT__HAVE_GETHOSTBYNAME_R_5_ARG) 1460290001Sglebius char buf[2048]; 1461290001Sglebius struct hostent hostent; 1462290001Sglebius ent = gethostbyname_r(nodename, &hostent, buf, sizeof(buf), 1463290001Sglebius &err); 1464290001Sglebius#elif defined(EVENT__HAVE_GETHOSTBYNAME_R_3_ARG) 1465290001Sglebius struct hostent_data data; 1466290001Sglebius struct hostent hostent; 1467290001Sglebius memset(&data, 0, sizeof(data)); 1468290001Sglebius err = gethostbyname_r(nodename, &hostent, &data); 1469290001Sglebius ent = err ? NULL : &hostent; 1470290001Sglebius#else 1471290001Sglebius /* fall back to gethostbyname. */ 1472290001Sglebius /* XXXX This needs a lock everywhere but Windows. */ 1473290001Sglebius ent = gethostbyname(nodename); 1474290001Sglebius#ifdef _WIN32 1475290001Sglebius err = WSAGetLastError(); 1476290001Sglebius#else 1477290001Sglebius err = h_errno; 1478290001Sglebius#endif 1479290001Sglebius#endif 1480290001Sglebius 1481290001Sglebius /* Now we have either ent or err set. */ 1482290001Sglebius if (!ent) { 1483290001Sglebius /* XXX is this right for windows ? */ 1484290001Sglebius switch (err) { 1485290001Sglebius case TRY_AGAIN: 1486290001Sglebius return EVUTIL_EAI_AGAIN; 1487290001Sglebius case NO_RECOVERY: 1488290001Sglebius default: 1489290001Sglebius return EVUTIL_EAI_FAIL; 1490290001Sglebius case HOST_NOT_FOUND: 1491290001Sglebius return EVUTIL_EAI_NONAME; 1492290001Sglebius case NO_ADDRESS: 1493290001Sglebius#if NO_DATA != NO_ADDRESS 1494290001Sglebius case NO_DATA: 1495290001Sglebius#endif 1496290001Sglebius return EVUTIL_EAI_NODATA; 1497290001Sglebius } 1498290001Sglebius } 1499290001Sglebius 1500290001Sglebius if (ent->h_addrtype != hints.ai_family && 1501290001Sglebius hints.ai_family != PF_UNSPEC) { 1502290001Sglebius /* This wasn't the type we were hoping for. Too bad 1503290001Sglebius * we never had a chance to ask gethostbyname for what 1504290001Sglebius * we wanted. */ 1505290001Sglebius return EVUTIL_EAI_NONAME; 1506290001Sglebius } 1507290001Sglebius 1508290001Sglebius /* Make sure we got _some_ answers. */ 1509290001Sglebius if (ent->h_length == 0) 1510290001Sglebius return EVUTIL_EAI_NODATA; 1511290001Sglebius 1512290001Sglebius /* If we got an address type we don't know how to make a 1513290001Sglebius sockaddr for, give up. */ 1514290001Sglebius if (ent->h_addrtype != PF_INET && ent->h_addrtype != PF_INET6) 1515290001Sglebius return EVUTIL_EAI_FAMILY; 1516290001Sglebius 1517290001Sglebius *res = addrinfo_from_hostent(ent, port, &hints); 1518290001Sglebius if (! *res) 1519290001Sglebius return EVUTIL_EAI_MEMORY; 1520290001Sglebius } 1521290001Sglebius 1522290001Sglebius return 0; 1523290001Sglebius#endif 1524290001Sglebius} 1525290001Sglebius 1526290001Sglebiusvoid 1527290001Sglebiusevutil_freeaddrinfo(struct evutil_addrinfo *ai) 1528290001Sglebius{ 1529290001Sglebius#ifdef EVENT__HAVE_GETADDRINFO 1530290001Sglebius if (!(ai->ai_flags & EVUTIL_AI_LIBEVENT_ALLOCATED)) { 1531290001Sglebius freeaddrinfo(ai); 1532290001Sglebius return; 1533290001Sglebius } 1534290001Sglebius#endif 1535290001Sglebius while (ai) { 1536290001Sglebius struct evutil_addrinfo *next = ai->ai_next; 1537290001Sglebius if (ai->ai_canonname) 1538290001Sglebius mm_free(ai->ai_canonname); 1539290001Sglebius mm_free(ai); 1540290001Sglebius ai = next; 1541290001Sglebius } 1542290001Sglebius} 1543290001Sglebius 1544290001Sglebiusstatic evdns_getaddrinfo_fn evdns_getaddrinfo_impl = NULL; 1545290001Sglebius 1546290001Sglebiusvoid 1547290001Sglebiusevutil_set_evdns_getaddrinfo_fn_(evdns_getaddrinfo_fn fn) 1548290001Sglebius{ 1549290001Sglebius if (!evdns_getaddrinfo_impl) 1550290001Sglebius evdns_getaddrinfo_impl = fn; 1551290001Sglebius} 1552290001Sglebius 1553290001Sglebius/* Internal helper function: act like evdns_getaddrinfo if dns_base is set; 1554290001Sglebius * otherwise do a blocking resolve and pass the result to the callback in the 1555290001Sglebius * way that evdns_getaddrinfo would. 1556290001Sglebius */ 1557290001Sglebiusint 1558290001Sglebiusevutil_getaddrinfo_async_(struct evdns_base *dns_base, 1559290001Sglebius const char *nodename, const char *servname, 1560290001Sglebius const struct evutil_addrinfo *hints_in, 1561290001Sglebius void (*cb)(int, struct evutil_addrinfo *, void *), void *arg) 1562290001Sglebius{ 1563290001Sglebius if (dns_base && evdns_getaddrinfo_impl) { 1564290001Sglebius evdns_getaddrinfo_impl( 1565290001Sglebius dns_base, nodename, servname, hints_in, cb, arg); 1566290001Sglebius } else { 1567290001Sglebius struct evutil_addrinfo *ai=NULL; 1568290001Sglebius int err; 1569290001Sglebius err = evutil_getaddrinfo(nodename, servname, hints_in, &ai); 1570290001Sglebius cb(err, ai, arg); 1571290001Sglebius } 1572290001Sglebius return 0; 1573290001Sglebius} 1574290001Sglebius 1575290001Sglebiusconst char * 1576290001Sglebiusevutil_gai_strerror(int err) 1577290001Sglebius{ 1578290001Sglebius /* As a sneaky side-benefit, this case statement will get most 1579290001Sglebius * compilers to tell us if any of the error codes we defined 1580290001Sglebius * conflict with the platform's native error codes. */ 1581290001Sglebius switch (err) { 1582290001Sglebius case EVUTIL_EAI_CANCEL: 1583290001Sglebius return "Request canceled"; 1584290001Sglebius case 0: 1585290001Sglebius return "No error"; 1586290001Sglebius 1587290001Sglebius case EVUTIL_EAI_ADDRFAMILY: 1588290001Sglebius return "address family for nodename not supported"; 1589290001Sglebius case EVUTIL_EAI_AGAIN: 1590290001Sglebius return "temporary failure in name resolution"; 1591290001Sglebius case EVUTIL_EAI_BADFLAGS: 1592290001Sglebius return "invalid value for ai_flags"; 1593290001Sglebius case EVUTIL_EAI_FAIL: 1594290001Sglebius return "non-recoverable failure in name resolution"; 1595290001Sglebius case EVUTIL_EAI_FAMILY: 1596290001Sglebius return "ai_family not supported"; 1597290001Sglebius case EVUTIL_EAI_MEMORY: 1598290001Sglebius return "memory allocation failure"; 1599290001Sglebius case EVUTIL_EAI_NODATA: 1600290001Sglebius return "no address associated with nodename"; 1601290001Sglebius case EVUTIL_EAI_NONAME: 1602290001Sglebius return "nodename nor servname provided, or not known"; 1603290001Sglebius case EVUTIL_EAI_SERVICE: 1604290001Sglebius return "servname not supported for ai_socktype"; 1605290001Sglebius case EVUTIL_EAI_SOCKTYPE: 1606290001Sglebius return "ai_socktype not supported"; 1607290001Sglebius case EVUTIL_EAI_SYSTEM: 1608290001Sglebius return "system error"; 1609290001Sglebius default: 1610290001Sglebius#if defined(USE_NATIVE_GETADDRINFO) && defined(_WIN32) 1611290001Sglebius return gai_strerrorA(err); 1612290001Sglebius#elif defined(USE_NATIVE_GETADDRINFO) 1613290001Sglebius return gai_strerror(err); 1614290001Sglebius#else 1615290001Sglebius return "Unknown error code"; 1616290001Sglebius#endif 1617290001Sglebius } 1618290001Sglebius} 1619290001Sglebius 1620290001Sglebius#ifdef _WIN32 1621290001Sglebius/* destructively remove a trailing line terminator from s */ 1622290001Sglebiusstatic void 1623290001Sglebiuschomp (char *s) 1624290001Sglebius{ 1625290001Sglebius size_t len; 1626290001Sglebius if (s && (len = strlen (s)) > 0 && s[len - 1] == '\n') { 1627290001Sglebius s[--len] = 0; 1628290001Sglebius if (len > 0 && s[len - 1] == '\r') 1629290001Sglebius s[--len] = 0; 1630290001Sglebius } 1631290001Sglebius} 1632290001Sglebius 1633290001Sglebius/* FormatMessage returns allocated strings, but evutil_socket_error_to_string 1634290001Sglebius * is supposed to return a string which is good indefinitely without having 1635290001Sglebius * to be freed. To make this work without leaking memory, we cache the 1636290001Sglebius * string the first time FormatMessage is called on a particular error 1637290001Sglebius * code, and then return the cached string on subsequent calls with the 1638290001Sglebius * same code. The strings aren't freed until libevent_global_shutdown 1639290001Sglebius * (or never). We use a linked list to cache the errors, because we 1640290001Sglebius * only expect there to be a few dozen, and that should be fast enough. 1641290001Sglebius */ 1642290001Sglebius 1643290001Sglebiusstruct cached_sock_errs_entry { 1644290001Sglebius HT_ENTRY(cached_sock_errs_entry) node; 1645290001Sglebius DWORD code; 1646290001Sglebius char *msg; /* allocated with LocalAlloc; free with LocalFree */ 1647290001Sglebius}; 1648290001Sglebius 1649290001Sglebiusstatic inline unsigned 1650290001Sglebiushash_cached_sock_errs(const struct cached_sock_errs_entry *e) 1651290001Sglebius{ 1652290001Sglebius /* Use Murmur3's 32-bit finalizer as an integer hash function */ 1653290001Sglebius DWORD h = e->code; 1654290001Sglebius h ^= h >> 16; 1655290001Sglebius h *= 0x85ebca6b; 1656290001Sglebius h ^= h >> 13; 1657290001Sglebius h *= 0xc2b2ae35; 1658290001Sglebius h ^= h >> 16; 1659290001Sglebius return h; 1660290001Sglebius} 1661290001Sglebius 1662290001Sglebiusstatic inline int 1663290001Sglebiuseq_cached_sock_errs(const struct cached_sock_errs_entry *a, 1664290001Sglebius const struct cached_sock_errs_entry *b) 1665290001Sglebius{ 1666290001Sglebius return a->code == b->code; 1667290001Sglebius} 1668290001Sglebius 1669290001Sglebius#ifndef EVENT__DISABLE_THREAD_SUPPORT 1670290001Sglebiusstatic void *windows_socket_errors_lock_ = NULL; 1671290001Sglebius#endif 1672290001Sglebius 1673290001Sglebiusstatic HT_HEAD(cached_sock_errs_map, cached_sock_errs_entry) 1674290001Sglebius windows_socket_errors = HT_INITIALIZER(); 1675290001Sglebius 1676290001SglebiusHT_PROTOTYPE(cached_sock_errs_map, 1677290001Sglebius cached_sock_errs_entry, 1678290001Sglebius node, 1679290001Sglebius hash_cached_sock_errs, 1680290001Sglebius eq_cached_sock_errs); 1681290001Sglebius 1682290001SglebiusHT_GENERATE(cached_sock_errs_map, 1683290001Sglebius cached_sock_errs_entry, 1684290001Sglebius node, 1685290001Sglebius hash_cached_sock_errs, 1686290001Sglebius eq_cached_sock_errs, 1687290001Sglebius 0.5, 1688290001Sglebius mm_malloc, 1689290001Sglebius mm_realloc, 1690290001Sglebius mm_free); 1691290001Sglebius 1692290001Sglebius/** Equivalent to strerror, but for windows socket errors. */ 1693290001Sglebiusconst char * 1694290001Sglebiusevutil_socket_error_to_string(int errcode) 1695290001Sglebius{ 1696290001Sglebius struct cached_sock_errs_entry *errs, *newerr, find; 1697290001Sglebius char *msg = NULL; 1698290001Sglebius 1699290001Sglebius EVLOCK_LOCK(windows_socket_errors_lock_, 0); 1700290001Sglebius 1701290001Sglebius find.code = errcode; 1702290001Sglebius errs = HT_FIND(cached_sock_errs_map, &windows_socket_errors, &find); 1703290001Sglebius if (errs) { 1704290001Sglebius msg = errs->msg; 1705290001Sglebius goto done; 1706290001Sglebius } 1707290001Sglebius 1708290001Sglebius if (0 != FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | 1709290001Sglebius FORMAT_MESSAGE_IGNORE_INSERTS | 1710290001Sglebius FORMAT_MESSAGE_ALLOCATE_BUFFER, 1711290001Sglebius NULL, errcode, 0, (LPTSTR)&msg, 0, NULL)) 1712290001Sglebius chomp (msg); /* because message has trailing newline */ 1713290001Sglebius else { 1714290001Sglebius size_t len = 50; 1715290001Sglebius /* use LocalAlloc because FormatMessage does */ 1716290001Sglebius msg = LocalAlloc(LMEM_FIXED, len); 1717290001Sglebius if (!msg) { 1718290001Sglebius msg = (char *)"LocalAlloc failed during Winsock error"; 1719290001Sglebius goto done; 1720290001Sglebius } 1721290001Sglebius evutil_snprintf(msg, len, "winsock error 0x%08x", errcode); 1722290001Sglebius } 1723290001Sglebius 1724290001Sglebius newerr = (struct cached_sock_errs_entry *) 1725290001Sglebius mm_malloc(sizeof (struct cached_sock_errs_entry)); 1726290001Sglebius 1727290001Sglebius if (!newerr) { 1728290001Sglebius LocalFree(msg); 1729290001Sglebius msg = (char *)"malloc failed during Winsock error"; 1730290001Sglebius goto done; 1731290001Sglebius } 1732290001Sglebius 1733290001Sglebius newerr->code = errcode; 1734290001Sglebius newerr->msg = msg; 1735290001Sglebius HT_INSERT(cached_sock_errs_map, &windows_socket_errors, newerr); 1736290001Sglebius 1737290001Sglebius done: 1738290001Sglebius EVLOCK_UNLOCK(windows_socket_errors_lock_, 0); 1739290001Sglebius 1740290001Sglebius return msg; 1741290001Sglebius} 1742290001Sglebius 1743290001Sglebius#ifndef EVENT__DISABLE_THREAD_SUPPORT 1744290001Sglebiusint 1745290001Sglebiusevutil_global_setup_locks_(const int enable_locks) 1746290001Sglebius{ 1747290001Sglebius EVTHREAD_SETUP_GLOBAL_LOCK(windows_socket_errors_lock_, 0); 1748290001Sglebius return 0; 1749290001Sglebius} 1750290001Sglebius#endif 1751290001Sglebius 1752290001Sglebiusstatic void 1753290001Sglebiusevutil_free_sock_err_globals(void) 1754290001Sglebius{ 1755290001Sglebius struct cached_sock_errs_entry **errs, *tofree; 1756290001Sglebius 1757290001Sglebius for (errs = HT_START(cached_sock_errs_map, &windows_socket_errors) 1758290001Sglebius ; errs; ) { 1759290001Sglebius tofree = *errs; 1760290001Sglebius errs = HT_NEXT_RMV(cached_sock_errs_map, 1761290001Sglebius &windows_socket_errors, 1762290001Sglebius errs); 1763290001Sglebius LocalFree(tofree->msg); 1764290001Sglebius mm_free(tofree); 1765290001Sglebius } 1766290001Sglebius 1767290001Sglebius HT_CLEAR(cached_sock_errs_map, &windows_socket_errors); 1768290001Sglebius 1769290001Sglebius#ifndef EVENT__DISABLE_THREAD_SUPPORT 1770290001Sglebius if (windows_socket_errors_lock_ != NULL) { 1771290001Sglebius EVTHREAD_FREE_LOCK(windows_socket_errors_lock_, 0); 1772290001Sglebius windows_socket_errors_lock_ = NULL; 1773290001Sglebius } 1774290001Sglebius#endif 1775290001Sglebius} 1776290001Sglebius 1777290001Sglebius#else 1778290001Sglebius 1779290001Sglebius#ifndef EVENT__DISABLE_THREAD_SUPPORT 1780290001Sglebiusint 1781290001Sglebiusevutil_global_setup_locks_(const int enable_locks) 1782290001Sglebius{ 1783290001Sglebius return 0; 1784290001Sglebius} 1785290001Sglebius#endif 1786290001Sglebius 1787290001Sglebiusstatic void 1788290001Sglebiusevutil_free_sock_err_globals(void) 1789290001Sglebius{ 1790290001Sglebius} 1791290001Sglebius 1792290001Sglebius#endif 1793290001Sglebius 1794290001Sglebiusint 1795290001Sglebiusevutil_snprintf(char *buf, size_t buflen, const char *format, ...) 1796290001Sglebius{ 1797290001Sglebius int r; 1798290001Sglebius va_list ap; 1799290001Sglebius va_start(ap, format); 1800290001Sglebius r = evutil_vsnprintf(buf, buflen, format, ap); 1801290001Sglebius va_end(ap); 1802290001Sglebius return r; 1803290001Sglebius} 1804290001Sglebius 1805290001Sglebiusint 1806290001Sglebiusevutil_vsnprintf(char *buf, size_t buflen, const char *format, va_list ap) 1807290001Sglebius{ 1808290001Sglebius int r; 1809290001Sglebius if (!buflen) 1810290001Sglebius return 0; 1811290001Sglebius#if defined(_MSC_VER) || defined(_WIN32) 1812290001Sglebius r = _vsnprintf(buf, buflen, format, ap); 1813290001Sglebius if (r < 0) 1814290001Sglebius r = _vscprintf(format, ap); 1815290001Sglebius#elif defined(sgi) 1816290001Sglebius /* Make sure we always use the correct vsnprintf on IRIX */ 1817290001Sglebius extern int _xpg5_vsnprintf(char * __restrict, 1818290001Sglebius __SGI_LIBC_NAMESPACE_QUALIFIER size_t, 1819290001Sglebius const char * __restrict, /* va_list */ char *); 1820290001Sglebius 1821290001Sglebius r = _xpg5_vsnprintf(buf, buflen, format, ap); 1822290001Sglebius#else 1823290001Sglebius r = vsnprintf(buf, buflen, format, ap); 1824290001Sglebius#endif 1825290001Sglebius buf[buflen-1] = '\0'; 1826290001Sglebius return r; 1827290001Sglebius} 1828290001Sglebius 1829290001Sglebius#define USE_INTERNAL_NTOP 1830290001Sglebius#define USE_INTERNAL_PTON 1831290001Sglebius 1832290001Sglebiusconst char * 1833290001Sglebiusevutil_inet_ntop(int af, const void *src, char *dst, size_t len) 1834290001Sglebius{ 1835290001Sglebius#if defined(EVENT__HAVE_INET_NTOP) && !defined(USE_INTERNAL_NTOP) 1836290001Sglebius return inet_ntop(af, src, dst, len); 1837290001Sglebius#else 1838290001Sglebius if (af == AF_INET) { 1839290001Sglebius const struct in_addr *in = src; 1840290001Sglebius const ev_uint32_t a = ntohl(in->s_addr); 1841290001Sglebius int r; 1842290001Sglebius r = evutil_snprintf(dst, len, "%d.%d.%d.%d", 1843290001Sglebius (int)(ev_uint8_t)((a>>24)&0xff), 1844290001Sglebius (int)(ev_uint8_t)((a>>16)&0xff), 1845290001Sglebius (int)(ev_uint8_t)((a>>8 )&0xff), 1846290001Sglebius (int)(ev_uint8_t)((a )&0xff)); 1847290001Sglebius if (r<0||(size_t)r>=len) 1848290001Sglebius return NULL; 1849290001Sglebius else 1850290001Sglebius return dst; 1851290001Sglebius#ifdef AF_INET6 1852290001Sglebius } else if (af == AF_INET6) { 1853290001Sglebius const struct in6_addr *addr = src; 1854290001Sglebius char buf[64], *cp; 1855290001Sglebius int longestGapLen = 0, longestGapPos = -1, i, 1856290001Sglebius curGapPos = -1, curGapLen = 0; 1857290001Sglebius ev_uint16_t words[8]; 1858290001Sglebius for (i = 0; i < 8; ++i) { 1859290001Sglebius words[i] = 1860290001Sglebius (((ev_uint16_t)addr->s6_addr[2*i])<<8) + addr->s6_addr[2*i+1]; 1861290001Sglebius } 1862290001Sglebius if (words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && 1863290001Sglebius words[4] == 0 && ((words[5] == 0 && words[6] && words[7]) || 1864290001Sglebius (words[5] == 0xffff))) { 1865290001Sglebius /* This is an IPv4 address. */ 1866290001Sglebius if (words[5] == 0) { 1867290001Sglebius evutil_snprintf(buf, sizeof(buf), "::%d.%d.%d.%d", 1868290001Sglebius addr->s6_addr[12], addr->s6_addr[13], 1869290001Sglebius addr->s6_addr[14], addr->s6_addr[15]); 1870290001Sglebius } else { 1871290001Sglebius evutil_snprintf(buf, sizeof(buf), "::%x:%d.%d.%d.%d", words[5], 1872290001Sglebius addr->s6_addr[12], addr->s6_addr[13], 1873290001Sglebius addr->s6_addr[14], addr->s6_addr[15]); 1874290001Sglebius } 1875290001Sglebius if (strlen(buf) > len) 1876290001Sglebius return NULL; 1877290001Sglebius strlcpy(dst, buf, len); 1878290001Sglebius return dst; 1879290001Sglebius } 1880290001Sglebius i = 0; 1881290001Sglebius while (i < 8) { 1882290001Sglebius if (words[i] == 0) { 1883290001Sglebius curGapPos = i++; 1884290001Sglebius curGapLen = 1; 1885290001Sglebius while (i<8 && words[i] == 0) { 1886290001Sglebius ++i; ++curGapLen; 1887290001Sglebius } 1888290001Sglebius if (curGapLen > longestGapLen) { 1889290001Sglebius longestGapPos = curGapPos; 1890290001Sglebius longestGapLen = curGapLen; 1891290001Sglebius } 1892290001Sglebius } else { 1893290001Sglebius ++i; 1894290001Sglebius } 1895290001Sglebius } 1896290001Sglebius if (longestGapLen<=1) 1897290001Sglebius longestGapPos = -1; 1898290001Sglebius 1899290001Sglebius cp = buf; 1900290001Sglebius for (i = 0; i < 8; ++i) { 1901290001Sglebius if (words[i] == 0 && longestGapPos == i) { 1902290001Sglebius if (i == 0) 1903290001Sglebius *cp++ = ':'; 1904290001Sglebius *cp++ = ':'; 1905290001Sglebius while (i < 8 && words[i] == 0) 1906290001Sglebius ++i; 1907290001Sglebius --i; /* to compensate for loop increment. */ 1908290001Sglebius } else { 1909290001Sglebius evutil_snprintf(cp, 1910290001Sglebius sizeof(buf)-(cp-buf), "%x", (unsigned)words[i]); 1911290001Sglebius cp += strlen(cp); 1912290001Sglebius if (i != 7) 1913290001Sglebius *cp++ = ':'; 1914290001Sglebius } 1915290001Sglebius } 1916290001Sglebius *cp = '\0'; 1917290001Sglebius if (strlen(buf) > len) 1918290001Sglebius return NULL; 1919290001Sglebius strlcpy(dst, buf, len); 1920290001Sglebius return dst; 1921290001Sglebius#endif 1922290001Sglebius } else { 1923290001Sglebius return NULL; 1924290001Sglebius } 1925290001Sglebius#endif 1926290001Sglebius} 1927290001Sglebius 1928290001Sglebiusint 1929290001Sglebiusevutil_inet_pton(int af, const char *src, void *dst) 1930290001Sglebius{ 1931290001Sglebius#if defined(EVENT__HAVE_INET_PTON) && !defined(USE_INTERNAL_PTON) 1932290001Sglebius return inet_pton(af, src, dst); 1933290001Sglebius#else 1934290001Sglebius if (af == AF_INET) { 1935290001Sglebius unsigned a,b,c,d; 1936290001Sglebius char more; 1937290001Sglebius struct in_addr *addr = dst; 1938290001Sglebius if (sscanf(src, "%u.%u.%u.%u%c", &a,&b,&c,&d,&more) != 4) 1939290001Sglebius return 0; 1940290001Sglebius if (a > 255) return 0; 1941290001Sglebius if (b > 255) return 0; 1942290001Sglebius if (c > 255) return 0; 1943290001Sglebius if (d > 255) return 0; 1944290001Sglebius addr->s_addr = htonl((a<<24) | (b<<16) | (c<<8) | d); 1945290001Sglebius return 1; 1946290001Sglebius#ifdef AF_INET6 1947290001Sglebius } else if (af == AF_INET6) { 1948290001Sglebius struct in6_addr *out = dst; 1949290001Sglebius ev_uint16_t words[8]; 1950290001Sglebius int gapPos = -1, i, setWords=0; 1951290001Sglebius const char *dot = strchr(src, '.'); 1952290001Sglebius const char *eow; /* end of words. */ 1953290001Sglebius if (dot == src) 1954290001Sglebius return 0; 1955290001Sglebius else if (!dot) 1956290001Sglebius eow = src+strlen(src); 1957290001Sglebius else { 1958290001Sglebius unsigned byte1,byte2,byte3,byte4; 1959290001Sglebius char more; 1960290001Sglebius for (eow = dot-1; eow >= src && EVUTIL_ISDIGIT_(*eow); --eow) 1961290001Sglebius ; 1962290001Sglebius ++eow; 1963290001Sglebius 1964290001Sglebius /* We use "scanf" because some platform inet_aton()s are too lax 1965290001Sglebius * about IPv4 addresses of the form "1.2.3" */ 1966290001Sglebius if (sscanf(eow, "%u.%u.%u.%u%c", 1967290001Sglebius &byte1,&byte2,&byte3,&byte4,&more) != 4) 1968290001Sglebius return 0; 1969290001Sglebius 1970290001Sglebius if (byte1 > 255 || 1971290001Sglebius byte2 > 255 || 1972290001Sglebius byte3 > 255 || 1973290001Sglebius byte4 > 255) 1974290001Sglebius return 0; 1975290001Sglebius 1976290001Sglebius words[6] = (byte1<<8) | byte2; 1977290001Sglebius words[7] = (byte3<<8) | byte4; 1978290001Sglebius setWords += 2; 1979290001Sglebius } 1980290001Sglebius 1981290001Sglebius i = 0; 1982290001Sglebius while (src < eow) { 1983290001Sglebius if (i > 7) 1984290001Sglebius return 0; 1985290001Sglebius if (EVUTIL_ISXDIGIT_(*src)) { 1986290001Sglebius char *next; 1987290001Sglebius long r = strtol(src, &next, 16); 1988290001Sglebius if (next > 4+src) 1989290001Sglebius return 0; 1990290001Sglebius if (next == src) 1991290001Sglebius return 0; 1992290001Sglebius if (r<0 || r>65536) 1993290001Sglebius return 0; 1994290001Sglebius 1995290001Sglebius words[i++] = (ev_uint16_t)r; 1996290001Sglebius setWords++; 1997290001Sglebius src = next; 1998290001Sglebius if (*src != ':' && src != eow) 1999290001Sglebius return 0; 2000290001Sglebius ++src; 2001290001Sglebius } else if (*src == ':' && i > 0 && gapPos==-1) { 2002290001Sglebius gapPos = i; 2003290001Sglebius ++src; 2004290001Sglebius } else if (*src == ':' && i == 0 && src[1] == ':' && gapPos==-1) { 2005290001Sglebius gapPos = i; 2006290001Sglebius src += 2; 2007290001Sglebius } else { 2008290001Sglebius return 0; 2009290001Sglebius } 2010290001Sglebius } 2011290001Sglebius 2012290001Sglebius if (setWords > 8 || 2013290001Sglebius (setWords == 8 && gapPos != -1) || 2014290001Sglebius (setWords < 8 && gapPos == -1)) 2015290001Sglebius return 0; 2016290001Sglebius 2017290001Sglebius if (gapPos >= 0) { 2018290001Sglebius int nToMove = setWords - (dot ? 2 : 0) - gapPos; 2019290001Sglebius int gapLen = 8 - setWords; 2020290001Sglebius /* assert(nToMove >= 0); */ 2021290001Sglebius if (nToMove < 0) 2022290001Sglebius return -1; /* should be impossible */ 2023290001Sglebius memmove(&words[gapPos+gapLen], &words[gapPos], 2024290001Sglebius sizeof(ev_uint16_t)*nToMove); 2025290001Sglebius memset(&words[gapPos], 0, sizeof(ev_uint16_t)*gapLen); 2026290001Sglebius } 2027290001Sglebius for (i = 0; i < 8; ++i) { 2028290001Sglebius out->s6_addr[2*i ] = words[i] >> 8; 2029290001Sglebius out->s6_addr[2*i+1] = words[i] & 0xff; 2030290001Sglebius } 2031290001Sglebius 2032290001Sglebius return 1; 2033290001Sglebius#endif 2034290001Sglebius } else { 2035290001Sglebius return -1; 2036290001Sglebius } 2037290001Sglebius#endif 2038290001Sglebius} 2039290001Sglebius 2040290001Sglebiusint 2041290001Sglebiusevutil_parse_sockaddr_port(const char *ip_as_string, struct sockaddr *out, int *outlen) 2042290001Sglebius{ 2043290001Sglebius int port; 2044290001Sglebius char buf[128]; 2045290001Sglebius const char *cp, *addr_part, *port_part; 2046290001Sglebius int is_ipv6; 2047290001Sglebius /* recognized formats are: 2048290001Sglebius * [ipv6]:port 2049290001Sglebius * ipv6 2050290001Sglebius * [ipv6] 2051290001Sglebius * ipv4:port 2052290001Sglebius * ipv4 2053290001Sglebius */ 2054290001Sglebius 2055290001Sglebius cp = strchr(ip_as_string, ':'); 2056290001Sglebius if (*ip_as_string == '[') { 2057290001Sglebius int len; 2058290001Sglebius if (!(cp = strchr(ip_as_string, ']'))) { 2059290001Sglebius return -1; 2060290001Sglebius } 2061290001Sglebius len = (int) ( cp-(ip_as_string + 1) ); 2062290001Sglebius if (len > (int)sizeof(buf)-1) { 2063290001Sglebius return -1; 2064290001Sglebius } 2065290001Sglebius memcpy(buf, ip_as_string+1, len); 2066290001Sglebius buf[len] = '\0'; 2067290001Sglebius addr_part = buf; 2068290001Sglebius if (cp[1] == ':') 2069290001Sglebius port_part = cp+2; 2070290001Sglebius else 2071290001Sglebius port_part = NULL; 2072290001Sglebius is_ipv6 = 1; 2073290001Sglebius } else if (cp && strchr(cp+1, ':')) { 2074290001Sglebius is_ipv6 = 1; 2075290001Sglebius addr_part = ip_as_string; 2076290001Sglebius port_part = NULL; 2077290001Sglebius } else if (cp) { 2078290001Sglebius is_ipv6 = 0; 2079290001Sglebius if (cp - ip_as_string > (int)sizeof(buf)-1) { 2080290001Sglebius return -1; 2081290001Sglebius } 2082290001Sglebius memcpy(buf, ip_as_string, cp-ip_as_string); 2083290001Sglebius buf[cp-ip_as_string] = '\0'; 2084290001Sglebius addr_part = buf; 2085290001Sglebius port_part = cp+1; 2086290001Sglebius } else { 2087290001Sglebius addr_part = ip_as_string; 2088290001Sglebius port_part = NULL; 2089290001Sglebius is_ipv6 = 0; 2090290001Sglebius } 2091290001Sglebius 2092290001Sglebius if (port_part == NULL) { 2093290001Sglebius port = 0; 2094290001Sglebius } else { 2095290001Sglebius port = atoi(port_part); 2096290001Sglebius if (port <= 0 || port > 65535) { 2097290001Sglebius return -1; 2098290001Sglebius } 2099290001Sglebius } 2100290001Sglebius 2101290001Sglebius if (!addr_part) 2102290001Sglebius return -1; /* Should be impossible. */ 2103290001Sglebius#ifdef AF_INET6 2104290001Sglebius if (is_ipv6) 2105290001Sglebius { 2106290001Sglebius struct sockaddr_in6 sin6; 2107290001Sglebius memset(&sin6, 0, sizeof(sin6)); 2108290001Sglebius#ifdef EVENT__HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN 2109290001Sglebius sin6.sin6_len = sizeof(sin6); 2110290001Sglebius#endif 2111290001Sglebius sin6.sin6_family = AF_INET6; 2112290001Sglebius sin6.sin6_port = htons(port); 2113290001Sglebius if (1 != evutil_inet_pton(AF_INET6, addr_part, &sin6.sin6_addr)) 2114290001Sglebius return -1; 2115290001Sglebius if ((int)sizeof(sin6) > *outlen) 2116290001Sglebius return -1; 2117290001Sglebius memset(out, 0, *outlen); 2118290001Sglebius memcpy(out, &sin6, sizeof(sin6)); 2119290001Sglebius *outlen = sizeof(sin6); 2120290001Sglebius return 0; 2121290001Sglebius } 2122290001Sglebius else 2123290001Sglebius#endif 2124290001Sglebius { 2125290001Sglebius struct sockaddr_in sin; 2126290001Sglebius memset(&sin, 0, sizeof(sin)); 2127290001Sglebius#ifdef EVENT__HAVE_STRUCT_SOCKADDR_IN_SIN_LEN 2128290001Sglebius sin.sin_len = sizeof(sin); 2129290001Sglebius#endif 2130290001Sglebius sin.sin_family = AF_INET; 2131290001Sglebius sin.sin_port = htons(port); 2132290001Sglebius if (1 != evutil_inet_pton(AF_INET, addr_part, &sin.sin_addr)) 2133290001Sglebius return -1; 2134290001Sglebius if ((int)sizeof(sin) > *outlen) 2135290001Sglebius return -1; 2136290001Sglebius memset(out, 0, *outlen); 2137290001Sglebius memcpy(out, &sin, sizeof(sin)); 2138290001Sglebius *outlen = sizeof(sin); 2139290001Sglebius return 0; 2140290001Sglebius } 2141290001Sglebius} 2142290001Sglebius 2143290001Sglebiusconst char * 2144290001Sglebiusevutil_format_sockaddr_port_(const struct sockaddr *sa, char *out, size_t outlen) 2145290001Sglebius{ 2146290001Sglebius char b[128]; 2147290001Sglebius const char *res=NULL; 2148290001Sglebius int port; 2149290001Sglebius if (sa->sa_family == AF_INET) { 2150290001Sglebius const struct sockaddr_in *sin = (const struct sockaddr_in*)sa; 2151290001Sglebius res = evutil_inet_ntop(AF_INET, &sin->sin_addr,b,sizeof(b)); 2152290001Sglebius port = ntohs(sin->sin_port); 2153290001Sglebius if (res) { 2154290001Sglebius evutil_snprintf(out, outlen, "%s:%d", b, port); 2155290001Sglebius return out; 2156290001Sglebius } 2157290001Sglebius } else if (sa->sa_family == AF_INET6) { 2158290001Sglebius const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6*)sa; 2159290001Sglebius res = evutil_inet_ntop(AF_INET6, &sin6->sin6_addr,b,sizeof(b)); 2160290001Sglebius port = ntohs(sin6->sin6_port); 2161290001Sglebius if (res) { 2162290001Sglebius evutil_snprintf(out, outlen, "[%s]:%d", b, port); 2163290001Sglebius return out; 2164290001Sglebius } 2165290001Sglebius } 2166290001Sglebius 2167290001Sglebius evutil_snprintf(out, outlen, "<addr with socktype %d>", 2168290001Sglebius (int)sa->sa_family); 2169290001Sglebius return out; 2170290001Sglebius} 2171290001Sglebius 2172290001Sglebiusint 2173290001Sglebiusevutil_sockaddr_cmp(const struct sockaddr *sa1, const struct sockaddr *sa2, 2174290001Sglebius int include_port) 2175290001Sglebius{ 2176290001Sglebius int r; 2177290001Sglebius if (0 != (r = (sa1->sa_family - sa2->sa_family))) 2178290001Sglebius return r; 2179290001Sglebius 2180290001Sglebius if (sa1->sa_family == AF_INET) { 2181290001Sglebius const struct sockaddr_in *sin1, *sin2; 2182290001Sglebius sin1 = (const struct sockaddr_in *)sa1; 2183290001Sglebius sin2 = (const struct sockaddr_in *)sa2; 2184290001Sglebius if (sin1->sin_addr.s_addr < sin2->sin_addr.s_addr) 2185290001Sglebius return -1; 2186290001Sglebius else if (sin1->sin_addr.s_addr > sin2->sin_addr.s_addr) 2187290001Sglebius return 1; 2188290001Sglebius else if (include_port && 2189290001Sglebius (r = ((int)sin1->sin_port - (int)sin2->sin_port))) 2190290001Sglebius return r; 2191290001Sglebius else 2192290001Sglebius return 0; 2193290001Sglebius } 2194290001Sglebius#ifdef AF_INET6 2195290001Sglebius else if (sa1->sa_family == AF_INET6) { 2196290001Sglebius const struct sockaddr_in6 *sin1, *sin2; 2197290001Sglebius sin1 = (const struct sockaddr_in6 *)sa1; 2198290001Sglebius sin2 = (const struct sockaddr_in6 *)sa2; 2199290001Sglebius if ((r = memcmp(sin1->sin6_addr.s6_addr, sin2->sin6_addr.s6_addr, 16))) 2200290001Sglebius return r; 2201290001Sglebius else if (include_port && 2202290001Sglebius (r = ((int)sin1->sin6_port - (int)sin2->sin6_port))) 2203290001Sglebius return r; 2204290001Sglebius else 2205290001Sglebius return 0; 2206290001Sglebius } 2207290001Sglebius#endif 2208290001Sglebius return 1; 2209290001Sglebius} 2210290001Sglebius 2211290001Sglebius/* Tables to implement ctypes-replacement EVUTIL_IS*() functions. Each table 2212290001Sglebius * has 256 bits to look up whether a character is in some set or not. This 2213290001Sglebius * fails on non-ASCII platforms, but so does every other place where we 2214290001Sglebius * take a char and write it onto the network. 2215290001Sglebius **/ 2216290001Sglebiusstatic const ev_uint32_t EVUTIL_ISALPHA_TABLE[8] = 2217290001Sglebius { 0, 0, 0x7fffffe, 0x7fffffe, 0, 0, 0, 0 }; 2218290001Sglebiusstatic const ev_uint32_t EVUTIL_ISALNUM_TABLE[8] = 2219290001Sglebius { 0, 0x3ff0000, 0x7fffffe, 0x7fffffe, 0, 0, 0, 0 }; 2220290001Sglebiusstatic const ev_uint32_t EVUTIL_ISSPACE_TABLE[8] = { 0x3e00, 0x1, 0, 0, 0, 0, 0, 0 }; 2221290001Sglebiusstatic const ev_uint32_t EVUTIL_ISXDIGIT_TABLE[8] = 2222290001Sglebius { 0, 0x3ff0000, 0x7e, 0x7e, 0, 0, 0, 0 }; 2223290001Sglebiusstatic const ev_uint32_t EVUTIL_ISDIGIT_TABLE[8] = { 0, 0x3ff0000, 0, 0, 0, 0, 0, 0 }; 2224290001Sglebiusstatic const ev_uint32_t EVUTIL_ISPRINT_TABLE[8] = 2225290001Sglebius { 0, 0xffffffff, 0xffffffff, 0x7fffffff, 0, 0, 0, 0x0 }; 2226290001Sglebiusstatic const ev_uint32_t EVUTIL_ISUPPER_TABLE[8] = { 0, 0, 0x7fffffe, 0, 0, 0, 0, 0 }; 2227290001Sglebiusstatic const ev_uint32_t EVUTIL_ISLOWER_TABLE[8] = { 0, 0, 0, 0x7fffffe, 0, 0, 0, 0 }; 2228290001Sglebius/* Upper-casing and lowercasing tables to map characters to upper/lowercase 2229290001Sglebius * equivalents. */ 2230290001Sglebiusstatic const unsigned char EVUTIL_TOUPPER_TABLE[256] = { 2231290001Sglebius 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 2232290001Sglebius 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, 2233290001Sglebius 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, 2234290001Sglebius 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63, 2235290001Sglebius 64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79, 2236290001Sglebius 80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95, 2237290001Sglebius 96,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79, 2238290001Sglebius 80,81,82,83,84,85,86,87,88,89,90,123,124,125,126,127, 2239290001Sglebius 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, 2240290001Sglebius 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, 2241290001Sglebius 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, 2242290001Sglebius 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, 2243290001Sglebius 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, 2244290001Sglebius 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, 2245290001Sglebius 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, 2246290001Sglebius 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255, 2247290001Sglebius}; 2248290001Sglebiusstatic const unsigned char EVUTIL_TOLOWER_TABLE[256] = { 2249290001Sglebius 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 2250290001Sglebius 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, 2251290001Sglebius 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, 2252290001Sglebius 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63, 2253290001Sglebius 64,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111, 2254290001Sglebius 112,113,114,115,116,117,118,119,120,121,122,91,92,93,94,95, 2255290001Sglebius 96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111, 2256290001Sglebius 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, 2257290001Sglebius 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, 2258290001Sglebius 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, 2259290001Sglebius 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, 2260290001Sglebius 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, 2261290001Sglebius 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, 2262290001Sglebius 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, 2263290001Sglebius 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, 2264290001Sglebius 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255, 2265290001Sglebius}; 2266290001Sglebius 2267290001Sglebius#define IMPL_CTYPE_FN(name) \ 2268290001Sglebius int EVUTIL_##name##_(char c) { \ 2269290001Sglebius ev_uint8_t u = c; \ 2270290001Sglebius return !!(EVUTIL_##name##_TABLE[(u >> 5) & 7] & (1 << (u & 31))); \ 2271290001Sglebius } 2272290001SglebiusIMPL_CTYPE_FN(ISALPHA) 2273290001SglebiusIMPL_CTYPE_FN(ISALNUM) 2274290001SglebiusIMPL_CTYPE_FN(ISSPACE) 2275290001SglebiusIMPL_CTYPE_FN(ISDIGIT) 2276290001SglebiusIMPL_CTYPE_FN(ISXDIGIT) 2277290001SglebiusIMPL_CTYPE_FN(ISPRINT) 2278290001SglebiusIMPL_CTYPE_FN(ISLOWER) 2279290001SglebiusIMPL_CTYPE_FN(ISUPPER) 2280290001Sglebius 2281290001Sglebiuschar EVUTIL_TOLOWER_(char c) 2282290001Sglebius{ 2283290001Sglebius return ((char)EVUTIL_TOLOWER_TABLE[(ev_uint8_t)c]); 2284290001Sglebius} 2285290001Sglebiuschar EVUTIL_TOUPPER_(char c) 2286290001Sglebius{ 2287290001Sglebius return ((char)EVUTIL_TOUPPER_TABLE[(ev_uint8_t)c]); 2288290001Sglebius} 2289290001Sglebiusint 2290290001Sglebiusevutil_ascii_strcasecmp(const char *s1, const char *s2) 2291290001Sglebius{ 2292290001Sglebius char c1, c2; 2293290001Sglebius while (1) { 2294290001Sglebius c1 = EVUTIL_TOLOWER_(*s1++); 2295290001Sglebius c2 = EVUTIL_TOLOWER_(*s2++); 2296290001Sglebius if (c1 < c2) 2297290001Sglebius return -1; 2298290001Sglebius else if (c1 > c2) 2299290001Sglebius return 1; 2300290001Sglebius else if (c1 == 0) 2301290001Sglebius return 0; 2302290001Sglebius } 2303290001Sglebius} 2304290001Sglebiusint evutil_ascii_strncasecmp(const char *s1, const char *s2, size_t n) 2305290001Sglebius{ 2306290001Sglebius char c1, c2; 2307290001Sglebius while (n--) { 2308290001Sglebius c1 = EVUTIL_TOLOWER_(*s1++); 2309290001Sglebius c2 = EVUTIL_TOLOWER_(*s2++); 2310290001Sglebius if (c1 < c2) 2311290001Sglebius return -1; 2312290001Sglebius else if (c1 > c2) 2313290001Sglebius return 1; 2314290001Sglebius else if (c1 == 0) 2315290001Sglebius return 0; 2316290001Sglebius } 2317290001Sglebius return 0; 2318290001Sglebius} 2319290001Sglebius 2320290001Sglebiusvoid 2321290001Sglebiusevutil_rtrim_lws_(char *str) 2322290001Sglebius{ 2323290001Sglebius char *cp; 2324290001Sglebius 2325290001Sglebius if (str == NULL) 2326290001Sglebius return; 2327290001Sglebius 2328290001Sglebius if ((cp = strchr(str, '\0')) == NULL || (cp == str)) 2329290001Sglebius return; 2330290001Sglebius 2331290001Sglebius --cp; 2332290001Sglebius 2333290001Sglebius while (*cp == ' ' || *cp == '\t') { 2334290001Sglebius *cp = '\0'; 2335290001Sglebius if (cp == str) 2336290001Sglebius break; 2337290001Sglebius --cp; 2338290001Sglebius } 2339290001Sglebius} 2340290001Sglebius 2341290001Sglebiusstatic int 2342290001Sglebiusevutil_issetugid(void) 2343290001Sglebius{ 2344290001Sglebius#ifdef EVENT__HAVE_ISSETUGID 2345290001Sglebius return issetugid(); 2346290001Sglebius#else 2347290001Sglebius 2348290001Sglebius#ifdef EVENT__HAVE_GETEUID 2349290001Sglebius if (getuid() != geteuid()) 2350290001Sglebius return 1; 2351290001Sglebius#endif 2352290001Sglebius#ifdef EVENT__HAVE_GETEGID 2353290001Sglebius if (getgid() != getegid()) 2354290001Sglebius return 1; 2355290001Sglebius#endif 2356290001Sglebius return 0; 2357290001Sglebius#endif 2358290001Sglebius} 2359290001Sglebius 2360290001Sglebiusconst char * 2361290001Sglebiusevutil_getenv_(const char *varname) 2362290001Sglebius{ 2363290001Sglebius if (evutil_issetugid()) 2364290001Sglebius return NULL; 2365290001Sglebius 2366290001Sglebius return getenv(varname); 2367290001Sglebius} 2368290001Sglebius 2369290001Sglebiusev_uint32_t 2370290001Sglebiusevutil_weakrand_seed_(struct evutil_weakrand_state *state, ev_uint32_t seed) 2371290001Sglebius{ 2372290001Sglebius if (seed == 0) { 2373290001Sglebius struct timeval tv; 2374290001Sglebius evutil_gettimeofday(&tv, NULL); 2375290001Sglebius seed = (ev_uint32_t)tv.tv_sec + (ev_uint32_t)tv.tv_usec; 2376290001Sglebius#ifdef _WIN32 2377290001Sglebius seed += (ev_uint32_t) _getpid(); 2378290001Sglebius#else 2379290001Sglebius seed += (ev_uint32_t) getpid(); 2380290001Sglebius#endif 2381290001Sglebius } 2382290001Sglebius state->seed = seed; 2383290001Sglebius return seed; 2384290001Sglebius} 2385290001Sglebius 2386290001Sglebiusev_int32_t 2387290001Sglebiusevutil_weakrand_(struct evutil_weakrand_state *state) 2388290001Sglebius{ 2389290001Sglebius /* This RNG implementation is a linear congruential generator, with 2390290001Sglebius * modulus 2^31, multiplier 1103515245, and addend 12345. It's also 2391290001Sglebius * used by OpenBSD, and by Glibc's TYPE_0 RNG. 2392290001Sglebius * 2393290001Sglebius * The linear congruential generator is not an industrial-strength 2394290001Sglebius * RNG! It's fast, but it can have higher-order patterns. Notably, 2395290001Sglebius * the low bits tend to have periodicity. 2396290001Sglebius */ 2397290001Sglebius state->seed = ((state->seed) * 1103515245 + 12345) & 0x7fffffff; 2398290001Sglebius return (ev_int32_t)(state->seed); 2399290001Sglebius} 2400290001Sglebius 2401290001Sglebiusev_int32_t 2402290001Sglebiusevutil_weakrand_range_(struct evutil_weakrand_state *state, ev_int32_t top) 2403290001Sglebius{ 2404290001Sglebius ev_int32_t divisor, result; 2405290001Sglebius 2406290001Sglebius /* We can't just do weakrand() % top, since the low bits of the LCG 2407290001Sglebius * are less random than the high ones. (Specifically, since the LCG 2408290001Sglebius * modulus is 2^N, every 2^m for m<N will divide the modulus, and so 2409290001Sglebius * therefore the low m bits of the LCG will have period 2^m.) */ 2410290001Sglebius divisor = EVUTIL_WEAKRAND_MAX / top; 2411290001Sglebius do { 2412290001Sglebius result = evutil_weakrand_(state) / divisor; 2413290001Sglebius } while (result >= top); 2414290001Sglebius return result; 2415290001Sglebius} 2416290001Sglebius 2417290001Sglebius/** 2418290001Sglebius * Volatile pointer to memset: we use this to keep the compiler from 2419290001Sglebius * eliminating our call to memset. 2420290001Sglebius */ 2421290001Sglebiusvoid * (*volatile evutil_memset_volatile_)(void *, int, size_t) = memset; 2422290001Sglebius 2423290001Sglebiusvoid 2424290001Sglebiusevutil_memclear_(void *mem, size_t len) 2425290001Sglebius{ 2426290001Sglebius evutil_memset_volatile_(mem, 0, len); 2427290001Sglebius} 2428290001Sglebius 2429290001Sglebiusint 2430290001Sglebiusevutil_sockaddr_is_loopback_(const struct sockaddr *addr) 2431290001Sglebius{ 2432290001Sglebius static const char LOOPBACK_S6[16] = 2433290001Sglebius "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1"; 2434290001Sglebius if (addr->sa_family == AF_INET) { 2435290001Sglebius struct sockaddr_in *sin = (struct sockaddr_in *)addr; 2436290001Sglebius return (ntohl(sin->sin_addr.s_addr) & 0xff000000) == 0x7f000000; 2437290001Sglebius } else if (addr->sa_family == AF_INET6) { 2438290001Sglebius struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr; 2439290001Sglebius return !memcmp(sin6->sin6_addr.s6_addr, LOOPBACK_S6, 16); 2440290001Sglebius } 2441290001Sglebius return 0; 2442290001Sglebius} 2443290001Sglebius 2444290001Sglebiusint 2445290001Sglebiusevutil_hex_char_to_int_(char c) 2446290001Sglebius{ 2447290001Sglebius switch(c) 2448290001Sglebius { 2449290001Sglebius case '0': return 0; 2450290001Sglebius case '1': return 1; 2451290001Sglebius case '2': return 2; 2452290001Sglebius case '3': return 3; 2453290001Sglebius case '4': return 4; 2454290001Sglebius case '5': return 5; 2455290001Sglebius case '6': return 6; 2456290001Sglebius case '7': return 7; 2457290001Sglebius case '8': return 8; 2458290001Sglebius case '9': return 9; 2459290001Sglebius case 'A': case 'a': return 10; 2460290001Sglebius case 'B': case 'b': return 11; 2461290001Sglebius case 'C': case 'c': return 12; 2462290001Sglebius case 'D': case 'd': return 13; 2463290001Sglebius case 'E': case 'e': return 14; 2464290001Sglebius case 'F': case 'f': return 15; 2465290001Sglebius } 2466290001Sglebius return -1; 2467290001Sglebius} 2468290001Sglebius 2469290001Sglebius#ifdef _WIN32 2470290001SglebiusHMODULE 2471290001Sglebiusevutil_load_windows_system_library_(const TCHAR *library_name) 2472290001Sglebius{ 2473290001Sglebius TCHAR path[MAX_PATH]; 2474290001Sglebius unsigned n; 2475290001Sglebius n = GetSystemDirectory(path, MAX_PATH); 2476290001Sglebius if (n == 0 || n + _tcslen(library_name) + 2 >= MAX_PATH) 2477290001Sglebius return 0; 2478290001Sglebius _tcscat(path, TEXT("\\")); 2479290001Sglebius _tcscat(path, library_name); 2480290001Sglebius return LoadLibrary(path); 2481290001Sglebius} 2482290001Sglebius#endif 2483290001Sglebius 2484290001Sglebius/* Internal wrapper around 'socket' to provide Linux-style support for 2485290001Sglebius * syscall-saving methods where available. 2486290001Sglebius * 2487290001Sglebius * In addition to regular socket behavior, you can use a bitwise or to set the 2488290001Sglebius * flags EVUTIL_SOCK_NONBLOCK and EVUTIL_SOCK_CLOEXEC in the 'type' argument, 2489290001Sglebius * to make the socket nonblocking or close-on-exec with as few syscalls as 2490290001Sglebius * possible. 2491290001Sglebius */ 2492290001Sglebiusevutil_socket_t 2493290001Sglebiusevutil_socket_(int domain, int type, int protocol) 2494290001Sglebius{ 2495290001Sglebius evutil_socket_t r; 2496290001Sglebius#if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC) 2497290001Sglebius r = socket(domain, type, protocol); 2498290001Sglebius if (r >= 0) 2499290001Sglebius return r; 2500290001Sglebius else if ((type & (SOCK_NONBLOCK|SOCK_CLOEXEC)) == 0) 2501290001Sglebius return -1; 2502290001Sglebius#endif 2503290001Sglebius#define SOCKET_TYPE_MASK (~(EVUTIL_SOCK_NONBLOCK|EVUTIL_SOCK_CLOEXEC)) 2504290001Sglebius r = socket(domain, type & SOCKET_TYPE_MASK, protocol); 2505290001Sglebius if (r < 0) 2506290001Sglebius return -1; 2507290001Sglebius if (type & EVUTIL_SOCK_NONBLOCK) { 2508290001Sglebius if (evutil_fast_socket_nonblocking(r) < 0) { 2509290001Sglebius evutil_closesocket(r); 2510290001Sglebius return -1; 2511290001Sglebius } 2512290001Sglebius } 2513290001Sglebius if (type & EVUTIL_SOCK_CLOEXEC) { 2514290001Sglebius if (evutil_fast_socket_closeonexec(r) < 0) { 2515290001Sglebius evutil_closesocket(r); 2516290001Sglebius return -1; 2517290001Sglebius } 2518290001Sglebius } 2519290001Sglebius return r; 2520290001Sglebius} 2521290001Sglebius 2522290001Sglebius/* Internal wrapper around 'accept' or 'accept4' to provide Linux-style 2523290001Sglebius * support for syscall-saving methods where available. 2524290001Sglebius * 2525290001Sglebius * In addition to regular accept behavior, you can set one or more of flags 2526290001Sglebius * EVUTIL_SOCK_NONBLOCK and EVUTIL_SOCK_CLOEXEC in the 'flags' argument, to 2527290001Sglebius * make the socket nonblocking or close-on-exec with as few syscalls as 2528290001Sglebius * possible. 2529290001Sglebius */ 2530290001Sglebiusevutil_socket_t 2531290001Sglebiusevutil_accept4_(evutil_socket_t sockfd, struct sockaddr *addr, 2532290001Sglebius ev_socklen_t *addrlen, int flags) 2533290001Sglebius{ 2534290001Sglebius evutil_socket_t result; 2535290001Sglebius#if defined(EVENT__HAVE_ACCEPT4) && defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK) 2536290001Sglebius result = accept4(sockfd, addr, addrlen, flags); 2537290001Sglebius if (result >= 0 || (errno != EINVAL && errno != ENOSYS)) { 2538290001Sglebius /* A nonnegative result means that we succeeded, so return. 2539290001Sglebius * Failing with EINVAL means that an option wasn't supported, 2540290001Sglebius * and failing with ENOSYS means that the syscall wasn't 2541290001Sglebius * there: in those cases we want to fall back. Otherwise, we 2542290001Sglebius * got a real error, and we should return. */ 2543290001Sglebius return result; 2544290001Sglebius } 2545290001Sglebius#endif 2546290001Sglebius result = accept(sockfd, addr, addrlen); 2547290001Sglebius if (result < 0) 2548290001Sglebius return result; 2549290001Sglebius 2550290001Sglebius if (flags & EVUTIL_SOCK_CLOEXEC) { 2551290001Sglebius if (evutil_fast_socket_closeonexec(result) < 0) { 2552290001Sglebius evutil_closesocket(result); 2553290001Sglebius return -1; 2554290001Sglebius } 2555290001Sglebius } 2556290001Sglebius if (flags & EVUTIL_SOCK_NONBLOCK) { 2557290001Sglebius if (evutil_fast_socket_nonblocking(result) < 0) { 2558290001Sglebius evutil_closesocket(result); 2559290001Sglebius return -1; 2560290001Sglebius } 2561290001Sglebius } 2562290001Sglebius return result; 2563290001Sglebius} 2564290001Sglebius 2565290001Sglebius/* Internal function: Set fd[0] and fd[1] to a pair of fds such that writes on 2566290001Sglebius * fd[0] get read from fd[1]. Make both fds nonblocking and close-on-exec. 2567290001Sglebius * Return 0 on success, -1 on failure. 2568290001Sglebius */ 2569290001Sglebiusint 2570290001Sglebiusevutil_make_internal_pipe_(evutil_socket_t fd[2]) 2571290001Sglebius{ 2572290001Sglebius /* 2573290001Sglebius Making the second socket nonblocking is a bit subtle, given that we 2574290001Sglebius ignore any EAGAIN returns when writing to it, and you don't usally 2575290001Sglebius do that for a nonblocking socket. But if the kernel gives us EAGAIN, 2576290001Sglebius then there's no need to add any more data to the buffer, since 2577290001Sglebius the main thread is already either about to wake up and drain it, 2578290001Sglebius or woken up and in the process of draining it. 2579290001Sglebius */ 2580290001Sglebius 2581290001Sglebius#if defined(EVENT__HAVE_PIPE2) 2582290001Sglebius if (pipe2(fd, O_NONBLOCK|O_CLOEXEC) == 0) 2583290001Sglebius return 0; 2584290001Sglebius#endif 2585290001Sglebius#if defined(EVENT__HAVE_PIPE) 2586290001Sglebius if (pipe(fd) == 0) { 2587290001Sglebius if (evutil_fast_socket_nonblocking(fd[0]) < 0 || 2588290001Sglebius evutil_fast_socket_nonblocking(fd[1]) < 0 || 2589290001Sglebius evutil_fast_socket_closeonexec(fd[0]) < 0 || 2590290001Sglebius evutil_fast_socket_closeonexec(fd[1]) < 0) { 2591290001Sglebius close(fd[0]); 2592290001Sglebius close(fd[1]); 2593290001Sglebius fd[0] = fd[1] = -1; 2594290001Sglebius return -1; 2595290001Sglebius } 2596290001Sglebius return 0; 2597290001Sglebius } else { 2598290001Sglebius event_warn("%s: pipe", __func__); 2599290001Sglebius } 2600290001Sglebius#endif 2601290001Sglebius 2602290001Sglebius#ifdef _WIN32 2603290001Sglebius#define LOCAL_SOCKETPAIR_AF AF_INET 2604290001Sglebius#else 2605290001Sglebius#define LOCAL_SOCKETPAIR_AF AF_UNIX 2606290001Sglebius#endif 2607290001Sglebius if (evutil_socketpair(LOCAL_SOCKETPAIR_AF, SOCK_STREAM, 0, fd) == 0) { 2608290001Sglebius if (evutil_fast_socket_nonblocking(fd[0]) < 0 || 2609290001Sglebius evutil_fast_socket_nonblocking(fd[1]) < 0 || 2610290001Sglebius evutil_fast_socket_closeonexec(fd[0]) < 0 || 2611290001Sglebius evutil_fast_socket_closeonexec(fd[1]) < 0) { 2612290001Sglebius evutil_closesocket(fd[0]); 2613290001Sglebius evutil_closesocket(fd[1]); 2614290001Sglebius fd[0] = fd[1] = -1; 2615290001Sglebius return -1; 2616290001Sglebius } 2617290001Sglebius return 0; 2618290001Sglebius } 2619290001Sglebius fd[0] = fd[1] = -1; 2620290001Sglebius return -1; 2621290001Sglebius} 2622290001Sglebius 2623290001Sglebius/* Wrapper around eventfd on systems that provide it. Unlike the system 2624290001Sglebius * eventfd, it always supports EVUTIL_EFD_CLOEXEC and EVUTIL_EFD_NONBLOCK as 2625290001Sglebius * flags. Returns -1 on error or if eventfd is not supported. 2626290001Sglebius */ 2627290001Sglebiusevutil_socket_t 2628290001Sglebiusevutil_eventfd_(unsigned initval, int flags) 2629290001Sglebius{ 2630290001Sglebius#if defined(EVENT__HAVE_EVENTFD) && defined(EVENT__HAVE_SYS_EVENTFD_H) 2631290001Sglebius int r; 2632290001Sglebius#if defined(EFD_CLOEXEC) && defined(EFD_NONBLOCK) 2633290001Sglebius r = eventfd(initval, flags); 2634290001Sglebius if (r >= 0 || flags == 0) 2635290001Sglebius return r; 2636290001Sglebius#endif 2637290001Sglebius r = eventfd(initval, 0); 2638290001Sglebius if (r < 0) 2639290001Sglebius return r; 2640290001Sglebius if (flags & EVUTIL_EFD_CLOEXEC) { 2641290001Sglebius if (evutil_fast_socket_closeonexec(r) < 0) { 2642290001Sglebius evutil_closesocket(r); 2643290001Sglebius return -1; 2644290001Sglebius } 2645290001Sglebius } 2646290001Sglebius if (flags & EVUTIL_EFD_NONBLOCK) { 2647290001Sglebius if (evutil_fast_socket_nonblocking(r) < 0) { 2648290001Sglebius evutil_closesocket(r); 2649290001Sglebius return -1; 2650290001Sglebius } 2651290001Sglebius } 2652290001Sglebius return r; 2653290001Sglebius#else 2654290001Sglebius return -1; 2655290001Sglebius#endif 2656290001Sglebius} 2657290001Sglebius 2658290001Sglebiusvoid 2659290001Sglebiusevutil_free_globals_(void) 2660290001Sglebius{ 2661290001Sglebius evutil_free_secure_rng_globals_(); 2662290001Sglebius evutil_free_sock_err_globals(); 2663290001Sglebius} 2664