1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/chromium/src/third_party/libevent/evutil.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,2178 @@ 1.4 +/* 1.5 + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson 1.6 + * 1.7 + * Redistribution and use in source and binary forms, with or without 1.8 + * modification, are permitted provided that the following conditions 1.9 + * are met: 1.10 + * 1. Redistributions of source code must retain the above copyright 1.11 + * notice, this list of conditions and the following disclaimer. 1.12 + * 2. Redistributions in binary form must reproduce the above copyright 1.13 + * notice, this list of conditions and the following disclaimer in the 1.14 + * documentation and/or other materials provided with the distribution. 1.15 + * 3. The name of the author may not be used to endorse or promote products 1.16 + * derived from this software without specific prior written permission. 1.17 + * 1.18 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1.19 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1.20 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1.21 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1.22 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 1.23 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.24 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.25 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.26 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 1.27 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.28 + */ 1.29 + 1.30 +#include "event2/event-config.h" 1.31 + 1.32 +#define _GNU_SOURCE 1.33 + 1.34 +#ifdef WIN32 1.35 +#include <winsock2.h> 1.36 +#include <ws2tcpip.h> 1.37 +#define WIN32_LEAN_AND_MEAN 1.38 +#include <windows.h> 1.39 +#undef WIN32_LEAN_AND_MEAN 1.40 +#include <io.h> 1.41 +#include <tchar.h> 1.42 +#endif 1.43 + 1.44 +#include <sys/types.h> 1.45 +#ifdef _EVENT_HAVE_SYS_SOCKET_H 1.46 +#include <sys/socket.h> 1.47 +#endif 1.48 +#ifdef _EVENT_HAVE_UNISTD_H 1.49 +#include <unistd.h> 1.50 +#endif 1.51 +#ifdef _EVENT_HAVE_FCNTL_H 1.52 +#include <fcntl.h> 1.53 +#endif 1.54 +#ifdef _EVENT_HAVE_STDLIB_H 1.55 +#include <stdlib.h> 1.56 +#endif 1.57 +#include <errno.h> 1.58 +#include <limits.h> 1.59 +#include <stdio.h> 1.60 +#include <string.h> 1.61 +#ifdef _EVENT_HAVE_NETINET_IN_H 1.62 +#include <netinet/in.h> 1.63 +#endif 1.64 +#ifdef _EVENT_HAVE_NETINET_IN6_H 1.65 +#include <netinet/in6.h> 1.66 +#endif 1.67 +#ifdef _EVENT_HAVE_ARPA_INET_H 1.68 +#include <arpa/inet.h> 1.69 +#endif 1.70 + 1.71 +#ifndef _EVENT_HAVE_GETTIMEOFDAY 1.72 +#include <sys/timeb.h> 1.73 +#include <time.h> 1.74 +#endif 1.75 +#include <sys/stat.h> 1.76 + 1.77 +#include "event2/util.h" 1.78 +#include "util-internal.h" 1.79 +#include "log-internal.h" 1.80 +#include "mm-internal.h" 1.81 + 1.82 +#include "strlcpy-internal.h" 1.83 +#include "ipv6-internal.h" 1.84 + 1.85 +#ifdef WIN32 1.86 +#define open _open 1.87 +#define read _read 1.88 +#define close _close 1.89 +#define fstat _fstati64 1.90 +#define stat _stati64 1.91 +#define mode_t int 1.92 +#endif 1.93 + 1.94 +int 1.95 +evutil_open_closeonexec(const char *pathname, int flags, unsigned mode) 1.96 +{ 1.97 + int fd; 1.98 + 1.99 +#ifdef O_CLOEXEC 1.100 + flags |= O_CLOEXEC; 1.101 +#endif 1.102 + 1.103 + if (flags & O_CREAT) 1.104 + fd = open(pathname, flags, (mode_t)mode); 1.105 + else 1.106 + fd = open(pathname, flags); 1.107 + if (fd < 0) 1.108 + return -1; 1.109 + 1.110 +#if !defined(O_CLOEXEC) && defined(FD_CLOEXEC) 1.111 + if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) 1.112 + return -1; 1.113 +#endif 1.114 + 1.115 + return fd; 1.116 +} 1.117 + 1.118 +/** 1.119 + Read the contents of 'filename' into a newly allocated NUL-terminated 1.120 + string. Set *content_out to hold this string, and *len_out to hold its 1.121 + length (not including the appended NUL). If 'is_binary', open the file in 1.122 + binary mode. 1.123 + 1.124 + Returns 0 on success, -1 if the open fails, and -2 for all other failures. 1.125 + 1.126 + Used internally only; may go away in a future version. 1.127 + */ 1.128 +int 1.129 +evutil_read_file(const char *filename, char **content_out, size_t *len_out, 1.130 + int is_binary) 1.131 +{ 1.132 + int fd, r; 1.133 + struct stat st; 1.134 + char *mem; 1.135 + size_t read_so_far=0; 1.136 + int mode = O_RDONLY; 1.137 + 1.138 + EVUTIL_ASSERT(content_out); 1.139 + EVUTIL_ASSERT(len_out); 1.140 + *content_out = NULL; 1.141 + *len_out = 0; 1.142 + 1.143 +#ifdef O_BINARY 1.144 + if (is_binary) 1.145 + mode |= O_BINARY; 1.146 +#endif 1.147 + 1.148 + fd = evutil_open_closeonexec(filename, mode, 0); 1.149 + if (fd < 0) 1.150 + return -1; 1.151 + if (fstat(fd, &st) || st.st_size < 0 || 1.152 + st.st_size > EV_SSIZE_MAX-1 ) { 1.153 + close(fd); 1.154 + return -2; 1.155 + } 1.156 + mem = mm_malloc((size_t)st.st_size + 1); 1.157 + if (!mem) { 1.158 + close(fd); 1.159 + return -2; 1.160 + } 1.161 + read_so_far = 0; 1.162 +#ifdef WIN32 1.163 +#define N_TO_READ(x) ((x) > INT_MAX) ? INT_MAX : ((int)(x)) 1.164 +#else 1.165 +#define N_TO_READ(x) (x) 1.166 +#endif 1.167 + while ((r = read(fd, mem+read_so_far, N_TO_READ(st.st_size - read_so_far))) > 0) { 1.168 + read_so_far += r; 1.169 + if (read_so_far >= (size_t)st.st_size) 1.170 + break; 1.171 + EVUTIL_ASSERT(read_so_far < (size_t)st.st_size); 1.172 + } 1.173 + close(fd); 1.174 + if (r < 0) { 1.175 + mm_free(mem); 1.176 + return -2; 1.177 + } 1.178 + mem[read_so_far] = 0; 1.179 + 1.180 + *len_out = read_so_far; 1.181 + *content_out = mem; 1.182 + return 0; 1.183 +} 1.184 + 1.185 +int 1.186 +evutil_socketpair(int family, int type, int protocol, evutil_socket_t fd[2]) 1.187 +{ 1.188 +#ifndef WIN32 1.189 + return socketpair(family, type, protocol, fd); 1.190 +#else 1.191 + return evutil_ersatz_socketpair(family, type, protocol, fd); 1.192 +#endif 1.193 +} 1.194 + 1.195 +int 1.196 +evutil_ersatz_socketpair(int family, int type, int protocol, 1.197 + evutil_socket_t fd[2]) 1.198 +{ 1.199 + /* This code is originally from Tor. Used with permission. */ 1.200 + 1.201 + /* This socketpair does not work when localhost is down. So 1.202 + * it's really not the same thing at all. But it's close enough 1.203 + * for now, and really, when localhost is down sometimes, we 1.204 + * have other problems too. 1.205 + */ 1.206 +#ifdef WIN32 1.207 +#define ERR(e) WSA##e 1.208 +#else 1.209 +#define ERR(e) e 1.210 +#endif 1.211 + evutil_socket_t listener = -1; 1.212 + evutil_socket_t connector = -1; 1.213 + evutil_socket_t acceptor = -1; 1.214 + struct sockaddr_in listen_addr; 1.215 + struct sockaddr_in connect_addr; 1.216 + ev_socklen_t size; 1.217 + int saved_errno = -1; 1.218 + 1.219 + if (protocol 1.220 + || (family != AF_INET 1.221 +#ifdef AF_UNIX 1.222 + && family != AF_UNIX 1.223 +#endif 1.224 + )) { 1.225 + EVUTIL_SET_SOCKET_ERROR(ERR(EAFNOSUPPORT)); 1.226 + return -1; 1.227 + } 1.228 + if (!fd) { 1.229 + EVUTIL_SET_SOCKET_ERROR(ERR(EINVAL)); 1.230 + return -1; 1.231 + } 1.232 + 1.233 + listener = socket(AF_INET, type, 0); 1.234 + if (listener < 0) 1.235 + return -1; 1.236 + memset(&listen_addr, 0, sizeof(listen_addr)); 1.237 + listen_addr.sin_family = AF_INET; 1.238 + listen_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 1.239 + listen_addr.sin_port = 0; /* kernel chooses port. */ 1.240 + if (bind(listener, (struct sockaddr *) &listen_addr, sizeof (listen_addr)) 1.241 + == -1) 1.242 + goto tidy_up_and_fail; 1.243 + if (listen(listener, 1) == -1) 1.244 + goto tidy_up_and_fail; 1.245 + 1.246 + connector = socket(AF_INET, type, 0); 1.247 + if (connector < 0) 1.248 + goto tidy_up_and_fail; 1.249 + /* We want to find out the port number to connect to. */ 1.250 + size = sizeof(connect_addr); 1.251 + if (getsockname(listener, (struct sockaddr *) &connect_addr, &size) == -1) 1.252 + goto tidy_up_and_fail; 1.253 + if (size != sizeof (connect_addr)) 1.254 + goto abort_tidy_up_and_fail; 1.255 + if (connect(connector, (struct sockaddr *) &connect_addr, 1.256 + sizeof(connect_addr)) == -1) 1.257 + goto tidy_up_and_fail; 1.258 + 1.259 + size = sizeof(listen_addr); 1.260 + acceptor = accept(listener, (struct sockaddr *) &listen_addr, &size); 1.261 + if (acceptor < 0) 1.262 + goto tidy_up_and_fail; 1.263 + if (size != sizeof(listen_addr)) 1.264 + goto abort_tidy_up_and_fail; 1.265 + evutil_closesocket(listener); 1.266 + /* Now check we are talking to ourself by matching port and host on the 1.267 + two sockets. */ 1.268 + if (getsockname(connector, (struct sockaddr *) &connect_addr, &size) == -1) 1.269 + goto tidy_up_and_fail; 1.270 + if (size != sizeof (connect_addr) 1.271 + || listen_addr.sin_family != connect_addr.sin_family 1.272 + || listen_addr.sin_addr.s_addr != connect_addr.sin_addr.s_addr 1.273 + || listen_addr.sin_port != connect_addr.sin_port) 1.274 + goto abort_tidy_up_and_fail; 1.275 + fd[0] = connector; 1.276 + fd[1] = acceptor; 1.277 + 1.278 + return 0; 1.279 + 1.280 + abort_tidy_up_and_fail: 1.281 + saved_errno = ERR(ECONNABORTED); 1.282 + tidy_up_and_fail: 1.283 + if (saved_errno < 0) 1.284 + saved_errno = EVUTIL_SOCKET_ERROR(); 1.285 + if (listener != -1) 1.286 + evutil_closesocket(listener); 1.287 + if (connector != -1) 1.288 + evutil_closesocket(connector); 1.289 + if (acceptor != -1) 1.290 + evutil_closesocket(acceptor); 1.291 + 1.292 + EVUTIL_SET_SOCKET_ERROR(saved_errno); 1.293 + return -1; 1.294 +#undef ERR 1.295 +} 1.296 + 1.297 +int 1.298 +evutil_make_socket_nonblocking(evutil_socket_t fd) 1.299 +{ 1.300 +#ifdef WIN32 1.301 + { 1.302 + u_long nonblocking = 1; 1.303 + if (ioctlsocket(fd, FIONBIO, &nonblocking) == SOCKET_ERROR) { 1.304 + event_sock_warn(fd, "fcntl(%d, F_GETFL)", (int)fd); 1.305 + return -1; 1.306 + } 1.307 + } 1.308 +#else 1.309 + { 1.310 + int flags; 1.311 + if ((flags = fcntl(fd, F_GETFL, NULL)) < 0) { 1.312 + event_warn("fcntl(%d, F_GETFL)", fd); 1.313 + return -1; 1.314 + } 1.315 + if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) { 1.316 + event_warn("fcntl(%d, F_SETFL)", fd); 1.317 + return -1; 1.318 + } 1.319 + } 1.320 +#endif 1.321 + return 0; 1.322 +} 1.323 + 1.324 +int 1.325 +evutil_make_listen_socket_reuseable(evutil_socket_t sock) 1.326 +{ 1.327 +#ifndef WIN32 1.328 + int one = 1; 1.329 + /* REUSEADDR on Unix means, "don't hang on to this address after the 1.330 + * listener is closed." On Windows, though, it means "don't keep other 1.331 + * processes from binding to this address while we're using it. */ 1.332 + return setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*) &one, 1.333 + (ev_socklen_t)sizeof(one)); 1.334 +#else 1.335 + return 0; 1.336 +#endif 1.337 +} 1.338 + 1.339 +int 1.340 +evutil_make_socket_closeonexec(evutil_socket_t fd) 1.341 +{ 1.342 +#if !defined(WIN32) && defined(_EVENT_HAVE_SETFD) 1.343 + int flags; 1.344 + if ((flags = fcntl(fd, F_GETFD, NULL)) < 0) { 1.345 + event_warn("fcntl(%d, F_GETFD)", fd); 1.346 + return -1; 1.347 + } 1.348 + if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) { 1.349 + event_warn("fcntl(%d, F_SETFD)", fd); 1.350 + return -1; 1.351 + } 1.352 +#endif 1.353 + return 0; 1.354 +} 1.355 + 1.356 +int 1.357 +evutil_closesocket(evutil_socket_t sock) 1.358 +{ 1.359 +#ifndef WIN32 1.360 + return close(sock); 1.361 +#else 1.362 + return closesocket(sock); 1.363 +#endif 1.364 +} 1.365 + 1.366 +ev_int64_t 1.367 +evutil_strtoll(const char *s, char **endptr, int base) 1.368 +{ 1.369 +#ifdef _EVENT_HAVE_STRTOLL 1.370 + return (ev_int64_t)strtoll(s, endptr, base); 1.371 +#elif _EVENT_SIZEOF_LONG == 8 1.372 + return (ev_int64_t)strtol(s, endptr, base); 1.373 +#elif defined(WIN32) && defined(_MSC_VER) && _MSC_VER < 1300 1.374 + /* XXXX on old versions of MS APIs, we only support base 1.375 + * 10. */ 1.376 + ev_int64_t r; 1.377 + if (base != 10) 1.378 + return 0; 1.379 + r = (ev_int64_t) _atoi64(s); 1.380 + while (isspace(*s)) 1.381 + ++s; 1.382 + if (*s == '-') 1.383 + ++s; 1.384 + while (isdigit(*s)) 1.385 + ++s; 1.386 + if (endptr) 1.387 + *endptr = (char*) s; 1.388 + return r; 1.389 +#elif defined(WIN32) 1.390 + return (ev_int64_t) _strtoi64(s, endptr, base); 1.391 +#elif defined(_EVENT_SIZEOF_LONG_LONG) && _EVENT_SIZEOF_LONG_LONG == 8 1.392 + long long r; 1.393 + int n; 1.394 + if (base != 10 && base != 16) 1.395 + return 0; 1.396 + if (base == 10) { 1.397 + n = sscanf(s, "%lld", &r); 1.398 + } else { 1.399 + unsigned long long ru=0; 1.400 + n = sscanf(s, "%llx", &ru); 1.401 + if (ru > EV_INT64_MAX) 1.402 + return 0; 1.403 + r = (long long) ru; 1.404 + } 1.405 + if (n != 1) 1.406 + return 0; 1.407 + while (EVUTIL_ISSPACE(*s)) 1.408 + ++s; 1.409 + if (*s == '-') 1.410 + ++s; 1.411 + if (base == 10) { 1.412 + while (EVUTIL_ISDIGIT(*s)) 1.413 + ++s; 1.414 + } else { 1.415 + while (EVUTIL_ISXDIGIT(*s)) 1.416 + ++s; 1.417 + } 1.418 + if (endptr) 1.419 + *endptr = (char*) s; 1.420 + return r; 1.421 +#else 1.422 +#error "I don't know how to parse 64-bit integers." 1.423 +#endif 1.424 +} 1.425 + 1.426 +#ifndef _EVENT_HAVE_GETTIMEOFDAY 1.427 +/* No gettimeofday; this muse be windows. */ 1.428 +int 1.429 +evutil_gettimeofday(struct timeval *tv, struct timezone *tz) 1.430 +{ 1.431 + struct _timeb tb; 1.432 + 1.433 + if (tv == NULL) 1.434 + return -1; 1.435 + 1.436 + /* XXXX 1.437 + * _ftime is not the greatest interface here; GetSystemTimeAsFileTime 1.438 + * would give us better resolution, whereas something cobbled together 1.439 + * with GetTickCount could maybe give us monotonic behavior. 1.440 + * 1.441 + * Either way, I think this value might be skewed to ignore the 1.442 + * timezone, and just return local time. That's not so good. 1.443 + */ 1.444 + _ftime(&tb); 1.445 + tv->tv_sec = (long) tb.time; 1.446 + tv->tv_usec = ((int) tb.millitm) * 1000; 1.447 + return 0; 1.448 +} 1.449 +#endif 1.450 + 1.451 +#ifdef WIN32 1.452 +int 1.453 +evutil_socket_geterror(evutil_socket_t sock) 1.454 +{ 1.455 + int optval, optvallen=sizeof(optval); 1.456 + int err = WSAGetLastError(); 1.457 + if (err == WSAEWOULDBLOCK && sock >= 0) { 1.458 + if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)&optval, 1.459 + &optvallen)) 1.460 + return err; 1.461 + if (optval) 1.462 + return optval; 1.463 + } 1.464 + return err; 1.465 +} 1.466 +#endif 1.467 + 1.468 +/* XXX we should use an enum here. */ 1.469 +/* 2 for connection refused, 1 for connected, 0 for not yet, -1 for error. */ 1.470 +int 1.471 +evutil_socket_connect(evutil_socket_t *fd_ptr, struct sockaddr *sa, int socklen) 1.472 +{ 1.473 + int made_fd = 0; 1.474 + 1.475 + if (*fd_ptr < 0) { 1.476 + if ((*fd_ptr = socket(sa->sa_family, SOCK_STREAM, 0)) < 0) 1.477 + goto err; 1.478 + made_fd = 1; 1.479 + if (evutil_make_socket_nonblocking(*fd_ptr) < 0) { 1.480 + goto err; 1.481 + } 1.482 + } 1.483 + 1.484 + if (connect(*fd_ptr, sa, socklen) < 0) { 1.485 + int e = evutil_socket_geterror(*fd_ptr); 1.486 + if (EVUTIL_ERR_CONNECT_RETRIABLE(e)) 1.487 + return 0; 1.488 + if (EVUTIL_ERR_CONNECT_REFUSED(e)) 1.489 + return 2; 1.490 + goto err; 1.491 + } else { 1.492 + return 1; 1.493 + } 1.494 + 1.495 +err: 1.496 + if (made_fd) { 1.497 + evutil_closesocket(*fd_ptr); 1.498 + *fd_ptr = -1; 1.499 + } 1.500 + return -1; 1.501 +} 1.502 + 1.503 +/* Check whether a socket on which we called connect() is done 1.504 + connecting. Return 1 for connected, 0 for not yet, -1 for error. In the 1.505 + error case, set the current socket errno to the error that happened during 1.506 + the connect operation. */ 1.507 +int 1.508 +evutil_socket_finished_connecting(evutil_socket_t fd) 1.509 +{ 1.510 + int e; 1.511 + ev_socklen_t elen = sizeof(e); 1.512 + 1.513 + if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&e, &elen) < 0) 1.514 + return -1; 1.515 + 1.516 + if (e) { 1.517 + if (EVUTIL_ERR_CONNECT_RETRIABLE(e)) 1.518 + return 0; 1.519 + EVUTIL_SET_SOCKET_ERROR(e); 1.520 + return -1; 1.521 + } 1.522 + 1.523 + return 1; 1.524 +} 1.525 + 1.526 +#if (EVUTIL_AI_PASSIVE|EVUTIL_AI_CANONNAME|EVUTIL_AI_NUMERICHOST| \ 1.527 + EVUTIL_AI_NUMERICSERV|EVUTIL_AI_V4MAPPED|EVUTIL_AI_ALL| \ 1.528 + EVUTIL_AI_ADDRCONFIG) != \ 1.529 + (EVUTIL_AI_PASSIVE^EVUTIL_AI_CANONNAME^EVUTIL_AI_NUMERICHOST^ \ 1.530 + EVUTIL_AI_NUMERICSERV^EVUTIL_AI_V4MAPPED^EVUTIL_AI_ALL^ \ 1.531 + EVUTIL_AI_ADDRCONFIG) 1.532 +#error "Some of our EVUTIL_AI_* flags seem to overlap with system AI_* flags" 1.533 +#endif 1.534 + 1.535 +/* We sometimes need to know whether we have an ipv4 address and whether we 1.536 + have an ipv6 address. If 'have_checked_interfaces', then we've already done 1.537 + the test. If 'had_ipv4_address', then it turns out we had an ipv4 address. 1.538 + If 'had_ipv6_address', then it turns out we had an ipv6 address. These are 1.539 + set by evutil_check_interfaces. */ 1.540 +static int have_checked_interfaces, had_ipv4_address, had_ipv6_address; 1.541 + 1.542 +/* Macro: True iff the IPv4 address 'addr', in host order, is in 127.0.0.0/8 1.543 + */ 1.544 +#define EVUTIL_V4ADDR_IS_LOCALHOST(addr) (((addr)>>24) == 127) 1.545 + 1.546 +/* Macro: True iff the IPv4 address 'addr', in host order, is a class D 1.547 + * (multiclass) address. 1.548 + */ 1.549 +#define EVUTIL_V4ADDR_IS_CLASSD(addr) ((((addr)>>24) & 0xf0) == 0xe0) 1.550 + 1.551 +/* Test whether we have an ipv4 interface and an ipv6 interface. Return 0 if 1.552 + * the test seemed successful. */ 1.553 +static int 1.554 +evutil_check_interfaces(int force_recheck) 1.555 +{ 1.556 + const char ZEROES[] = "\x00\x00\x00\x00\x00\x00\x00\x00" 1.557 + "\x00\x00\x00\x00\x00\x00\x00\x00"; 1.558 + evutil_socket_t fd = -1; 1.559 + struct sockaddr_in sin, sin_out; 1.560 + struct sockaddr_in6 sin6, sin6_out; 1.561 + ev_socklen_t sin_out_len = sizeof(sin_out); 1.562 + ev_socklen_t sin6_out_len = sizeof(sin6_out); 1.563 + int r; 1.564 + char buf[128]; 1.565 + if (have_checked_interfaces && !force_recheck) 1.566 + return 0; 1.567 + 1.568 + /* To check whether we have an interface open for a given protocol, we 1.569 + * try to make a UDP 'connection' to a remote host on the internet. 1.570 + * We don't actually use it, so the address doesn't matter, but we 1.571 + * want to pick one that keep us from using a host- or link-local 1.572 + * interface. */ 1.573 + memset(&sin, 0, sizeof(sin)); 1.574 + sin.sin_family = AF_INET; 1.575 + sin.sin_port = htons(53); 1.576 + r = evutil_inet_pton(AF_INET, "18.244.0.188", &sin.sin_addr); 1.577 + EVUTIL_ASSERT(r); 1.578 + 1.579 + memset(&sin6, 0, sizeof(sin6)); 1.580 + sin6.sin6_family = AF_INET6; 1.581 + sin6.sin6_port = htons(53); 1.582 + r = evutil_inet_pton(AF_INET6, "2001:4860:b002::68", &sin6.sin6_addr); 1.583 + EVUTIL_ASSERT(r); 1.584 + 1.585 + memset(&sin_out, 0, sizeof(sin_out)); 1.586 + memset(&sin6_out, 0, sizeof(sin6_out)); 1.587 + 1.588 + /* XXX some errnos mean 'no address'; some mean 'not enough sockets'. */ 1.589 + if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) >= 0 && 1.590 + connect(fd, (struct sockaddr*)&sin, sizeof(sin)) == 0 && 1.591 + getsockname(fd, (struct sockaddr*)&sin_out, &sin_out_len) == 0) { 1.592 + /* We might have an IPv4 interface. */ 1.593 + ev_uint32_t addr = ntohl(sin_out.sin_addr.s_addr); 1.594 + if (addr == 0 || 1.595 + EVUTIL_V4ADDR_IS_LOCALHOST(addr) || 1.596 + EVUTIL_V4ADDR_IS_CLASSD(addr)) { 1.597 + evutil_inet_ntop(AF_INET, &sin_out.sin_addr, 1.598 + buf, sizeof(buf)); 1.599 + /* This is a reserved, ipv4compat, ipv4map, loopback, 1.600 + * link-local or unspecified address. The host should 1.601 + * never have given it to us; it could never connect 1.602 + * to sin. */ 1.603 + event_warnx("Got a strange local ipv4 address %s",buf); 1.604 + } else { 1.605 + event_debug(("Detected an IPv4 interface")); 1.606 + had_ipv4_address = 1; 1.607 + } 1.608 + } 1.609 + if (fd >= 0) 1.610 + evutil_closesocket(fd); 1.611 + 1.612 + if ((fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) >= 0 && 1.613 + connect(fd, (struct sockaddr*)&sin6, sizeof(sin6)) == 0 && 1.614 + getsockname(fd, (struct sockaddr*)&sin6_out, &sin6_out_len) == 0) { 1.615 + /* We might have an IPv6 interface. */ 1.616 + const unsigned char *addr = 1.617 + (unsigned char*)sin6_out.sin6_addr.s6_addr; 1.618 + if (!memcmp(addr, ZEROES, 8) || 1.619 + (addr[0] == 0xfe && (addr[1] & 0xc0) == 0x80)) { 1.620 + /* This is a reserved, ipv4compat, ipv4map, loopback, 1.621 + * link-local or unspecified address. The host should 1.622 + * never have given it to us; it could never connect 1.623 + * to sin6. */ 1.624 + evutil_inet_ntop(AF_INET6, &sin6_out.sin6_addr, 1.625 + buf, sizeof(buf)); 1.626 + event_warnx("Got a strange local ipv6 address %s",buf); 1.627 + } else { 1.628 + event_debug(("Detected an IPv4 interface")); 1.629 + had_ipv6_address = 1; 1.630 + } 1.631 + } 1.632 + 1.633 + if (fd >= 0) 1.634 + evutil_closesocket(fd); 1.635 + 1.636 + return 0; 1.637 +} 1.638 + 1.639 +/* Internal addrinfo flag. This one is set when we allocate the addrinfo from 1.640 + * inside libevent. Otherwise, the built-in getaddrinfo() function allocated 1.641 + * it, and we should trust what they said. 1.642 + **/ 1.643 +#define EVUTIL_AI_LIBEVENT_ALLOCATED 0x80000000 1.644 + 1.645 +/* Helper: construct a new addrinfo containing the socket address in 1.646 + * 'sa', which must be a sockaddr_in or a sockaddr_in6. Take the 1.647 + * socktype and protocol info from hints. If they weren't set, then 1.648 + * allocate both a TCP and a UDP addrinfo. 1.649 + */ 1.650 +struct evutil_addrinfo * 1.651 +evutil_new_addrinfo(struct sockaddr *sa, ev_socklen_t socklen, 1.652 + const struct evutil_addrinfo *hints) 1.653 +{ 1.654 + struct evutil_addrinfo *res; 1.655 + EVUTIL_ASSERT(hints); 1.656 + 1.657 + if (hints->ai_socktype == 0 && hints->ai_protocol == 0) { 1.658 + /* Indecisive user! Give them a UDP and a TCP. */ 1.659 + struct evutil_addrinfo *r1, *r2; 1.660 + struct evutil_addrinfo tmp; 1.661 + memcpy(&tmp, hints, sizeof(tmp)); 1.662 + tmp.ai_socktype = SOCK_STREAM; tmp.ai_protocol = IPPROTO_TCP; 1.663 + r1 = evutil_new_addrinfo(sa, socklen, &tmp); 1.664 + if (!r1) 1.665 + return NULL; 1.666 + tmp.ai_socktype = SOCK_DGRAM; tmp.ai_protocol = IPPROTO_UDP; 1.667 + r2 = evutil_new_addrinfo(sa, socklen, &tmp); 1.668 + if (!r2) { 1.669 + evutil_freeaddrinfo(r1); 1.670 + return NULL; 1.671 + } 1.672 + r1->ai_next = r2; 1.673 + return r1; 1.674 + } 1.675 + 1.676 + /* We're going to allocate extra space to hold the sockaddr. */ 1.677 + res = mm_calloc(1,sizeof(struct evutil_addrinfo)+socklen); 1.678 + if (!res) 1.679 + return NULL; 1.680 + res->ai_addr = (struct sockaddr*) 1.681 + (((char*)res) + sizeof(struct evutil_addrinfo)); 1.682 + memcpy(res->ai_addr, sa, socklen); 1.683 + res->ai_addrlen = socklen; 1.684 + res->ai_family = sa->sa_family; /* Same or not? XXX */ 1.685 + res->ai_flags = EVUTIL_AI_LIBEVENT_ALLOCATED; 1.686 + res->ai_socktype = hints->ai_socktype; 1.687 + res->ai_protocol = hints->ai_protocol; 1.688 + 1.689 + return res; 1.690 +} 1.691 + 1.692 +/* Append the addrinfo 'append' to the end of 'first', and return the start of 1.693 + * the list. Either element can be NULL, in which case we return the element 1.694 + * that is not NULL. */ 1.695 +struct evutil_addrinfo * 1.696 +evutil_addrinfo_append(struct evutil_addrinfo *first, 1.697 + struct evutil_addrinfo *append) 1.698 +{ 1.699 + struct evutil_addrinfo *ai = first; 1.700 + if (!ai) 1.701 + return append; 1.702 + while (ai->ai_next) 1.703 + ai = ai->ai_next; 1.704 + ai->ai_next = append; 1.705 + 1.706 + return first; 1.707 +} 1.708 + 1.709 +static int 1.710 +parse_numeric_servname(const char *servname) 1.711 +{ 1.712 + int n; 1.713 + char *endptr=NULL; 1.714 + n = (int) strtol(servname, &endptr, 10); 1.715 + if (n>=0 && n <= 65535 && servname[0] && endptr && !endptr[0]) 1.716 + return n; 1.717 + else 1.718 + return -1; 1.719 +} 1.720 + 1.721 +/** Parse a service name in 'servname', which can be a decimal port. 1.722 + * Return the port number, or -1 on error. 1.723 + */ 1.724 +static int 1.725 +evutil_parse_servname(const char *servname, const char *protocol, 1.726 + const struct evutil_addrinfo *hints) 1.727 +{ 1.728 + int n = parse_numeric_servname(servname); 1.729 + if (n>=0) 1.730 + return n; 1.731 +#if defined(_EVENT_HAVE_GETSERVBYNAME) || defined(WIN32) 1.732 + if (!(hints->ai_flags & EVUTIL_AI_NUMERICSERV)) { 1.733 + struct servent *ent = getservbyname(servname, protocol); 1.734 + if (ent) { 1.735 + return ntohs(ent->s_port); 1.736 + } 1.737 + } 1.738 +#endif 1.739 + return -1; 1.740 +} 1.741 + 1.742 +/* Return a string corresponding to a protocol number that we can pass to 1.743 + * getservyname. */ 1.744 +static const char * 1.745 +evutil_unparse_protoname(int proto) 1.746 +{ 1.747 + switch (proto) { 1.748 + case 0: 1.749 + return NULL; 1.750 + case IPPROTO_TCP: 1.751 + return "tcp"; 1.752 + case IPPROTO_UDP: 1.753 + return "udp"; 1.754 +#ifdef IPPROTO_SCTP 1.755 + case IPPROTO_SCTP: 1.756 + return "sctp"; 1.757 +#endif 1.758 + default: 1.759 +#ifdef _EVENT_HAVE_GETPROTOBYNUMBER 1.760 + { 1.761 + struct protoent *ent = getprotobynumber(proto); 1.762 + if (ent) 1.763 + return ent->p_name; 1.764 + } 1.765 +#endif 1.766 + return NULL; 1.767 + } 1.768 +} 1.769 + 1.770 +static void 1.771 +evutil_getaddrinfo_infer_protocols(struct evutil_addrinfo *hints) 1.772 +{ 1.773 + /* If we can guess the protocol from the socktype, do so. */ 1.774 + if (!hints->ai_protocol && hints->ai_socktype) { 1.775 + if (hints->ai_socktype == SOCK_DGRAM) 1.776 + hints->ai_protocol = IPPROTO_UDP; 1.777 + else if (hints->ai_socktype == SOCK_STREAM) 1.778 + hints->ai_protocol = IPPROTO_TCP; 1.779 + } 1.780 + 1.781 + /* Set the socktype if it isn't set. */ 1.782 + if (!hints->ai_socktype && hints->ai_protocol) { 1.783 + if (hints->ai_protocol == IPPROTO_UDP) 1.784 + hints->ai_socktype = SOCK_DGRAM; 1.785 + else if (hints->ai_protocol == IPPROTO_TCP) 1.786 + hints->ai_socktype = SOCK_STREAM; 1.787 +#ifdef IPPROTO_SCTP 1.788 + else if (hints->ai_protocol == IPPROTO_SCTP) 1.789 + hints->ai_socktype = SOCK_STREAM; 1.790 +#endif 1.791 + } 1.792 +} 1.793 + 1.794 +#if AF_UNSPEC != PF_UNSPEC 1.795 +#error "I cannot build on a system where AF_UNSPEC != PF_UNSPEC" 1.796 +#endif 1.797 + 1.798 +/** Implements the part of looking up hosts by name that's common to both 1.799 + * the blocking and nonblocking resolver: 1.800 + * - Adjust 'hints' to have a reasonable socktype and protocol. 1.801 + * - Look up the port based on 'servname', and store it in *portnum, 1.802 + * - Handle the nodename==NULL case 1.803 + * - Handle some invalid arguments cases. 1.804 + * - Handle the cases where nodename is an IPv4 or IPv6 address. 1.805 + * 1.806 + * If we need the resolver to look up the hostname, we return 1.807 + * EVUTIL_EAI_NEED_RESOLVE. Otherwise, we can completely implement 1.808 + * getaddrinfo: we return 0 or an appropriate EVUTIL_EAI_* error, and 1.809 + * set *res as getaddrinfo would. 1.810 + */ 1.811 +int 1.812 +evutil_getaddrinfo_common(const char *nodename, const char *servname, 1.813 + struct evutil_addrinfo *hints, struct evutil_addrinfo **res, int *portnum) 1.814 +{ 1.815 + int port = 0; 1.816 + const char *pname; 1.817 + 1.818 + if (nodename == NULL && servname == NULL) 1.819 + return EVUTIL_EAI_NONAME; 1.820 + 1.821 + /* We only understand 3 families */ 1.822 + if (hints->ai_family != PF_UNSPEC && hints->ai_family != PF_INET && 1.823 + hints->ai_family != PF_INET6) 1.824 + return EVUTIL_EAI_FAMILY; 1.825 + 1.826 + evutil_getaddrinfo_infer_protocols(hints); 1.827 + 1.828 + /* Look up the port number and protocol, if possible. */ 1.829 + pname = evutil_unparse_protoname(hints->ai_protocol); 1.830 + if (servname) { 1.831 + /* XXXX We could look at the protocol we got back from 1.832 + * getservbyname, but it doesn't seem too useful. */ 1.833 + port = evutil_parse_servname(servname, pname, hints); 1.834 + if (port < 0) { 1.835 + return EVUTIL_EAI_NONAME; 1.836 + } 1.837 + } 1.838 + 1.839 + /* If we have no node name, then we're supposed to bind to 'any' and 1.840 + * connect to localhost. */ 1.841 + if (nodename == NULL) { 1.842 + struct evutil_addrinfo *res4=NULL, *res6=NULL; 1.843 + if (hints->ai_family != PF_INET) { /* INET6 or UNSPEC. */ 1.844 + struct sockaddr_in6 sin6; 1.845 + memset(&sin6, 0, sizeof(sin6)); 1.846 + sin6.sin6_family = AF_INET6; 1.847 + sin6.sin6_port = htons(port); 1.848 + if (hints->ai_flags & EVUTIL_AI_PASSIVE) { 1.849 + /* Bind to :: */ 1.850 + } else { 1.851 + /* connect to ::1 */ 1.852 + sin6.sin6_addr.s6_addr[15] = 1; 1.853 + } 1.854 + res6 = evutil_new_addrinfo((struct sockaddr*)&sin6, 1.855 + sizeof(sin6), hints); 1.856 + if (!res6) 1.857 + return EVUTIL_EAI_MEMORY; 1.858 + } 1.859 + 1.860 + if (hints->ai_family != PF_INET6) { /* INET or UNSPEC */ 1.861 + struct sockaddr_in sin; 1.862 + memset(&sin, 0, sizeof(sin)); 1.863 + sin.sin_family = AF_INET; 1.864 + sin.sin_port = htons(port); 1.865 + if (hints->ai_flags & EVUTIL_AI_PASSIVE) { 1.866 + /* Bind to 0.0.0.0 */ 1.867 + } else { 1.868 + /* connect to 127.0.0.1 */ 1.869 + sin.sin_addr.s_addr = htonl(0x7f000001); 1.870 + } 1.871 + res4 = evutil_new_addrinfo((struct sockaddr*)&sin, 1.872 + sizeof(sin), hints); 1.873 + if (!res4) { 1.874 + if (res6) 1.875 + evutil_freeaddrinfo(res6); 1.876 + return EVUTIL_EAI_MEMORY; 1.877 + } 1.878 + } 1.879 + *res = evutil_addrinfo_append(res4, res6); 1.880 + return 0; 1.881 + } 1.882 + 1.883 + /* If we can, we should try to parse the hostname without resolving 1.884 + * it. */ 1.885 + /* Try ipv6. */ 1.886 + if (hints->ai_family == PF_INET6 || hints->ai_family == PF_UNSPEC) { 1.887 + struct sockaddr_in6 sin6; 1.888 + memset(&sin6, 0, sizeof(sin6)); 1.889 + if (1==evutil_inet_pton(AF_INET6, nodename, &sin6.sin6_addr)) { 1.890 + /* Got an ipv6 address. */ 1.891 + sin6.sin6_family = AF_INET6; 1.892 + sin6.sin6_port = htons(port); 1.893 + *res = evutil_new_addrinfo((struct sockaddr*)&sin6, 1.894 + sizeof(sin6), hints); 1.895 + if (!*res) 1.896 + return EVUTIL_EAI_MEMORY; 1.897 + return 0; 1.898 + } 1.899 + } 1.900 + 1.901 + /* Try ipv4. */ 1.902 + if (hints->ai_family == PF_INET || hints->ai_family == PF_UNSPEC) { 1.903 + struct sockaddr_in sin; 1.904 + memset(&sin, 0, sizeof(sin)); 1.905 + if (1==evutil_inet_pton(AF_INET, nodename, &sin.sin_addr)) { 1.906 + /* Got an ipv6 address. */ 1.907 + sin.sin_family = AF_INET; 1.908 + sin.sin_port = htons(port); 1.909 + *res = evutil_new_addrinfo((struct sockaddr*)&sin, 1.910 + sizeof(sin), hints); 1.911 + if (!*res) 1.912 + return EVUTIL_EAI_MEMORY; 1.913 + return 0; 1.914 + } 1.915 + } 1.916 + 1.917 + 1.918 + /* If we have reached this point, we definitely need to do a DNS 1.919 + * lookup. */ 1.920 + if ((hints->ai_flags & EVUTIL_AI_NUMERICHOST)) { 1.921 + /* If we're not allowed to do one, then say so. */ 1.922 + return EVUTIL_EAI_NONAME; 1.923 + } 1.924 + *portnum = port; 1.925 + return EVUTIL_EAI_NEED_RESOLVE; 1.926 +} 1.927 + 1.928 +#ifdef _EVENT_HAVE_GETADDRINFO 1.929 +#define USE_NATIVE_GETADDRINFO 1.930 +#endif 1.931 + 1.932 +#ifdef USE_NATIVE_GETADDRINFO 1.933 +/* A mask of all the flags that we declare, so we can clear them before calling 1.934 + * the native getaddrinfo */ 1.935 +static const unsigned int ALL_NONNATIVE_AI_FLAGS = 1.936 +#ifndef AI_PASSIVE 1.937 + EVUTIL_AI_PASSIVE | 1.938 +#endif 1.939 +#ifndef AI_CANONNAME 1.940 + EVUTIL_AI_CANONNAME | 1.941 +#endif 1.942 +#ifndef AI_NUMERICHOST 1.943 + EVUTIL_AI_NUMERICHOST | 1.944 +#endif 1.945 +#ifndef AI_NUMERICSERV 1.946 + EVUTIL_AI_NUMERICSERV | 1.947 +#endif 1.948 +#ifndef AI_ADDRCONFIG 1.949 + EVUTIL_AI_ADDRCONFIG | 1.950 +#endif 1.951 +#ifndef AI_ALL 1.952 + EVUTIL_AI_ALL | 1.953 +#endif 1.954 +#ifndef AI_V4MAPPED 1.955 + EVUTIL_AI_V4MAPPED | 1.956 +#endif 1.957 + EVUTIL_AI_LIBEVENT_ALLOCATED; 1.958 + 1.959 +static const unsigned int ALL_NATIVE_AI_FLAGS = 1.960 +#ifdef AI_PASSIVE 1.961 + AI_PASSIVE | 1.962 +#endif 1.963 +#ifdef AI_CANONNAME 1.964 + AI_CANONNAME | 1.965 +#endif 1.966 +#ifdef AI_NUMERICHOST 1.967 + AI_NUMERICHOST | 1.968 +#endif 1.969 +#ifdef AI_NUMERICSERV 1.970 + AI_NUMERICSERV | 1.971 +#endif 1.972 +#ifdef AI_ADDRCONFIG 1.973 + AI_ADDRCONFIG | 1.974 +#endif 1.975 +#ifdef AI_ALL 1.976 + AI_ALL | 1.977 +#endif 1.978 +#ifdef AI_V4MAPPED 1.979 + AI_V4MAPPED | 1.980 +#endif 1.981 + 0; 1.982 +#endif 1.983 + 1.984 +#ifndef USE_NATIVE_GETADDRINFO 1.985 +/* Helper for systems with no getaddrinfo(): make one or more addrinfos out of 1.986 + * a struct hostent. 1.987 + */ 1.988 +static struct evutil_addrinfo * 1.989 +addrinfo_from_hostent(const struct hostent *ent, 1.990 + int port, const struct evutil_addrinfo *hints) 1.991 +{ 1.992 + int i; 1.993 + struct sockaddr_in sin; 1.994 + struct sockaddr_in6 sin6; 1.995 + struct sockaddr *sa; 1.996 + int socklen; 1.997 + struct evutil_addrinfo *res=NULL, *ai; 1.998 + void *addrp; 1.999 + 1.1000 + if (ent->h_addrtype == PF_INET) { 1.1001 + memset(&sin, 0, sizeof(sin)); 1.1002 + sin.sin_family = AF_INET; 1.1003 + sin.sin_port = htons(port); 1.1004 + sa = (struct sockaddr *)&sin; 1.1005 + socklen = sizeof(struct sockaddr_in); 1.1006 + addrp = &sin.sin_addr; 1.1007 + if (ent->h_length != sizeof(sin.sin_addr)) { 1.1008 + event_warnx("Weird h_length from gethostbyname"); 1.1009 + return NULL; 1.1010 + } 1.1011 + } else if (ent->h_addrtype == PF_INET6) { 1.1012 + memset(&sin6, 0, sizeof(sin6)); 1.1013 + sin6.sin6_family = AF_INET6; 1.1014 + sin6.sin6_port = htons(port); 1.1015 + sa = (struct sockaddr *)&sin6; 1.1016 + socklen = sizeof(struct sockaddr_in); 1.1017 + addrp = &sin6.sin6_addr; 1.1018 + if (ent->h_length != sizeof(sin6.sin6_addr)) { 1.1019 + event_warnx("Weird h_length from gethostbyname"); 1.1020 + return NULL; 1.1021 + } 1.1022 + } else 1.1023 + return NULL; 1.1024 + 1.1025 + for (i = 0; ent->h_addr_list[i]; ++i) { 1.1026 + memcpy(addrp, ent->h_addr_list[i], ent->h_length); 1.1027 + ai = evutil_new_addrinfo(sa, socklen, hints); 1.1028 + if (!ai) { 1.1029 + evutil_freeaddrinfo(res); 1.1030 + return NULL; 1.1031 + } 1.1032 + res = evutil_addrinfo_append(res, ai); 1.1033 + } 1.1034 + 1.1035 + if (res && ((hints->ai_flags & EVUTIL_AI_CANONNAME) && ent->h_name)) { 1.1036 + res->ai_canonname = mm_strdup(ent->h_name); 1.1037 + if (res->ai_canonname == NULL) { 1.1038 + evutil_freeaddrinfo(res); 1.1039 + return NULL; 1.1040 + } 1.1041 + } 1.1042 + 1.1043 + return res; 1.1044 +} 1.1045 +#endif 1.1046 + 1.1047 +/* If the EVUTIL_AI_ADDRCONFIG flag is set on hints->ai_flags, and 1.1048 + * hints->ai_family is PF_UNSPEC, then revise the value of hints->ai_family so 1.1049 + * that we'll only get addresses we could maybe connect to. 1.1050 + */ 1.1051 +void 1.1052 +evutil_adjust_hints_for_addrconfig(struct evutil_addrinfo *hints) 1.1053 +{ 1.1054 + if (!(hints->ai_flags & EVUTIL_AI_ADDRCONFIG)) 1.1055 + return; 1.1056 + if (hints->ai_family != PF_UNSPEC) 1.1057 + return; 1.1058 + if (!have_checked_interfaces) 1.1059 + evutil_check_interfaces(0); 1.1060 + if (had_ipv4_address && !had_ipv6_address) { 1.1061 + hints->ai_family = PF_INET; 1.1062 + } else if (!had_ipv4_address && had_ipv6_address) { 1.1063 + hints->ai_family = PF_INET6; 1.1064 + } 1.1065 +} 1.1066 + 1.1067 +#ifdef USE_NATIVE_GETADDRINFO 1.1068 +static int need_numeric_port_hack_=0; 1.1069 +static int need_socktype_protocol_hack_=0; 1.1070 +static int tested_for_getaddrinfo_hacks=0; 1.1071 + 1.1072 +/* Some older BSDs (like OpenBSD up to 4.6) used to believe that 1.1073 + giving a numeric port without giving an ai_socktype was verboten. 1.1074 + We test for this so we can apply an appropriate workaround. If it 1.1075 + turns out that the bug is present, then: 1.1076 + 1.1077 + - If nodename==NULL and servname is numeric, we build an answer 1.1078 + ourselves using evutil_getaddrinfo_common(). 1.1079 + 1.1080 + - If nodename!=NULL and servname is numeric, then we set 1.1081 + servname=NULL when calling getaddrinfo, and post-process the 1.1082 + result to set the ports on it. 1.1083 + 1.1084 + We test for this bug at runtime, since otherwise we can't have the 1.1085 + same binary run on multiple BSD versions. 1.1086 + 1.1087 + - Some versions of Solaris believe that it's nice to leave to protocol 1.1088 + field set to 0. We test for this so we can apply an appropriate 1.1089 + workaround. 1.1090 +*/ 1.1091 +static void 1.1092 +test_for_getaddrinfo_hacks(void) 1.1093 +{ 1.1094 + int r, r2; 1.1095 + struct evutil_addrinfo *ai=NULL, *ai2=NULL; 1.1096 + struct evutil_addrinfo hints; 1.1097 + 1.1098 + memset(&hints,0,sizeof(hints)); 1.1099 + hints.ai_family = PF_UNSPEC; 1.1100 + hints.ai_flags = 1.1101 +#ifdef AI_NUMERICHOST 1.1102 + AI_NUMERICHOST | 1.1103 +#endif 1.1104 +#ifdef AI_NUMERICSERV 1.1105 + AI_NUMERICSERV | 1.1106 +#endif 1.1107 + 0; 1.1108 + r = getaddrinfo("1.2.3.4", "80", &hints, &ai); 1.1109 + hints.ai_socktype = SOCK_STREAM; 1.1110 + r2 = getaddrinfo("1.2.3.4", "80", &hints, &ai2); 1.1111 + if (r2 == 0 && r != 0) { 1.1112 + need_numeric_port_hack_=1; 1.1113 + } 1.1114 + if (ai2 && ai2->ai_protocol == 0) { 1.1115 + need_socktype_protocol_hack_=1; 1.1116 + } 1.1117 + 1.1118 + if (ai) 1.1119 + freeaddrinfo(ai); 1.1120 + if (ai2) 1.1121 + freeaddrinfo(ai2); 1.1122 + tested_for_getaddrinfo_hacks=1; 1.1123 +} 1.1124 + 1.1125 +static inline int 1.1126 +need_numeric_port_hack(void) 1.1127 +{ 1.1128 + if (!tested_for_getaddrinfo_hacks) 1.1129 + test_for_getaddrinfo_hacks(); 1.1130 + return need_numeric_port_hack_; 1.1131 +} 1.1132 + 1.1133 +static inline int 1.1134 +need_socktype_protocol_hack(void) 1.1135 +{ 1.1136 + if (!tested_for_getaddrinfo_hacks) 1.1137 + test_for_getaddrinfo_hacks(); 1.1138 + return need_socktype_protocol_hack_; 1.1139 +} 1.1140 + 1.1141 +static void 1.1142 +apply_numeric_port_hack(int port, struct evutil_addrinfo **ai) 1.1143 +{ 1.1144 + /* Now we run through the list and set the ports on all of the 1.1145 + * results where ports would make sense. */ 1.1146 + for ( ; *ai; ai = &(*ai)->ai_next) { 1.1147 + struct sockaddr *sa = (*ai)->ai_addr; 1.1148 + if (sa && sa->sa_family == AF_INET) { 1.1149 + struct sockaddr_in *sin = (struct sockaddr_in*)sa; 1.1150 + sin->sin_port = htons(port); 1.1151 + } else if (sa && sa->sa_family == AF_INET6) { 1.1152 + struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)sa; 1.1153 + sin6->sin6_port = htons(port); 1.1154 + } else { 1.1155 + /* A numeric port makes no sense here; remove this one 1.1156 + * from the list. */ 1.1157 + struct evutil_addrinfo *victim = *ai; 1.1158 + *ai = victim->ai_next; 1.1159 + victim->ai_next = NULL; 1.1160 + freeaddrinfo(victim); 1.1161 + } 1.1162 + } 1.1163 +} 1.1164 + 1.1165 +static int 1.1166 +apply_socktype_protocol_hack(struct evutil_addrinfo *ai) 1.1167 +{ 1.1168 + struct evutil_addrinfo *ai_new; 1.1169 + for (; ai; ai = ai->ai_next) { 1.1170 + evutil_getaddrinfo_infer_protocols(ai); 1.1171 + if (ai->ai_socktype || ai->ai_protocol) 1.1172 + continue; 1.1173 + ai_new = mm_malloc(sizeof(*ai_new)); 1.1174 + if (!ai_new) 1.1175 + return -1; 1.1176 + memcpy(ai_new, ai, sizeof(*ai_new)); 1.1177 + ai->ai_socktype = SOCK_STREAM; 1.1178 + ai->ai_protocol = IPPROTO_TCP; 1.1179 + ai_new->ai_socktype = SOCK_DGRAM; 1.1180 + ai_new->ai_protocol = IPPROTO_UDP; 1.1181 + 1.1182 + ai_new->ai_next = ai->ai_next; 1.1183 + ai->ai_next = ai_new; 1.1184 + } 1.1185 + return 0; 1.1186 +} 1.1187 +#endif 1.1188 + 1.1189 +int 1.1190 +evutil_getaddrinfo(const char *nodename, const char *servname, 1.1191 + const struct evutil_addrinfo *hints_in, struct evutil_addrinfo **res) 1.1192 +{ 1.1193 +#ifdef USE_NATIVE_GETADDRINFO 1.1194 + struct evutil_addrinfo hints; 1.1195 + int portnum=-1, need_np_hack, err; 1.1196 + 1.1197 + if (hints_in) { 1.1198 + memcpy(&hints, hints_in, sizeof(hints)); 1.1199 + } else { 1.1200 + memset(&hints, 0, sizeof(hints)); 1.1201 + hints.ai_family = PF_UNSPEC; 1.1202 + } 1.1203 + 1.1204 +#ifndef AI_ADDRCONFIG 1.1205 + /* Not every system has AI_ADDRCONFIG, so fake it. */ 1.1206 + if (hints.ai_family == PF_UNSPEC && 1.1207 + (hints.ai_flags & EVUTIL_AI_ADDRCONFIG)) { 1.1208 + evutil_adjust_hints_for_addrconfig(&hints); 1.1209 + } 1.1210 +#endif 1.1211 + 1.1212 +#ifndef AI_NUMERICSERV 1.1213 + /* Not every system has AI_NUMERICSERV, so fake it. */ 1.1214 + if (hints.ai_flags & EVUTIL_AI_NUMERICSERV) { 1.1215 + if (servname && parse_numeric_servname(servname)<0) 1.1216 + return EVUTIL_EAI_NONAME; 1.1217 + } 1.1218 +#endif 1.1219 + 1.1220 + /* Enough operating systems handle enough common non-resolve 1.1221 + * cases here weirdly enough that we are better off just 1.1222 + * overriding them. For example: 1.1223 + * 1.1224 + * - Windows doesn't like to infer the protocol from the 1.1225 + * socket type, or fill in socket or protocol types much at 1.1226 + * all. It also seems to do its own broken implicit 1.1227 + * always-on version of AI_ADDRCONFIG that keeps it from 1.1228 + * ever resolving even a literal IPv6 address when 1.1229 + * ai_addrtype is PF_UNSPEC. 1.1230 + */ 1.1231 +#ifdef WIN32 1.1232 + { 1.1233 + int tmp_port; 1.1234 + err = evutil_getaddrinfo_common(nodename,servname,&hints, 1.1235 + res, &tmp_port); 1.1236 + if (err == 0 || 1.1237 + err == EVUTIL_EAI_MEMORY || 1.1238 + err == EVUTIL_EAI_NONAME) 1.1239 + return err; 1.1240 + /* If we make it here, the system getaddrinfo can 1.1241 + * have a crack at it. */ 1.1242 + } 1.1243 +#endif 1.1244 + 1.1245 + /* See documentation for need_numeric_port_hack above.*/ 1.1246 + need_np_hack = need_numeric_port_hack() && servname && !hints.ai_socktype 1.1247 + && ((portnum=parse_numeric_servname(servname)) >= 0); 1.1248 + if (need_np_hack) { 1.1249 + if (!nodename) 1.1250 + return evutil_getaddrinfo_common( 1.1251 + NULL,servname,&hints, res, &portnum); 1.1252 + servname = NULL; 1.1253 + } 1.1254 + 1.1255 + if (need_socktype_protocol_hack()) { 1.1256 + evutil_getaddrinfo_infer_protocols(&hints); 1.1257 + } 1.1258 + 1.1259 + /* Make sure that we didn't actually steal any AI_FLAGS values that 1.1260 + * the system is using. (This is a constant expression, and should ge 1.1261 + * optimized out.) 1.1262 + * 1.1263 + * XXXX Turn this into a compile-time failure rather than a run-time 1.1264 + * failure. 1.1265 + */ 1.1266 + EVUTIL_ASSERT((ALL_NONNATIVE_AI_FLAGS & ALL_NATIVE_AI_FLAGS) == 0); 1.1267 + 1.1268 + /* Clear any flags that only libevent understands. */ 1.1269 + hints.ai_flags &= ~ALL_NONNATIVE_AI_FLAGS; 1.1270 + 1.1271 + err = getaddrinfo(nodename, servname, &hints, res); 1.1272 + if (need_np_hack) 1.1273 + apply_numeric_port_hack(portnum, res); 1.1274 + 1.1275 + if (need_socktype_protocol_hack()) { 1.1276 + if (apply_socktype_protocol_hack(*res) < 0) { 1.1277 + evutil_freeaddrinfo(*res); 1.1278 + *res = NULL; 1.1279 + return EVUTIL_EAI_MEMORY; 1.1280 + } 1.1281 + } 1.1282 + return err; 1.1283 +#else 1.1284 + int port=0, err; 1.1285 + struct hostent *ent = NULL; 1.1286 + struct evutil_addrinfo hints; 1.1287 + 1.1288 + if (hints_in) { 1.1289 + memcpy(&hints, hints_in, sizeof(hints)); 1.1290 + } else { 1.1291 + memset(&hints, 0, sizeof(hints)); 1.1292 + hints.ai_family = PF_UNSPEC; 1.1293 + } 1.1294 + 1.1295 + evutil_adjust_hints_for_addrconfig(&hints); 1.1296 + 1.1297 + err = evutil_getaddrinfo_common(nodename, servname, &hints, res, &port); 1.1298 + if (err != EVUTIL_EAI_NEED_RESOLVE) { 1.1299 + /* We either succeeded or failed. No need to continue */ 1.1300 + return err; 1.1301 + } 1.1302 + 1.1303 + err = 0; 1.1304 + /* Use any of the various gethostbyname_r variants as available. */ 1.1305 + { 1.1306 +#ifdef _EVENT_HAVE_GETHOSTBYNAME_R_6_ARG 1.1307 + /* This one is what glibc provides. */ 1.1308 + char buf[2048]; 1.1309 + struct hostent hostent; 1.1310 + int r; 1.1311 + r = gethostbyname_r(nodename, &hostent, buf, sizeof(buf), &ent, 1.1312 + &err); 1.1313 +#elif defined(_EVENT_HAVE_GETHOSTBYNAME_R_5_ARG) 1.1314 + char buf[2048]; 1.1315 + struct hostent hostent; 1.1316 + ent = gethostbyname_r(nodename, &hostent, buf, sizeof(buf), 1.1317 + &err); 1.1318 +#elif defined(_EVENT_HAVE_GETHOSTBYNAME_R_3_ARG) 1.1319 + struct hostent_data data; 1.1320 + struct hostent hostent; 1.1321 + memset(&data, 0, sizeof(data)); 1.1322 + err = gethostbyname_r(nodename, &hostent, &data); 1.1323 + ent = err ? NULL : &hostent; 1.1324 +#else 1.1325 + /* fall back to gethostbyname. */ 1.1326 + /* XXXX This needs a lock everywhere but Windows. */ 1.1327 + ent = gethostbyname(nodename); 1.1328 +#ifdef WIN32 1.1329 + err = WSAGetLastError(); 1.1330 +#else 1.1331 + err = h_errno; 1.1332 +#endif 1.1333 +#endif 1.1334 + 1.1335 + /* Now we have either ent or err set. */ 1.1336 + if (!ent) { 1.1337 + /* XXX is this right for windows ? */ 1.1338 + switch (err) { 1.1339 + case TRY_AGAIN: 1.1340 + return EVUTIL_EAI_AGAIN; 1.1341 + case NO_RECOVERY: 1.1342 + default: 1.1343 + return EVUTIL_EAI_FAIL; 1.1344 + case HOST_NOT_FOUND: 1.1345 + return EVUTIL_EAI_NONAME; 1.1346 + case NO_ADDRESS: 1.1347 +#if NO_DATA != NO_ADDRESS 1.1348 + case NO_DATA: 1.1349 +#endif 1.1350 + return EVUTIL_EAI_NODATA; 1.1351 + } 1.1352 + } 1.1353 + 1.1354 + if (ent->h_addrtype != hints.ai_family && 1.1355 + hints.ai_family != PF_UNSPEC) { 1.1356 + /* This wasn't the type we were hoping for. Too bad 1.1357 + * we never had a chance to ask gethostbyname for what 1.1358 + * we wanted. */ 1.1359 + return EVUTIL_EAI_NONAME; 1.1360 + } 1.1361 + 1.1362 + /* Make sure we got _some_ answers. */ 1.1363 + if (ent->h_length == 0) 1.1364 + return EVUTIL_EAI_NODATA; 1.1365 + 1.1366 + /* If we got an address type we don't know how to make a 1.1367 + sockaddr for, give up. */ 1.1368 + if (ent->h_addrtype != PF_INET && ent->h_addrtype != PF_INET6) 1.1369 + return EVUTIL_EAI_FAMILY; 1.1370 + 1.1371 + *res = addrinfo_from_hostent(ent, port, &hints); 1.1372 + if (! *res) 1.1373 + return EVUTIL_EAI_MEMORY; 1.1374 + } 1.1375 + 1.1376 + return 0; 1.1377 +#endif 1.1378 +} 1.1379 + 1.1380 +void 1.1381 +evutil_freeaddrinfo(struct evutil_addrinfo *ai) 1.1382 +{ 1.1383 +#ifdef _EVENT_HAVE_GETADDRINFO 1.1384 + if (!(ai->ai_flags & EVUTIL_AI_LIBEVENT_ALLOCATED)) { 1.1385 + freeaddrinfo(ai); 1.1386 + return; 1.1387 + } 1.1388 +#endif 1.1389 + while (ai) { 1.1390 + struct evutil_addrinfo *next = ai->ai_next; 1.1391 + if (ai->ai_canonname) 1.1392 + mm_free(ai->ai_canonname); 1.1393 + mm_free(ai); 1.1394 + ai = next; 1.1395 + } 1.1396 +} 1.1397 + 1.1398 +static evdns_getaddrinfo_fn evdns_getaddrinfo_impl = NULL; 1.1399 + 1.1400 +void 1.1401 +evutil_set_evdns_getaddrinfo_fn(evdns_getaddrinfo_fn fn) 1.1402 +{ 1.1403 + if (!evdns_getaddrinfo_impl) 1.1404 + evdns_getaddrinfo_impl = fn; 1.1405 +} 1.1406 + 1.1407 +/* Internal helper function: act like evdns_getaddrinfo if dns_base is set; 1.1408 + * otherwise do a blocking resolve and pass the result to the callback in the 1.1409 + * way that evdns_getaddrinfo would. 1.1410 + */ 1.1411 +int 1.1412 +evutil_getaddrinfo_async(struct evdns_base *dns_base, 1.1413 + const char *nodename, const char *servname, 1.1414 + const struct evutil_addrinfo *hints_in, 1.1415 + void (*cb)(int, struct evutil_addrinfo *, void *), void *arg) 1.1416 +{ 1.1417 + if (dns_base && evdns_getaddrinfo_impl) { 1.1418 + evdns_getaddrinfo_impl( 1.1419 + dns_base, nodename, servname, hints_in, cb, arg); 1.1420 + } else { 1.1421 + struct evutil_addrinfo *ai=NULL; 1.1422 + int err; 1.1423 + err = evutil_getaddrinfo(nodename, servname, hints_in, &ai); 1.1424 + cb(err, ai, arg); 1.1425 + } 1.1426 + return 0; 1.1427 +} 1.1428 + 1.1429 +const char * 1.1430 +evutil_gai_strerror(int err) 1.1431 +{ 1.1432 + /* As a sneaky side-benefit, this case statement will get most 1.1433 + * compilers to tell us if any of the error codes we defined 1.1434 + * conflict with the platform's native error codes. */ 1.1435 + switch (err) { 1.1436 + case EVUTIL_EAI_CANCEL: 1.1437 + return "Request canceled"; 1.1438 + case 0: 1.1439 + return "No error"; 1.1440 + 1.1441 + case EVUTIL_EAI_ADDRFAMILY: 1.1442 + return "address family for nodename not supported"; 1.1443 + case EVUTIL_EAI_AGAIN: 1.1444 + return "temporary failure in name resolution"; 1.1445 + case EVUTIL_EAI_BADFLAGS: 1.1446 + return "invalid value for ai_flags"; 1.1447 + case EVUTIL_EAI_FAIL: 1.1448 + return "non-recoverable failure in name resolution"; 1.1449 + case EVUTIL_EAI_FAMILY: 1.1450 + return "ai_family not supported"; 1.1451 + case EVUTIL_EAI_MEMORY: 1.1452 + return "memory allocation failure"; 1.1453 + case EVUTIL_EAI_NODATA: 1.1454 + return "no address associated with nodename"; 1.1455 + case EVUTIL_EAI_NONAME: 1.1456 + return "nodename nor servname provided, or not known"; 1.1457 + case EVUTIL_EAI_SERVICE: 1.1458 + return "servname not supported for ai_socktype"; 1.1459 + case EVUTIL_EAI_SOCKTYPE: 1.1460 + return "ai_socktype not supported"; 1.1461 + case EVUTIL_EAI_SYSTEM: 1.1462 + return "system error"; 1.1463 + default: 1.1464 +#if defined(USE_NATIVE_GETADDRINFO) && defined(WIN32) 1.1465 + return gai_strerrorA(err); 1.1466 +#elif defined(USE_NATIVE_GETADDRINFO) 1.1467 + return gai_strerror(err); 1.1468 +#else 1.1469 + return "Unknown error code"; 1.1470 +#endif 1.1471 + } 1.1472 +} 1.1473 + 1.1474 +#ifdef WIN32 1.1475 +#define E(code, s) { code, (s " [" #code " ]") } 1.1476 +static struct { int code; const char *msg; } windows_socket_errors[] = { 1.1477 + E(WSAEINTR, "Interrupted function call"), 1.1478 + E(WSAEACCES, "Permission denied"), 1.1479 + E(WSAEFAULT, "Bad address"), 1.1480 + E(WSAEINVAL, "Invalid argument"), 1.1481 + E(WSAEMFILE, "Too many open files"), 1.1482 + E(WSAEWOULDBLOCK, "Resource temporarily unavailable"), 1.1483 + E(WSAEINPROGRESS, "Operation now in progress"), 1.1484 + E(WSAEALREADY, "Operation already in progress"), 1.1485 + E(WSAENOTSOCK, "Socket operation on nonsocket"), 1.1486 + E(WSAEDESTADDRREQ, "Destination address required"), 1.1487 + E(WSAEMSGSIZE, "Message too long"), 1.1488 + E(WSAEPROTOTYPE, "Protocol wrong for socket"), 1.1489 + E(WSAENOPROTOOPT, "Bad protocol option"), 1.1490 + E(WSAEPROTONOSUPPORT, "Protocol not supported"), 1.1491 + E(WSAESOCKTNOSUPPORT, "Socket type not supported"), 1.1492 + /* What's the difference between NOTSUPP and NOSUPPORT? :) */ 1.1493 + E(WSAEOPNOTSUPP, "Operation not supported"), 1.1494 + E(WSAEPFNOSUPPORT, "Protocol family not supported"), 1.1495 + E(WSAEAFNOSUPPORT, "Address family not supported by protocol family"), 1.1496 + E(WSAEADDRINUSE, "Address already in use"), 1.1497 + E(WSAEADDRNOTAVAIL, "Cannot assign requested address"), 1.1498 + E(WSAENETDOWN, "Network is down"), 1.1499 + E(WSAENETUNREACH, "Network is unreachable"), 1.1500 + E(WSAENETRESET, "Network dropped connection on reset"), 1.1501 + E(WSAECONNABORTED, "Software caused connection abort"), 1.1502 + E(WSAECONNRESET, "Connection reset by peer"), 1.1503 + E(WSAENOBUFS, "No buffer space available"), 1.1504 + E(WSAEISCONN, "Socket is already connected"), 1.1505 + E(WSAENOTCONN, "Socket is not connected"), 1.1506 + E(WSAESHUTDOWN, "Cannot send after socket shutdown"), 1.1507 + E(WSAETIMEDOUT, "Connection timed out"), 1.1508 + E(WSAECONNREFUSED, "Connection refused"), 1.1509 + E(WSAEHOSTDOWN, "Host is down"), 1.1510 + E(WSAEHOSTUNREACH, "No route to host"), 1.1511 + E(WSAEPROCLIM, "Too many processes"), 1.1512 + 1.1513 + /* Yes, some of these start with WSA, not WSAE. No, I don't know why. */ 1.1514 + E(WSASYSNOTREADY, "Network subsystem is unavailable"), 1.1515 + E(WSAVERNOTSUPPORTED, "Winsock.dll out of range"), 1.1516 + E(WSANOTINITIALISED, "Successful WSAStartup not yet performed"), 1.1517 + E(WSAEDISCON, "Graceful shutdown now in progress"), 1.1518 +#ifdef WSATYPE_NOT_FOUND 1.1519 + E(WSATYPE_NOT_FOUND, "Class type not found"), 1.1520 +#endif 1.1521 + E(WSAHOST_NOT_FOUND, "Host not found"), 1.1522 + E(WSATRY_AGAIN, "Nonauthoritative host not found"), 1.1523 + E(WSANO_RECOVERY, "This is a nonrecoverable error"), 1.1524 + E(WSANO_DATA, "Valid name, no data record of requested type)"), 1.1525 + 1.1526 + /* There are some more error codes whose numeric values are marked 1.1527 + * <b>OS dependent</b>. They start with WSA_, apparently for the same 1.1528 + * reason that practitioners of some craft traditions deliberately 1.1529 + * introduce imperfections into their baskets and rugs "to allow the 1.1530 + * evil spirits to escape." If we catch them, then our binaries 1.1531 + * might not report consistent results across versions of Windows. 1.1532 + * Thus, I'm going to let them all fall through. 1.1533 + */ 1.1534 + { -1, NULL }, 1.1535 +}; 1.1536 +#undef E 1.1537 +/** Equivalent to strerror, but for windows socket errors. */ 1.1538 +const char * 1.1539 +evutil_socket_error_to_string(int errcode) 1.1540 +{ 1.1541 + /* XXXX Is there really no built-in function to do this? */ 1.1542 + int i; 1.1543 + for (i=0; windows_socket_errors[i].code >= 0; ++i) { 1.1544 + if (errcode == windows_socket_errors[i].code) 1.1545 + return windows_socket_errors[i].msg; 1.1546 + } 1.1547 + return strerror(errcode); 1.1548 +} 1.1549 +#endif 1.1550 + 1.1551 +int 1.1552 +evutil_snprintf(char *buf, size_t buflen, const char *format, ...) 1.1553 +{ 1.1554 + int r; 1.1555 + va_list ap; 1.1556 + va_start(ap, format); 1.1557 + r = evutil_vsnprintf(buf, buflen, format, ap); 1.1558 + va_end(ap); 1.1559 + return r; 1.1560 +} 1.1561 + 1.1562 +int 1.1563 +evutil_vsnprintf(char *buf, size_t buflen, const char *format, va_list ap) 1.1564 +{ 1.1565 + int r; 1.1566 + if (!buflen) 1.1567 + return 0; 1.1568 +#ifdef _MSC_VER 1.1569 + r = _vsnprintf(buf, buflen, format, ap); 1.1570 + if (r < 0) 1.1571 + r = _vscprintf(format, ap); 1.1572 +#elif defined(sgi) 1.1573 + /* Make sure we always use the correct vsnprintf on IRIX */ 1.1574 + extern int _xpg5_vsnprintf(char * __restrict, 1.1575 + __SGI_LIBC_NAMESPACE_QUALIFIER size_t, 1.1576 + const char * __restrict, /* va_list */ char *); 1.1577 + 1.1578 + r = _xpg5_vsnprintf(buf, buflen, format, ap); 1.1579 +#else 1.1580 + r = vsnprintf(buf, buflen, format, ap); 1.1581 +#endif 1.1582 + buf[buflen-1] = '\0'; 1.1583 + return r; 1.1584 +} 1.1585 + 1.1586 +#define USE_INTERNAL_NTOP 1.1587 +#define USE_INTERNAL_PTON 1.1588 + 1.1589 +const char * 1.1590 +evutil_inet_ntop(int af, const void *src, char *dst, size_t len) 1.1591 +{ 1.1592 +#if defined(_EVENT_HAVE_INET_NTOP) && !defined(USE_INTERNAL_NTOP) 1.1593 + return inet_ntop(af, src, dst, len); 1.1594 +#else 1.1595 + if (af == AF_INET) { 1.1596 + const struct in_addr *in = src; 1.1597 + const ev_uint32_t a = ntohl(in->s_addr); 1.1598 + int r; 1.1599 + r = evutil_snprintf(dst, len, "%d.%d.%d.%d", 1.1600 + (int)(ev_uint8_t)((a>>24)&0xff), 1.1601 + (int)(ev_uint8_t)((a>>16)&0xff), 1.1602 + (int)(ev_uint8_t)((a>>8 )&0xff), 1.1603 + (int)(ev_uint8_t)((a )&0xff)); 1.1604 + if (r<0||(size_t)r>=len) 1.1605 + return NULL; 1.1606 + else 1.1607 + return dst; 1.1608 +#ifdef AF_INET6 1.1609 + } else if (af == AF_INET6) { 1.1610 + const struct in6_addr *addr = src; 1.1611 + char buf[64], *cp; 1.1612 + int longestGapLen = 0, longestGapPos = -1, i, 1.1613 + curGapPos = -1, curGapLen = 0; 1.1614 + ev_uint16_t words[8]; 1.1615 + for (i = 0; i < 8; ++i) { 1.1616 + words[i] = 1.1617 + (((ev_uint16_t)addr->s6_addr[2*i])<<8) + addr->s6_addr[2*i+1]; 1.1618 + } 1.1619 + if (words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && 1.1620 + words[4] == 0 && ((words[5] == 0 && words[6] && words[7]) || 1.1621 + (words[5] == 0xffff))) { 1.1622 + /* This is an IPv4 address. */ 1.1623 + if (words[5] == 0) { 1.1624 + evutil_snprintf(buf, sizeof(buf), "::%d.%d.%d.%d", 1.1625 + addr->s6_addr[12], addr->s6_addr[13], 1.1626 + addr->s6_addr[14], addr->s6_addr[15]); 1.1627 + } else { 1.1628 + evutil_snprintf(buf, sizeof(buf), "::%x:%d.%d.%d.%d", words[5], 1.1629 + addr->s6_addr[12], addr->s6_addr[13], 1.1630 + addr->s6_addr[14], addr->s6_addr[15]); 1.1631 + } 1.1632 + if (strlen(buf) > len) 1.1633 + return NULL; 1.1634 + strlcpy(dst, buf, len); 1.1635 + return dst; 1.1636 + } 1.1637 + i = 0; 1.1638 + while (i < 8) { 1.1639 + if (words[i] == 0) { 1.1640 + curGapPos = i++; 1.1641 + curGapLen = 1; 1.1642 + while (i<8 && words[i] == 0) { 1.1643 + ++i; ++curGapLen; 1.1644 + } 1.1645 + if (curGapLen > longestGapLen) { 1.1646 + longestGapPos = curGapPos; 1.1647 + longestGapLen = curGapLen; 1.1648 + } 1.1649 + } else { 1.1650 + ++i; 1.1651 + } 1.1652 + } 1.1653 + if (longestGapLen<=1) 1.1654 + longestGapPos = -1; 1.1655 + 1.1656 + cp = buf; 1.1657 + for (i = 0; i < 8; ++i) { 1.1658 + if (words[i] == 0 && longestGapPos == i) { 1.1659 + if (i == 0) 1.1660 + *cp++ = ':'; 1.1661 + *cp++ = ':'; 1.1662 + while (i < 8 && words[i] == 0) 1.1663 + ++i; 1.1664 + --i; /* to compensate for loop increment. */ 1.1665 + } else { 1.1666 + evutil_snprintf(cp, 1.1667 + sizeof(buf)-(cp-buf), "%x", (unsigned)words[i]); 1.1668 + cp += strlen(cp); 1.1669 + if (i != 7) 1.1670 + *cp++ = ':'; 1.1671 + } 1.1672 + } 1.1673 + *cp = '\0'; 1.1674 + if (strlen(buf) > len) 1.1675 + return NULL; 1.1676 + strlcpy(dst, buf, len); 1.1677 + return dst; 1.1678 +#endif 1.1679 + } else { 1.1680 + return NULL; 1.1681 + } 1.1682 +#endif 1.1683 +} 1.1684 + 1.1685 +int 1.1686 +evutil_inet_pton(int af, const char *src, void *dst) 1.1687 +{ 1.1688 +#if defined(_EVENT_HAVE_INET_PTON) && !defined(USE_INTERNAL_PTON) 1.1689 + return inet_pton(af, src, dst); 1.1690 +#else 1.1691 + if (af == AF_INET) { 1.1692 + int a,b,c,d; 1.1693 + char more; 1.1694 + struct in_addr *addr = dst; 1.1695 + if (sscanf(src, "%d.%d.%d.%d%c", &a,&b,&c,&d,&more) != 4) 1.1696 + return 0; 1.1697 + if (a < 0 || a > 255) return 0; 1.1698 + if (b < 0 || b > 255) return 0; 1.1699 + if (c < 0 || c > 255) return 0; 1.1700 + if (d < 0 || d > 255) return 0; 1.1701 + addr->s_addr = htonl((a<<24) | (b<<16) | (c<<8) | d); 1.1702 + return 1; 1.1703 +#ifdef AF_INET6 1.1704 + } else if (af == AF_INET6) { 1.1705 + struct in6_addr *out = dst; 1.1706 + ev_uint16_t words[8]; 1.1707 + int gapPos = -1, i, setWords=0; 1.1708 + const char *dot = strchr(src, '.'); 1.1709 + const char *eow; /* end of words. */ 1.1710 + if (dot == src) 1.1711 + return 0; 1.1712 + else if (!dot) 1.1713 + eow = src+strlen(src); 1.1714 + else { 1.1715 + int byte1,byte2,byte3,byte4; 1.1716 + char more; 1.1717 + for (eow = dot-1; eow >= src && EVUTIL_ISDIGIT(*eow); --eow) 1.1718 + ; 1.1719 + ++eow; 1.1720 + 1.1721 + /* We use "scanf" because some platform inet_aton()s are too lax 1.1722 + * about IPv4 addresses of the form "1.2.3" */ 1.1723 + if (sscanf(eow, "%d.%d.%d.%d%c", 1.1724 + &byte1,&byte2,&byte3,&byte4,&more) != 4) 1.1725 + return 0; 1.1726 + 1.1727 + if (byte1 > 255 || byte1 < 0 || 1.1728 + byte2 > 255 || byte2 < 0 || 1.1729 + byte3 > 255 || byte3 < 0 || 1.1730 + byte4 > 255 || byte4 < 0) 1.1731 + return 0; 1.1732 + 1.1733 + words[6] = (byte1<<8) | byte2; 1.1734 + words[7] = (byte3<<8) | byte4; 1.1735 + setWords += 2; 1.1736 + } 1.1737 + 1.1738 + i = 0; 1.1739 + while (src < eow) { 1.1740 + if (i > 7) 1.1741 + return 0; 1.1742 + if (EVUTIL_ISXDIGIT(*src)) { 1.1743 + char *next; 1.1744 + long r = strtol(src, &next, 16); 1.1745 + if (next > 4+src) 1.1746 + return 0; 1.1747 + if (next == src) 1.1748 + return 0; 1.1749 + if (r<0 || r>65536) 1.1750 + return 0; 1.1751 + 1.1752 + words[i++] = (ev_uint16_t)r; 1.1753 + setWords++; 1.1754 + src = next; 1.1755 + if (*src != ':' && src != eow) 1.1756 + return 0; 1.1757 + ++src; 1.1758 + } else if (*src == ':' && i > 0 && gapPos==-1) { 1.1759 + gapPos = i; 1.1760 + ++src; 1.1761 + } else if (*src == ':' && i == 0 && src[1] == ':' && gapPos==-1) { 1.1762 + gapPos = i; 1.1763 + src += 2; 1.1764 + } else { 1.1765 + return 0; 1.1766 + } 1.1767 + } 1.1768 + 1.1769 + if (setWords > 8 || 1.1770 + (setWords == 8 && gapPos != -1) || 1.1771 + (setWords < 8 && gapPos == -1)) 1.1772 + return 0; 1.1773 + 1.1774 + if (gapPos >= 0) { 1.1775 + int nToMove = setWords - (dot ? 2 : 0) - gapPos; 1.1776 + int gapLen = 8 - setWords; 1.1777 + /* assert(nToMove >= 0); */ 1.1778 + if (nToMove < 0) 1.1779 + return -1; /* should be impossible */ 1.1780 + memmove(&words[gapPos+gapLen], &words[gapPos], 1.1781 + sizeof(ev_uint16_t)*nToMove); 1.1782 + memset(&words[gapPos], 0, sizeof(ev_uint16_t)*gapLen); 1.1783 + } 1.1784 + for (i = 0; i < 8; ++i) { 1.1785 + out->s6_addr[2*i ] = words[i] >> 8; 1.1786 + out->s6_addr[2*i+1] = words[i] & 0xff; 1.1787 + } 1.1788 + 1.1789 + return 1; 1.1790 +#endif 1.1791 + } else { 1.1792 + return -1; 1.1793 + } 1.1794 +#endif 1.1795 +} 1.1796 + 1.1797 +int 1.1798 +evutil_parse_sockaddr_port(const char *ip_as_string, struct sockaddr *out, int *outlen) 1.1799 +{ 1.1800 + int port; 1.1801 + char buf[128]; 1.1802 + const char *cp, *addr_part, *port_part; 1.1803 + int is_ipv6; 1.1804 + /* recognized formats are: 1.1805 + * [ipv6]:port 1.1806 + * ipv6 1.1807 + * [ipv6] 1.1808 + * ipv4:port 1.1809 + * ipv4 1.1810 + */ 1.1811 + 1.1812 + cp = strchr(ip_as_string, ':'); 1.1813 + if (*ip_as_string == '[') { 1.1814 + int len; 1.1815 + if (!(cp = strchr(ip_as_string, ']'))) { 1.1816 + return -1; 1.1817 + } 1.1818 + len = (int) ( cp-(ip_as_string + 1) ); 1.1819 + if (len > (int)sizeof(buf)-1) { 1.1820 + return -1; 1.1821 + } 1.1822 + memcpy(buf, ip_as_string+1, len); 1.1823 + buf[len] = '\0'; 1.1824 + addr_part = buf; 1.1825 + if (cp[1] == ':') 1.1826 + port_part = cp+2; 1.1827 + else 1.1828 + port_part = NULL; 1.1829 + is_ipv6 = 1; 1.1830 + } else if (cp && strchr(cp+1, ':')) { 1.1831 + is_ipv6 = 1; 1.1832 + addr_part = ip_as_string; 1.1833 + port_part = NULL; 1.1834 + } else if (cp) { 1.1835 + is_ipv6 = 0; 1.1836 + if (cp - ip_as_string > (int)sizeof(buf)-1) { 1.1837 + return -1; 1.1838 + } 1.1839 + memcpy(buf, ip_as_string, cp-ip_as_string); 1.1840 + buf[cp-ip_as_string] = '\0'; 1.1841 + addr_part = buf; 1.1842 + port_part = cp+1; 1.1843 + } else { 1.1844 + addr_part = ip_as_string; 1.1845 + port_part = NULL; 1.1846 + is_ipv6 = 0; 1.1847 + } 1.1848 + 1.1849 + if (port_part == NULL) { 1.1850 + port = 0; 1.1851 + } else { 1.1852 + port = atoi(port_part); 1.1853 + if (port <= 0 || port > 65535) { 1.1854 + return -1; 1.1855 + } 1.1856 + } 1.1857 + 1.1858 + if (!addr_part) 1.1859 + return -1; /* Should be impossible. */ 1.1860 +#ifdef AF_INET6 1.1861 + if (is_ipv6) 1.1862 + { 1.1863 + struct sockaddr_in6 sin6; 1.1864 + memset(&sin6, 0, sizeof(sin6)); 1.1865 +#ifdef _EVENT_HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN 1.1866 + sin6.sin6_len = sizeof(sin6); 1.1867 +#endif 1.1868 + sin6.sin6_family = AF_INET6; 1.1869 + sin6.sin6_port = htons(port); 1.1870 + if (1 != evutil_inet_pton(AF_INET6, addr_part, &sin6.sin6_addr)) 1.1871 + return -1; 1.1872 + if ((int)sizeof(sin6) > *outlen) 1.1873 + return -1; 1.1874 + memset(out, 0, *outlen); 1.1875 + memcpy(out, &sin6, sizeof(sin6)); 1.1876 + *outlen = sizeof(sin6); 1.1877 + return 0; 1.1878 + } 1.1879 + else 1.1880 +#endif 1.1881 + { 1.1882 + struct sockaddr_in sin; 1.1883 + memset(&sin, 0, sizeof(sin)); 1.1884 +#ifdef _EVENT_HAVE_STRUCT_SOCKADDR_IN_SIN_LEN 1.1885 + sin.sin_len = sizeof(sin); 1.1886 +#endif 1.1887 + sin.sin_family = AF_INET; 1.1888 + sin.sin_port = htons(port); 1.1889 + if (1 != evutil_inet_pton(AF_INET, addr_part, &sin.sin_addr)) 1.1890 + return -1; 1.1891 + if ((int)sizeof(sin) > *outlen) 1.1892 + return -1; 1.1893 + memset(out, 0, *outlen); 1.1894 + memcpy(out, &sin, sizeof(sin)); 1.1895 + *outlen = sizeof(sin); 1.1896 + return 0; 1.1897 + } 1.1898 +} 1.1899 + 1.1900 +const char * 1.1901 +evutil_format_sockaddr_port(const struct sockaddr *sa, char *out, size_t outlen) 1.1902 +{ 1.1903 + char b[128]; 1.1904 + const char *res=NULL; 1.1905 + int port; 1.1906 + if (sa->sa_family == AF_INET) { 1.1907 + const struct sockaddr_in *sin = (const struct sockaddr_in*)sa; 1.1908 + res = evutil_inet_ntop(AF_INET, &sin->sin_addr,b,sizeof(b)); 1.1909 + port = ntohs(sin->sin_port); 1.1910 + if (res) { 1.1911 + evutil_snprintf(out, outlen, "%s:%d", b, port); 1.1912 + return out; 1.1913 + } 1.1914 + } else if (sa->sa_family == AF_INET6) { 1.1915 + const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6*)sa; 1.1916 + res = evutil_inet_ntop(AF_INET6, &sin6->sin6_addr,b,sizeof(b)); 1.1917 + port = ntohs(sin6->sin6_port); 1.1918 + if (res) { 1.1919 + evutil_snprintf(out, outlen, "[%s]:%d", b, port); 1.1920 + return out; 1.1921 + } 1.1922 + } 1.1923 + 1.1924 + evutil_snprintf(out, outlen, "<addr with socktype %d>", 1.1925 + (int)sa->sa_family); 1.1926 + return out; 1.1927 +} 1.1928 + 1.1929 +int 1.1930 +evutil_sockaddr_cmp(const struct sockaddr *sa1, const struct sockaddr *sa2, 1.1931 + int include_port) 1.1932 +{ 1.1933 + int r; 1.1934 + if (0 != (r = (sa1->sa_family - sa2->sa_family))) 1.1935 + return r; 1.1936 + 1.1937 + if (sa1->sa_family == AF_INET) { 1.1938 + const struct sockaddr_in *sin1, *sin2; 1.1939 + sin1 = (const struct sockaddr_in *)sa1; 1.1940 + sin2 = (const struct sockaddr_in *)sa2; 1.1941 + if (sin1->sin_addr.s_addr < sin2->sin_addr.s_addr) 1.1942 + return -1; 1.1943 + else if (sin1->sin_addr.s_addr > sin2->sin_addr.s_addr) 1.1944 + return 1; 1.1945 + else if (include_port && 1.1946 + (r = ((int)sin1->sin_port - (int)sin2->sin_port))) 1.1947 + return r; 1.1948 + else 1.1949 + return 0; 1.1950 + } 1.1951 +#ifdef AF_INET6 1.1952 + else if (sa1->sa_family == AF_INET6) { 1.1953 + const struct sockaddr_in6 *sin1, *sin2; 1.1954 + sin1 = (const struct sockaddr_in6 *)sa1; 1.1955 + sin2 = (const struct sockaddr_in6 *)sa2; 1.1956 + if ((r = memcmp(sin1->sin6_addr.s6_addr, sin2->sin6_addr.s6_addr, 16))) 1.1957 + return r; 1.1958 + else if (include_port && 1.1959 + (r = ((int)sin1->sin6_port - (int)sin2->sin6_port))) 1.1960 + return r; 1.1961 + else 1.1962 + return 0; 1.1963 + } 1.1964 +#endif 1.1965 + return 1; 1.1966 +} 1.1967 + 1.1968 +/* Tables to implement ctypes-replacement EVUTIL_IS*() functions. Each table 1.1969 + * has 256 bits to look up whether a character is in some set or not. This 1.1970 + * fails on non-ASCII platforms, but so does every other place where we 1.1971 + * take a char and write it onto the network. 1.1972 + **/ 1.1973 +static const ev_uint32_t EVUTIL_ISALPHA_TABLE[8] = 1.1974 + { 0, 0, 0x7fffffe, 0x7fffffe, 0, 0, 0, 0 }; 1.1975 +static const ev_uint32_t EVUTIL_ISALNUM_TABLE[8] = 1.1976 + { 0, 0x3ff0000, 0x7fffffe, 0x7fffffe, 0, 0, 0, 0 }; 1.1977 +static const ev_uint32_t EVUTIL_ISSPACE_TABLE[8] = { 0x3e00, 0x1, 0, 0, 0, 0, 0, 0 }; 1.1978 +static const ev_uint32_t EVUTIL_ISXDIGIT_TABLE[8] = 1.1979 + { 0, 0x3ff0000, 0x7e, 0x7e, 0, 0, 0, 0 }; 1.1980 +static const ev_uint32_t EVUTIL_ISDIGIT_TABLE[8] = { 0, 0x3ff0000, 0, 0, 0, 0, 0, 0 }; 1.1981 +static const ev_uint32_t EVUTIL_ISPRINT_TABLE[8] = 1.1982 + { 0, 0xffffffff, 0xffffffff, 0x7fffffff, 0, 0, 0, 0x0 }; 1.1983 +static const ev_uint32_t EVUTIL_ISUPPER_TABLE[8] = { 0, 0, 0x7fffffe, 0, 0, 0, 0, 0 }; 1.1984 +static const ev_uint32_t EVUTIL_ISLOWER_TABLE[8] = { 0, 0, 0, 0x7fffffe, 0, 0, 0, 0 }; 1.1985 +/* Upper-casing and lowercasing tables to map characters to upper/lowercase 1.1986 + * equivalents. */ 1.1987 +static const unsigned char EVUTIL_TOUPPER_TABLE[256] = { 1.1988 + 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 1.1989 + 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, 1.1990 + 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, 1.1991 + 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63, 1.1992 + 64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79, 1.1993 + 80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95, 1.1994 + 96,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79, 1.1995 + 80,81,82,83,84,85,86,87,88,89,90,123,124,125,126,127, 1.1996 + 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, 1.1997 + 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, 1.1998 + 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, 1.1999 + 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, 1.2000 + 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, 1.2001 + 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, 1.2002 + 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, 1.2003 + 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255, 1.2004 +}; 1.2005 +static const unsigned char EVUTIL_TOLOWER_TABLE[256] = { 1.2006 + 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 1.2007 + 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, 1.2008 + 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, 1.2009 + 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63, 1.2010 + 64,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111, 1.2011 + 112,113,114,115,116,117,118,119,120,121,122,91,92,93,94,95, 1.2012 + 96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111, 1.2013 + 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, 1.2014 + 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, 1.2015 + 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, 1.2016 + 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, 1.2017 + 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, 1.2018 + 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, 1.2019 + 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, 1.2020 + 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, 1.2021 + 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255, 1.2022 +}; 1.2023 + 1.2024 +#define IMPL_CTYPE_FN(name) \ 1.2025 + int EVUTIL_##name(char c) { \ 1.2026 + ev_uint8_t u = c; \ 1.2027 + return !!(EVUTIL_##name##_TABLE[(u >> 5) & 7] & (1 << (u & 31))); \ 1.2028 + } 1.2029 +IMPL_CTYPE_FN(ISALPHA) 1.2030 +IMPL_CTYPE_FN(ISALNUM) 1.2031 +IMPL_CTYPE_FN(ISSPACE) 1.2032 +IMPL_CTYPE_FN(ISDIGIT) 1.2033 +IMPL_CTYPE_FN(ISXDIGIT) 1.2034 +IMPL_CTYPE_FN(ISPRINT) 1.2035 +IMPL_CTYPE_FN(ISLOWER) 1.2036 +IMPL_CTYPE_FN(ISUPPER) 1.2037 + 1.2038 +char EVUTIL_TOLOWER(char c) 1.2039 +{ 1.2040 + return ((char)EVUTIL_TOLOWER_TABLE[(ev_uint8_t)c]); 1.2041 +} 1.2042 +char EVUTIL_TOUPPER(char c) 1.2043 +{ 1.2044 + return ((char)EVUTIL_TOUPPER_TABLE[(ev_uint8_t)c]); 1.2045 +} 1.2046 +int 1.2047 +evutil_ascii_strcasecmp(const char *s1, const char *s2) 1.2048 +{ 1.2049 + char c1, c2; 1.2050 + while (1) { 1.2051 + c1 = EVUTIL_TOLOWER(*s1++); 1.2052 + c2 = EVUTIL_TOLOWER(*s2++); 1.2053 + if (c1 < c2) 1.2054 + return -1; 1.2055 + else if (c1 > c2) 1.2056 + return 1; 1.2057 + else if (c1 == 0) 1.2058 + return 0; 1.2059 + } 1.2060 +} 1.2061 +int evutil_ascii_strncasecmp(const char *s1, const char *s2, size_t n) 1.2062 +{ 1.2063 + char c1, c2; 1.2064 + while (n--) { 1.2065 + c1 = EVUTIL_TOLOWER(*s1++); 1.2066 + c2 = EVUTIL_TOLOWER(*s2++); 1.2067 + if (c1 < c2) 1.2068 + return -1; 1.2069 + else if (c1 > c2) 1.2070 + return 1; 1.2071 + else if (c1 == 0) 1.2072 + return 0; 1.2073 + } 1.2074 + return 0; 1.2075 +} 1.2076 + 1.2077 +static int 1.2078 +evutil_issetugid(void) 1.2079 +{ 1.2080 +#ifdef _EVENT_HAVE_ISSETUGID 1.2081 + return issetugid(); 1.2082 +#else 1.2083 + 1.2084 +#ifdef _EVENT_HAVE_GETEUID 1.2085 + if (getuid() != geteuid()) 1.2086 + return 1; 1.2087 +#endif 1.2088 +#ifdef _EVENT_HAVE_GETEGID 1.2089 + if (getgid() != getegid()) 1.2090 + return 1; 1.2091 +#endif 1.2092 + return 0; 1.2093 +#endif 1.2094 +} 1.2095 + 1.2096 +const char * 1.2097 +evutil_getenv(const char *varname) 1.2098 +{ 1.2099 + if (evutil_issetugid()) 1.2100 + return NULL; 1.2101 + 1.2102 + return getenv(varname); 1.2103 +} 1.2104 + 1.2105 +long 1.2106 +_evutil_weakrand(void) 1.2107 +{ 1.2108 +#ifdef WIN32 1.2109 + return rand(); 1.2110 +#else 1.2111 + return random(); 1.2112 +#endif 1.2113 +} 1.2114 + 1.2115 +int 1.2116 +evutil_sockaddr_is_loopback(const struct sockaddr *addr) 1.2117 +{ 1.2118 + static const char LOOPBACK_S6[16] = 1.2119 + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1"; 1.2120 + if (addr->sa_family == AF_INET) { 1.2121 + struct sockaddr_in *sin = (struct sockaddr_in *)addr; 1.2122 + return (ntohl(sin->sin_addr.s_addr) & 0xff000000) == 0x7f000000; 1.2123 + } else if (addr->sa_family == AF_INET6) { 1.2124 + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr; 1.2125 + return !memcmp(sin6->sin6_addr.s6_addr, LOOPBACK_S6, 16); 1.2126 + } 1.2127 + return 0; 1.2128 +} 1.2129 + 1.2130 +#define MAX_SECONDS_IN_MSEC_LONG \ 1.2131 + (((LONG_MAX) - 999) / 1000) 1.2132 + 1.2133 +long 1.2134 +evutil_tv_to_msec(const struct timeval *tv) 1.2135 +{ 1.2136 + if (tv->tv_usec > 1000000 || tv->tv_sec > MAX_SECONDS_IN_MSEC_LONG) 1.2137 + return -1; 1.2138 + 1.2139 + return (tv->tv_sec * 1000) + ((tv->tv_usec + 999) / 1000); 1.2140 +} 1.2141 + 1.2142 +int 1.2143 +evutil_hex_char_to_int(char c) 1.2144 +{ 1.2145 + switch(c) 1.2146 + { 1.2147 + case '0': return 0; 1.2148 + case '1': return 1; 1.2149 + case '2': return 2; 1.2150 + case '3': return 3; 1.2151 + case '4': return 4; 1.2152 + case '5': return 5; 1.2153 + case '6': return 6; 1.2154 + case '7': return 7; 1.2155 + case '8': return 8; 1.2156 + case '9': return 9; 1.2157 + case 'A': case 'a': return 10; 1.2158 + case 'B': case 'b': return 11; 1.2159 + case 'C': case 'c': return 12; 1.2160 + case 'D': case 'd': return 13; 1.2161 + case 'E': case 'e': return 14; 1.2162 + case 'F': case 'f': return 15; 1.2163 + } 1.2164 + return -1; 1.2165 +} 1.2166 + 1.2167 +#ifdef WIN32 1.2168 +HANDLE 1.2169 +evutil_load_windows_system_library(const TCHAR *library_name) 1.2170 +{ 1.2171 + TCHAR path[MAX_PATH]; 1.2172 + unsigned n; 1.2173 + n = GetSystemDirectory(path, MAX_PATH); 1.2174 + if (n == 0 || n + _tcslen(library_name) + 2 >= MAX_PATH) 1.2175 + return 0; 1.2176 + _tcscat(path, TEXT("\\")); 1.2177 + _tcscat(path, library_name); 1.2178 + return LoadLibrary(path); 1.2179 +} 1.2180 +#endif 1.2181 +