1e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/* 2e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson 3e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * 4e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * Redistribution and use in source and binary forms, with or without 5e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * modification, are permitted provided that the following conditions 6e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * are met: 7e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * 1. Redistributions of source code must retain the above copyright 8e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * notice, this list of conditions and the following disclaimer. 9e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * 2. Redistributions in binary form must reproduce the above copyright 10e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * notice, this list of conditions and the following disclaimer in the 11e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * documentation and/or other materials provided with the distribution. 12e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * 3. The name of the author may not be used to endorse or promote products 13e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * derived from this software without specific prior written permission. 14e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * 15e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley */ 26e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 27e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include "event2/event-config.h" 28fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#include "evconfig-private.h" 29e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 30fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifdef _WIN32 31e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <winsock2.h> 32e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <ws2tcpip.h> 33e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#define WIN32_LEAN_AND_MEAN 34e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <windows.h> 35e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#undef WIN32_LEAN_AND_MEAN 36e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <io.h> 37e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <tchar.h> 38fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#include <process.h> 39fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#undef _WIN32_WINNT 40fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath/* For structs needed by GetAdaptersAddresses */ 41fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#define _WIN32_WINNT 0x0501 42fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#include <iphlpapi.h> 43e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 44e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 45e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <sys/types.h> 46fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifdef EVENT__HAVE_SYS_SOCKET_H 47e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <sys/socket.h> 48e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 49fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifdef EVENT__HAVE_UNISTD_H 50e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <unistd.h> 51e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 52fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifdef EVENT__HAVE_FCNTL_H 53e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <fcntl.h> 54e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 55fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifdef EVENT__HAVE_STDLIB_H 56e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <stdlib.h> 57e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 58e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <errno.h> 59e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <limits.h> 60e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <stdio.h> 61e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <string.h> 62fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifdef EVENT__HAVE_NETINET_IN_H 63e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <netinet/in.h> 64e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 65fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifdef EVENT__HAVE_NETINET_IN6_H 66e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <netinet/in6.h> 67e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 68fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifdef EVENT__HAVE_NETINET_TCP_H 69fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#include <netinet/tcp.h> 70fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#endif 71fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifdef EVENT__HAVE_ARPA_INET_H 72e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <arpa/inet.h> 73e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 74e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <time.h> 7583a0c9c65a60a92d3ea5542596b3ba56db492c37Josh Gao#include <sys/stat.h> 76fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifdef EVENT__HAVE_IFADDRS_H 77fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#include <ifaddrs.h> 78fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#endif 79e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 80e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include "event2/util.h" 81e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include "util-internal.h" 82e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include "log-internal.h" 83e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include "mm-internal.h" 84fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#include "evthread-internal.h" 85e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 86e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include "strlcpy-internal.h" 87e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include "ipv6-internal.h" 88e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 89fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifdef _WIN32 90fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#define HT_NO_CACHE_HASH_VALUES 91fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#include "ht-internal.h" 92e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#define open _open 93e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#define read _read 94e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#define close _close 95fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifndef fstat 96e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#define fstat _fstati64 97fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#endif 98fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifndef stat 99e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#define stat _stati64 100fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#endif 101e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#define mode_t int 102e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 103e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 104e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyint 105fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathevutil_open_closeonexec_(const char *pathname, int flags, unsigned mode) 106e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 107e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int fd; 108e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 109e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef O_CLOEXEC 110fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath fd = open(pathname, flags|O_CLOEXEC, (mode_t)mode); 111fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (fd >= 0 || errno == EINVAL) 112fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return fd; 113fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath /* If we got an EINVAL, fall through and try without O_CLOEXEC */ 114e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 115fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath fd = open(pathname, flags, (mode_t)mode); 116e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (fd < 0) 117e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 118e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 119fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#if defined(FD_CLOEXEC) 120fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) { 121fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath close(fd); 122e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 123fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 124e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 125e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 126e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return fd; 127e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 128e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 129e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/** 130e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley Read the contents of 'filename' into a newly allocated NUL-terminated 131e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley string. Set *content_out to hold this string, and *len_out to hold its 132e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley length (not including the appended NUL). If 'is_binary', open the file in 133e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley binary mode. 134e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 135e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley Returns 0 on success, -1 if the open fails, and -2 for all other failures. 136e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 137e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley Used internally only; may go away in a future version. 138e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley */ 139e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyint 140fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathevutil_read_file_(const char *filename, char **content_out, size_t *len_out, 141e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int is_binary) 142e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 143e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int fd, r; 144e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct stat st; 145e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley char *mem; 146e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley size_t read_so_far=0; 147e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int mode = O_RDONLY; 148e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 149e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EVUTIL_ASSERT(content_out); 150e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EVUTIL_ASSERT(len_out); 151e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley *content_out = NULL; 152e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley *len_out = 0; 153e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 154e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef O_BINARY 155e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (is_binary) 156e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley mode |= O_BINARY; 157e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 158e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 159fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath fd = evutil_open_closeonexec_(filename, mode, 0); 160e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (fd < 0) 161e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 162e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (fstat(fd, &st) || st.st_size < 0 || 163e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley st.st_size > EV_SSIZE_MAX-1 ) { 164e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley close(fd); 165e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -2; 166e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 167e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley mem = mm_malloc((size_t)st.st_size + 1); 168e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (!mem) { 169e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley close(fd); 170e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -2; 171e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 172e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley read_so_far = 0; 173fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifdef _WIN32 174e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#define N_TO_READ(x) ((x) > INT_MAX) ? INT_MAX : ((int)(x)) 175e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#else 176e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#define N_TO_READ(x) (x) 177e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 178e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley while ((r = read(fd, mem+read_so_far, N_TO_READ(st.st_size - read_so_far))) > 0) { 179e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley read_so_far += r; 180e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (read_so_far >= (size_t)st.st_size) 181e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley break; 182e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EVUTIL_ASSERT(read_so_far < (size_t)st.st_size); 183e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 184e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley close(fd); 185e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (r < 0) { 186e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley mm_free(mem); 187e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -2; 188e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 189e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley mem[read_so_far] = 0; 190e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 191e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley *len_out = read_so_far; 192e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley *content_out = mem; 193e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 194e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 195e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 196e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyint 197e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevutil_socketpair(int family, int type, int protocol, evutil_socket_t fd[2]) 198e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 199fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifndef _WIN32 200e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return socketpair(family, type, protocol, fd); 201e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#else 202fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return evutil_ersatz_socketpair_(family, type, protocol, fd); 203e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 204e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 205e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 206e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyint 207fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathevutil_ersatz_socketpair_(int family, int type, int protocol, 208e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evutil_socket_t fd[2]) 209e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 210e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* This code is originally from Tor. Used with permission. */ 211e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 212e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* This socketpair does not work when localhost is down. So 213e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * it's really not the same thing at all. But it's close enough 214e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * for now, and really, when localhost is down sometimes, we 215e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * have other problems too. 216e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley */ 217fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifdef _WIN32 218e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#define ERR(e) WSA##e 219e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#else 220e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#define ERR(e) e 221e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 222e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evutil_socket_t listener = -1; 223e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evutil_socket_t connector = -1; 224e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evutil_socket_t acceptor = -1; 225e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct sockaddr_in listen_addr; 226e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct sockaddr_in connect_addr; 227e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley ev_socklen_t size; 228e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int saved_errno = -1; 229fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath int family_test; 230fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 231fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath family_test = family != AF_INET; 232e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef AF_UNIX 233fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath family_test = family_test && (family != AF_UNIX); 234e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 235fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (protocol || family_test) { 236e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EVUTIL_SET_SOCKET_ERROR(ERR(EAFNOSUPPORT)); 237e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 238e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 239fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 240e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (!fd) { 241e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EVUTIL_SET_SOCKET_ERROR(ERR(EINVAL)); 242e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 243e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 244e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 245e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley listener = socket(AF_INET, type, 0); 246e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (listener < 0) 247e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 248e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley memset(&listen_addr, 0, sizeof(listen_addr)); 249e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley listen_addr.sin_family = AF_INET; 250e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley listen_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 251e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley listen_addr.sin_port = 0; /* kernel chooses port. */ 252e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (bind(listener, (struct sockaddr *) &listen_addr, sizeof (listen_addr)) 253e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley == -1) 254e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto tidy_up_and_fail; 255e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (listen(listener, 1) == -1) 256e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto tidy_up_and_fail; 257e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 258e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley connector = socket(AF_INET, type, 0); 259e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (connector < 0) 260e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto tidy_up_and_fail; 261fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 262fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath memset(&connect_addr, 0, sizeof(connect_addr)); 263fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 264e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* We want to find out the port number to connect to. */ 265e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley size = sizeof(connect_addr); 266e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (getsockname(listener, (struct sockaddr *) &connect_addr, &size) == -1) 267e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto tidy_up_and_fail; 268e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (size != sizeof (connect_addr)) 269e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto abort_tidy_up_and_fail; 270e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (connect(connector, (struct sockaddr *) &connect_addr, 271e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sizeof(connect_addr)) == -1) 272e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto tidy_up_and_fail; 273e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 274e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley size = sizeof(listen_addr); 275e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley acceptor = accept(listener, (struct sockaddr *) &listen_addr, &size); 276e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (acceptor < 0) 277e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto tidy_up_and_fail; 278e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (size != sizeof(listen_addr)) 279e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto abort_tidy_up_and_fail; 280e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* Now check we are talking to ourself by matching port and host on the 281e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley two sockets. */ 282e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (getsockname(connector, (struct sockaddr *) &connect_addr, &size) == -1) 283e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto tidy_up_and_fail; 284e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (size != sizeof (connect_addr) 285e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley || listen_addr.sin_family != connect_addr.sin_family 286e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley || listen_addr.sin_addr.s_addr != connect_addr.sin_addr.s_addr 287e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley || listen_addr.sin_port != connect_addr.sin_port) 288e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto abort_tidy_up_and_fail; 289e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evutil_closesocket(listener); 290e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley fd[0] = connector; 291e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley fd[1] = acceptor; 292e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 293e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 294e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 295e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley abort_tidy_up_and_fail: 296e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley saved_errno = ERR(ECONNABORTED); 297e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley tidy_up_and_fail: 298e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (saved_errno < 0) 299e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley saved_errno = EVUTIL_SOCKET_ERROR(); 300e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (listener != -1) 301e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evutil_closesocket(listener); 302e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (connector != -1) 303e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evutil_closesocket(connector); 304e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (acceptor != -1) 305e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evutil_closesocket(acceptor); 306e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 307e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EVUTIL_SET_SOCKET_ERROR(saved_errno); 308e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 309e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#undef ERR 310e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 311e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 312e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyint 313e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevutil_make_socket_nonblocking(evutil_socket_t fd) 314e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 315fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifdef _WIN32 316e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley { 317fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath unsigned long nonblocking = 1; 318e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (ioctlsocket(fd, FIONBIO, &nonblocking) == SOCKET_ERROR) { 319e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley event_sock_warn(fd, "fcntl(%d, F_GETFL)", (int)fd); 320e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 321e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 322e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 323e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#else 324e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley { 325e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int flags; 326e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if ((flags = fcntl(fd, F_GETFL, NULL)) < 0) { 327e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley event_warn("fcntl(%d, F_GETFL)", fd); 328e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 329e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 330fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (!(flags & O_NONBLOCK)) { 331fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) { 332fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath event_warn("fcntl(%d, F_SETFL)", fd); 333fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return -1; 334fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 335e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 336e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 337e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 338e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 339e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 340e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 341fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath/* Faster version of evutil_make_socket_nonblocking for internal use. 342fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * 343fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * Requires that no F_SETFL flags were previously set on the fd. 344fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath */ 345fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathstatic int 346fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathevutil_fast_socket_nonblocking(evutil_socket_t fd) 347fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath{ 348fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifdef _WIN32 349fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return evutil_make_socket_nonblocking(fd); 350fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#else 351fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) { 352fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath event_warn("fcntl(%d, F_SETFL)", fd); 353fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return -1; 354fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 355fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return 0; 356fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#endif 357fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath} 358fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 359e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyint 360e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevutil_make_listen_socket_reuseable(evutil_socket_t sock) 361e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 362fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#if defined(SO_REUSEADDR) && !defined(_WIN32) 363e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int one = 1; 364e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* REUSEADDR on Unix means, "don't hang on to this address after the 365e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * listener is closed." On Windows, though, it means "don't keep other 366e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * processes from binding to this address while we're using it. */ 367e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*) &one, 368e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley (ev_socklen_t)sizeof(one)); 369e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#else 370e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 371e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 372e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 373e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 374e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyint 375fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathevutil_make_listen_socket_reuseable_port(evutil_socket_t sock) 376fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath{ 377fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#if defined __linux__ && defined(SO_REUSEPORT) 378fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath int one = 1; 379fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath /* REUSEPORT on Linux 3.9+ means, "Multiple servers (processes or 380fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * threads) can bind to the same port if they each set the option. */ 381fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (void*) &one, 382fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath (ev_socklen_t)sizeof(one)); 383fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#else 384fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return 0; 385fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#endif 386fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath} 387fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 388fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathint 389fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathevutil_make_tcp_listen_socket_deferred(evutil_socket_t sock) 390fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath{ 391fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#if defined(EVENT__HAVE_NETINET_TCP_H) && defined(TCP_DEFER_ACCEPT) 392fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath int one = 1; 393fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 394fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath /* TCP_DEFER_ACCEPT tells the kernel to call defer accept() only after data 395fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * has arrived and ready to read */ 396fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return setsockopt(sock, IPPROTO_TCP, TCP_DEFER_ACCEPT, &one, 397fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath (ev_socklen_t)sizeof(one)); 398fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#endif 399fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return 0; 400fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath} 401fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 402fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathint 403e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevutil_make_socket_closeonexec(evutil_socket_t fd) 404e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 405fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#if !defined(_WIN32) && defined(EVENT__HAVE_SETFD) 406e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int flags; 407e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if ((flags = fcntl(fd, F_GETFD, NULL)) < 0) { 408e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley event_warn("fcntl(%d, F_GETFD)", fd); 409e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 410e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 411fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (!(flags & FD_CLOEXEC)) { 412fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) { 413fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath event_warn("fcntl(%d, F_SETFD)", fd); 414fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return -1; 415fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 416fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 417fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#endif 418fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return 0; 419fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath} 420fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 421fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath/* Faster version of evutil_make_socket_closeonexec for internal use. 422fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * 423fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * Requires that no F_SETFD flags were previously set on the fd. 424fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath */ 425fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathstatic int 426fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathevutil_fast_socket_closeonexec(evutil_socket_t fd) 427fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath{ 428fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#if !defined(_WIN32) && defined(EVENT__HAVE_SETFD) 429fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) { 430e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley event_warn("fcntl(%d, F_SETFD)", fd); 431e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 432e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 433e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 434e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 435e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 436e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 437e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyint 438e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevutil_closesocket(evutil_socket_t sock) 439e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 440fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifndef _WIN32 441e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return close(sock); 442e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#else 443e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return closesocket(sock); 444e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 445e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 446e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 447e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyev_int64_t 448e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevutil_strtoll(const char *s, char **endptr, int base) 449e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 450fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifdef EVENT__HAVE_STRTOLL 451e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return (ev_int64_t)strtoll(s, endptr, base); 452fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#elif EVENT__SIZEOF_LONG == 8 453e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return (ev_int64_t)strtol(s, endptr, base); 454fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#elif defined(_WIN32) && defined(_MSC_VER) && _MSC_VER < 1300 455e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* XXXX on old versions of MS APIs, we only support base 456e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * 10. */ 457e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley ev_int64_t r; 458e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (base != 10) 459e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 460e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley r = (ev_int64_t) _atoi64(s); 461e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley while (isspace(*s)) 462e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley ++s; 463e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (*s == '-') 464e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley ++s; 465e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley while (isdigit(*s)) 466e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley ++s; 467e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (endptr) 468e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley *endptr = (char*) s; 469e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return r; 470fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#elif defined(_WIN32) 471e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return (ev_int64_t) _strtoi64(s, endptr, base); 472fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#elif defined(EVENT__SIZEOF_LONG_LONG) && EVENT__SIZEOF_LONG_LONG == 8 473e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley long long r; 474e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int n; 475e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (base != 10 && base != 16) 476e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 477e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (base == 10) { 478e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley n = sscanf(s, "%lld", &r); 479e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } else { 480e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley unsigned long long ru=0; 481e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley n = sscanf(s, "%llx", &ru); 482e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (ru > EV_INT64_MAX) 483e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 484e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley r = (long long) ru; 485e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 486e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (n != 1) 487e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 488fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath while (EVUTIL_ISSPACE_(*s)) 489e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley ++s; 490e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (*s == '-') 491e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley ++s; 492e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (base == 10) { 493fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath while (EVUTIL_ISDIGIT_(*s)) 494e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley ++s; 495e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } else { 496fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath while (EVUTIL_ISXDIGIT_(*s)) 497e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley ++s; 498e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 499e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (endptr) 500e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley *endptr = (char*) s; 501e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return r; 502e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#else 503e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#error "I don't know how to parse 64-bit integers." 504e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 505e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 506e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 507fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifdef _WIN32 508e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyint 509e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevutil_socket_geterror(evutil_socket_t sock) 510e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 511e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int optval, optvallen=sizeof(optval); 512e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int err = WSAGetLastError(); 513e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (err == WSAEWOULDBLOCK && sock >= 0) { 514e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)&optval, 515e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley &optvallen)) 516e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return err; 517e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (optval) 518e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return optval; 519e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 520e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return err; 521e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 522e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 523e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 524e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/* XXX we should use an enum here. */ 525e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/* 2 for connection refused, 1 for connected, 0 for not yet, -1 for error. */ 526e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyint 527fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathevutil_socket_connect_(evutil_socket_t *fd_ptr, const struct sockaddr *sa, int socklen) 528e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 529e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int made_fd = 0; 530e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 531e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (*fd_ptr < 0) { 532e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if ((*fd_ptr = socket(sa->sa_family, SOCK_STREAM, 0)) < 0) 533e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto err; 534e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley made_fd = 1; 535e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (evutil_make_socket_nonblocking(*fd_ptr) < 0) { 536e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto err; 537e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 538e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 539e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 540e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (connect(*fd_ptr, sa, socklen) < 0) { 541e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int e = evutil_socket_geterror(*fd_ptr); 542e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (EVUTIL_ERR_CONNECT_RETRIABLE(e)) 543e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 544e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (EVUTIL_ERR_CONNECT_REFUSED(e)) 545e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 2; 546e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley goto err; 547e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } else { 548e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 1; 549e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 550e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 551e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyerr: 552e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (made_fd) { 553e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evutil_closesocket(*fd_ptr); 554e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley *fd_ptr = -1; 555e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 556e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 557e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 558e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 559e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/* Check whether a socket on which we called connect() is done 560e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley connecting. Return 1 for connected, 0 for not yet, -1 for error. In the 561e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley error case, set the current socket errno to the error that happened during 562e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley the connect operation. */ 563e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyint 564fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathevutil_socket_finished_connecting_(evutil_socket_t fd) 565e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 566e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int e; 567e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley ev_socklen_t elen = sizeof(e); 568e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 569e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&e, &elen) < 0) 570e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 571e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 572e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (e) { 573e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (EVUTIL_ERR_CONNECT_RETRIABLE(e)) 574e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 575e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EVUTIL_SET_SOCKET_ERROR(e); 576e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 577e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 578e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 579e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 1; 580e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 581e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 582e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#if (EVUTIL_AI_PASSIVE|EVUTIL_AI_CANONNAME|EVUTIL_AI_NUMERICHOST| \ 583e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EVUTIL_AI_NUMERICSERV|EVUTIL_AI_V4MAPPED|EVUTIL_AI_ALL| \ 584e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EVUTIL_AI_ADDRCONFIG) != \ 585e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley (EVUTIL_AI_PASSIVE^EVUTIL_AI_CANONNAME^EVUTIL_AI_NUMERICHOST^ \ 586e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EVUTIL_AI_NUMERICSERV^EVUTIL_AI_V4MAPPED^EVUTIL_AI_ALL^ \ 587e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EVUTIL_AI_ADDRCONFIG) 588e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#error "Some of our EVUTIL_AI_* flags seem to overlap with system AI_* flags" 589e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 590e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 591e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/* We sometimes need to know whether we have an ipv4 address and whether we 592e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley have an ipv6 address. If 'have_checked_interfaces', then we've already done 593e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley the test. If 'had_ipv4_address', then it turns out we had an ipv4 address. 594e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley If 'had_ipv6_address', then it turns out we had an ipv6 address. These are 595e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley set by evutil_check_interfaces. */ 596e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic int have_checked_interfaces, had_ipv4_address, had_ipv6_address; 597e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 598e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/* Macro: True iff the IPv4 address 'addr', in host order, is in 127.0.0.0/8 599e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley */ 600e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#define EVUTIL_V4ADDR_IS_LOCALHOST(addr) (((addr)>>24) == 127) 601e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 602e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/* Macro: True iff the IPv4 address 'addr', in host order, is a class D 603e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * (multiclass) address. 604e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley */ 605e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#define EVUTIL_V4ADDR_IS_CLASSD(addr) ((((addr)>>24) & 0xf0) == 0xe0) 606e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 607fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathstatic void 608fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathevutil_found_ifaddr(const struct sockaddr *sa) 609fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath{ 610fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath const char ZEROES[] = "\x00\x00\x00\x00\x00\x00\x00\x00" 611fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath "\x00\x00\x00\x00\x00\x00\x00\x00"; 612fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 613fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (sa->sa_family == AF_INET) { 614fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath const struct sockaddr_in *sin = (struct sockaddr_in *)sa; 615fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath ev_uint32_t addr = ntohl(sin->sin_addr.s_addr); 616fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (addr == 0 || 617fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath EVUTIL_V4ADDR_IS_LOCALHOST(addr) || 618fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath EVUTIL_V4ADDR_IS_CLASSD(addr)) { 619fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath /* Not actually a usable external address. */ 620fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } else { 621fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath event_debug(("Detected an IPv4 interface")); 622fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath had_ipv4_address = 1; 623fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 624fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } else if (sa->sa_family == AF_INET6) { 625fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; 626fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath const unsigned char *addr = 627fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath (unsigned char*)sin6->sin6_addr.s6_addr; 628fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (!memcmp(addr, ZEROES, 8) || 629fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath ((addr[0] & 0xfe) == 0xfc) || 630fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath (addr[0] == 0xfe && (addr[1] & 0xc0) == 0x80) || 631fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath (addr[0] == 0xfe && (addr[1] & 0xc0) == 0xc0) || 632fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath (addr[0] == 0xff)) { 633fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath /* This is a reserved, ipv4compat, ipv4map, loopback, 634fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * link-local, multicast, or unspecified address. */ 635fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } else { 636fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath event_debug(("Detected an IPv6 interface")); 637fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath had_ipv6_address = 1; 638fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 639fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 640fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath} 641fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 642fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifdef _WIN32 643fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathtypedef ULONG (WINAPI *GetAdaptersAddresses_fn_t)( 644fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath ULONG, ULONG, PVOID, PIP_ADAPTER_ADDRESSES, PULONG); 645fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#endif 646fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 647fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathstatic int 648fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathevutil_check_ifaddrs(void) 649fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath{ 650fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#if defined(EVENT__HAVE_GETIFADDRS) 651fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath /* Most free Unixy systems provide getifaddrs, which gives us a linked list 652fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * of struct ifaddrs. */ 653fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath struct ifaddrs *ifa = NULL; 654fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath const struct ifaddrs *i; 655fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (getifaddrs(&ifa) < 0) { 656fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath event_warn("Unable to call getifaddrs()"); 657fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return -1; 658fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 659fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 660fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath for (i = ifa; i; i = i->ifa_next) { 661fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (!i->ifa_addr) 662fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath continue; 663fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath evutil_found_ifaddr(i->ifa_addr); 664fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 665fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 666fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath freeifaddrs(ifa); 667fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return 0; 668fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#elif defined(_WIN32) 669fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath /* Windows XP began to provide GetAdaptersAddresses. Windows 2000 had a 670fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath "GetAdaptersInfo", but that's deprecated; let's just try 671fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath GetAdaptersAddresses and fall back to connect+getsockname. 672fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath */ 673fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath HMODULE lib = evutil_load_windows_system_library_(TEXT("ihplapi.dll")); 674fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath GetAdaptersAddresses_fn_t fn; 675fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath ULONG size, res; 676fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath IP_ADAPTER_ADDRESSES *addresses = NULL, *address; 677fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath int result = -1; 678fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 679fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#define FLAGS (GAA_FLAG_SKIP_ANYCAST | \ 680fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath GAA_FLAG_SKIP_MULTICAST | \ 681fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath GAA_FLAG_SKIP_DNS_SERVER) 682fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 683fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (!lib) 684fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath goto done; 685fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 686fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (!(fn = (GetAdaptersAddresses_fn_t) GetProcAddress(lib, "GetAdaptersAddresses"))) 687fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath goto done; 688fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 689fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath /* Guess how much space we need. */ 690fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath size = 15*1024; 691fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath addresses = mm_malloc(size); 692fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (!addresses) 693fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath goto done; 694fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath res = fn(AF_UNSPEC, FLAGS, NULL, addresses, &size); 695fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (res == ERROR_BUFFER_OVERFLOW) { 696fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath /* we didn't guess that we needed enough space; try again */ 697fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath mm_free(addresses); 698fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath addresses = mm_malloc(size); 699fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (!addresses) 700fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath goto done; 701fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath res = fn(AF_UNSPEC, FLAGS, NULL, addresses, &size); 702fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 703fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (res != NO_ERROR) 704fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath goto done; 705fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 706fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath for (address = addresses; address; address = address->Next) { 707fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath IP_ADAPTER_UNICAST_ADDRESS *a; 708fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath for (a = address->FirstUnicastAddress; a; a = a->Next) { 709fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath /* Yes, it's a linked list inside a linked list */ 710fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath struct sockaddr *sa = a->Address.lpSockaddr; 711fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath evutil_found_ifaddr(sa); 712fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 713fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 714fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 715fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath result = 0; 716fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathdone: 717fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (lib) 718fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath FreeLibrary(lib); 719fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (addresses) 720fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath mm_free(addresses); 721fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return result; 722fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#else 723fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return -1; 724fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#endif 725fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath} 726fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 727e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/* Test whether we have an ipv4 interface and an ipv6 interface. Return 0 if 728e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * the test seemed successful. */ 729e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic int 730e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevutil_check_interfaces(int force_recheck) 731e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 732e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evutil_socket_t fd = -1; 733e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct sockaddr_in sin, sin_out; 734e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct sockaddr_in6 sin6, sin6_out; 735e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley ev_socklen_t sin_out_len = sizeof(sin_out); 736e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley ev_socklen_t sin6_out_len = sizeof(sin6_out); 737e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int r; 738e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (have_checked_interfaces && !force_recheck) 739e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 740e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 741fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (evutil_check_ifaddrs() == 0) { 742fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath /* Use a nice sane interface, if this system has one. */ 743fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return 0; 744fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 745fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 746fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath /* Ugh. There was no nice sane interface. So to check whether we have 747fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * an interface open for a given protocol, will try to make a UDP 748fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * 'connection' to a remote host on the internet. We don't actually 749fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * use it, so the address doesn't matter, but we want to pick one that 750fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * keep us from using a host- or link-local interface. */ 751e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley memset(&sin, 0, sizeof(sin)); 752e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sin.sin_family = AF_INET; 753e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sin.sin_port = htons(53); 754e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley r = evutil_inet_pton(AF_INET, "18.244.0.188", &sin.sin_addr); 755e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EVUTIL_ASSERT(r); 756e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 757e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley memset(&sin6, 0, sizeof(sin6)); 758e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sin6.sin6_family = AF_INET6; 759e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sin6.sin6_port = htons(53); 760e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley r = evutil_inet_pton(AF_INET6, "2001:4860:b002::68", &sin6.sin6_addr); 761e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EVUTIL_ASSERT(r); 762e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 763e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley memset(&sin_out, 0, sizeof(sin_out)); 764e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley memset(&sin6_out, 0, sizeof(sin6_out)); 765e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 766e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* XXX some errnos mean 'no address'; some mean 'not enough sockets'. */ 767e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) >= 0 && 768e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley connect(fd, (struct sockaddr*)&sin, sizeof(sin)) == 0 && 769e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley getsockname(fd, (struct sockaddr*)&sin_out, &sin_out_len) == 0) { 770e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* We might have an IPv4 interface. */ 771fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath evutil_found_ifaddr((struct sockaddr*) &sin_out); 772e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 773e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (fd >= 0) 774e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evutil_closesocket(fd); 775e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 776e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if ((fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) >= 0 && 777e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley connect(fd, (struct sockaddr*)&sin6, sizeof(sin6)) == 0 && 778e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley getsockname(fd, (struct sockaddr*)&sin6_out, &sin6_out_len) == 0) { 779e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* We might have an IPv6 interface. */ 780fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath evutil_found_ifaddr((struct sockaddr*) &sin6_out); 781e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 782e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 783e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (fd >= 0) 784e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evutil_closesocket(fd); 785e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 786e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 787e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 788e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 789e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/* Internal addrinfo flag. This one is set when we allocate the addrinfo from 790e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * inside libevent. Otherwise, the built-in getaddrinfo() function allocated 791e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * it, and we should trust what they said. 792e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley **/ 793e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#define EVUTIL_AI_LIBEVENT_ALLOCATED 0x80000000 794e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 795e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/* Helper: construct a new addrinfo containing the socket address in 796e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * 'sa', which must be a sockaddr_in or a sockaddr_in6. Take the 797e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * socktype and protocol info from hints. If they weren't set, then 798e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * allocate both a TCP and a UDP addrinfo. 799e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley */ 800e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystruct evutil_addrinfo * 801fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathevutil_new_addrinfo_(struct sockaddr *sa, ev_socklen_t socklen, 802e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley const struct evutil_addrinfo *hints) 803e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 804e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct evutil_addrinfo *res; 805e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EVUTIL_ASSERT(hints); 806e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 807e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (hints->ai_socktype == 0 && hints->ai_protocol == 0) { 808e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* Indecisive user! Give them a UDP and a TCP. */ 809e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct evutil_addrinfo *r1, *r2; 810e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct evutil_addrinfo tmp; 811e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley memcpy(&tmp, hints, sizeof(tmp)); 812e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley tmp.ai_socktype = SOCK_STREAM; tmp.ai_protocol = IPPROTO_TCP; 813fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath r1 = evutil_new_addrinfo_(sa, socklen, &tmp); 814e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (!r1) 815e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return NULL; 816e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley tmp.ai_socktype = SOCK_DGRAM; tmp.ai_protocol = IPPROTO_UDP; 817fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath r2 = evutil_new_addrinfo_(sa, socklen, &tmp); 818e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (!r2) { 819e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evutil_freeaddrinfo(r1); 820e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return NULL; 821e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 822e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley r1->ai_next = r2; 823e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return r1; 824e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 825e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 826e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* We're going to allocate extra space to hold the sockaddr. */ 827e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley res = mm_calloc(1,sizeof(struct evutil_addrinfo)+socklen); 828e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (!res) 829e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return NULL; 830e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley res->ai_addr = (struct sockaddr*) 831e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley (((char*)res) + sizeof(struct evutil_addrinfo)); 832e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley memcpy(res->ai_addr, sa, socklen); 833e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley res->ai_addrlen = socklen; 834e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley res->ai_family = sa->sa_family; /* Same or not? XXX */ 835e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley res->ai_flags = EVUTIL_AI_LIBEVENT_ALLOCATED; 836e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley res->ai_socktype = hints->ai_socktype; 837e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley res->ai_protocol = hints->ai_protocol; 838e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 839e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return res; 840e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 841e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 842e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/* Append the addrinfo 'append' to the end of 'first', and return the start of 843e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * the list. Either element can be NULL, in which case we return the element 844e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * that is not NULL. */ 845e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystruct evutil_addrinfo * 846fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathevutil_addrinfo_append_(struct evutil_addrinfo *first, 847e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct evutil_addrinfo *append) 848e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 849e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct evutil_addrinfo *ai = first; 850e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (!ai) 851e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return append; 852e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley while (ai->ai_next) 853e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley ai = ai->ai_next; 854e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley ai->ai_next = append; 855e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 856e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return first; 857e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 858e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 859e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic int 860e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyparse_numeric_servname(const char *servname) 861e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 862e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int n; 863e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley char *endptr=NULL; 864e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley n = (int) strtol(servname, &endptr, 10); 865e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (n>=0 && n <= 65535 && servname[0] && endptr && !endptr[0]) 866e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return n; 867e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley else 868e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 869e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 870e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 871e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/** Parse a service name in 'servname', which can be a decimal port. 872e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * Return the port number, or -1 on error. 873e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley */ 874e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic int 875e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevutil_parse_servname(const char *servname, const char *protocol, 876e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley const struct evutil_addrinfo *hints) 877e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 878e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int n = parse_numeric_servname(servname); 879e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (n>=0) 880e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return n; 881fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#if defined(EVENT__HAVE_GETSERVBYNAME) || defined(_WIN32) 882e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (!(hints->ai_flags & EVUTIL_AI_NUMERICSERV)) { 883e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct servent *ent = getservbyname(servname, protocol); 884e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (ent) { 885e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return ntohs(ent->s_port); 886e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 887e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 888e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 889e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 890e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 891e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 892e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/* Return a string corresponding to a protocol number that we can pass to 893e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * getservyname. */ 894e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic const char * 895e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevutil_unparse_protoname(int proto) 896e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 897e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley switch (proto) { 898e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case 0: 899e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return NULL; 900e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case IPPROTO_TCP: 901e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return "tcp"; 902e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case IPPROTO_UDP: 903e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return "udp"; 904e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef IPPROTO_SCTP 905e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case IPPROTO_SCTP: 906e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return "sctp"; 907e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 908e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley default: 909fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifdef EVENT__HAVE_GETPROTOBYNUMBER 910e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley { 911e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct protoent *ent = getprotobynumber(proto); 912e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (ent) 913e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return ent->p_name; 914e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 915e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 916e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return NULL; 917e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 918e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 919e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 920e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic void 921e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevutil_getaddrinfo_infer_protocols(struct evutil_addrinfo *hints) 922e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 923e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* If we can guess the protocol from the socktype, do so. */ 924e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (!hints->ai_protocol && hints->ai_socktype) { 925e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (hints->ai_socktype == SOCK_DGRAM) 926e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley hints->ai_protocol = IPPROTO_UDP; 927e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley else if (hints->ai_socktype == SOCK_STREAM) 928e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley hints->ai_protocol = IPPROTO_TCP; 929e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 930e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 931e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* Set the socktype if it isn't set. */ 932e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (!hints->ai_socktype && hints->ai_protocol) { 933e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (hints->ai_protocol == IPPROTO_UDP) 934e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley hints->ai_socktype = SOCK_DGRAM; 935e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley else if (hints->ai_protocol == IPPROTO_TCP) 936e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley hints->ai_socktype = SOCK_STREAM; 937e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef IPPROTO_SCTP 938e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley else if (hints->ai_protocol == IPPROTO_SCTP) 939e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley hints->ai_socktype = SOCK_STREAM; 940e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 941e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 942e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 943e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 944e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#if AF_UNSPEC != PF_UNSPEC 945e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#error "I cannot build on a system where AF_UNSPEC != PF_UNSPEC" 946e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 947e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 948e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/** Implements the part of looking up hosts by name that's common to both 949e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * the blocking and nonblocking resolver: 950e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * - Adjust 'hints' to have a reasonable socktype and protocol. 951e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * - Look up the port based on 'servname', and store it in *portnum, 952e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * - Handle the nodename==NULL case 953e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * - Handle some invalid arguments cases. 954e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * - Handle the cases where nodename is an IPv4 or IPv6 address. 955e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * 956e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * If we need the resolver to look up the hostname, we return 957e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * EVUTIL_EAI_NEED_RESOLVE. Otherwise, we can completely implement 958e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * getaddrinfo: we return 0 or an appropriate EVUTIL_EAI_* error, and 959e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * set *res as getaddrinfo would. 960e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley */ 961e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyint 962fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathevutil_getaddrinfo_common_(const char *nodename, const char *servname, 963e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct evutil_addrinfo *hints, struct evutil_addrinfo **res, int *portnum) 964e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 965e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int port = 0; 966e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley const char *pname; 967e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 968e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (nodename == NULL && servname == NULL) 969e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return EVUTIL_EAI_NONAME; 970e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 971e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* We only understand 3 families */ 972e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (hints->ai_family != PF_UNSPEC && hints->ai_family != PF_INET && 973e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley hints->ai_family != PF_INET6) 974e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return EVUTIL_EAI_FAMILY; 975e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 976e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evutil_getaddrinfo_infer_protocols(hints); 977e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 978e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* Look up the port number and protocol, if possible. */ 979e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley pname = evutil_unparse_protoname(hints->ai_protocol); 980e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (servname) { 981e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* XXXX We could look at the protocol we got back from 982e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * getservbyname, but it doesn't seem too useful. */ 983e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley port = evutil_parse_servname(servname, pname, hints); 984e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (port < 0) { 985e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return EVUTIL_EAI_NONAME; 986e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 987e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 988e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 989e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* If we have no node name, then we're supposed to bind to 'any' and 990e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * connect to localhost. */ 991e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (nodename == NULL) { 992e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct evutil_addrinfo *res4=NULL, *res6=NULL; 993e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (hints->ai_family != PF_INET) { /* INET6 or UNSPEC. */ 994e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct sockaddr_in6 sin6; 995e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley memset(&sin6, 0, sizeof(sin6)); 996e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sin6.sin6_family = AF_INET6; 997e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sin6.sin6_port = htons(port); 998e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (hints->ai_flags & EVUTIL_AI_PASSIVE) { 999e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* Bind to :: */ 1000e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } else { 1001e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* connect to ::1 */ 1002e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sin6.sin6_addr.s6_addr[15] = 1; 1003e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1004fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath res6 = evutil_new_addrinfo_((struct sockaddr*)&sin6, 1005e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sizeof(sin6), hints); 1006e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (!res6) 1007e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return EVUTIL_EAI_MEMORY; 1008e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1009e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1010e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (hints->ai_family != PF_INET6) { /* INET or UNSPEC */ 1011e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct sockaddr_in sin; 1012e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley memset(&sin, 0, sizeof(sin)); 1013e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sin.sin_family = AF_INET; 1014e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sin.sin_port = htons(port); 1015e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (hints->ai_flags & EVUTIL_AI_PASSIVE) { 1016e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* Bind to 0.0.0.0 */ 1017e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } else { 1018e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* connect to 127.0.0.1 */ 1019e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sin.sin_addr.s_addr = htonl(0x7f000001); 1020e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1021fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath res4 = evutil_new_addrinfo_((struct sockaddr*)&sin, 1022e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sizeof(sin), hints); 1023e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (!res4) { 1024e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (res6) 1025e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evutil_freeaddrinfo(res6); 1026e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return EVUTIL_EAI_MEMORY; 1027e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1028e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1029fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath *res = evutil_addrinfo_append_(res4, res6); 1030e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 1031e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1032e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1033e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* If we can, we should try to parse the hostname without resolving 1034e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * it. */ 1035e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* Try ipv6. */ 1036e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (hints->ai_family == PF_INET6 || hints->ai_family == PF_UNSPEC) { 1037e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct sockaddr_in6 sin6; 1038e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley memset(&sin6, 0, sizeof(sin6)); 1039e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (1==evutil_inet_pton(AF_INET6, nodename, &sin6.sin6_addr)) { 1040e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* Got an ipv6 address. */ 1041e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sin6.sin6_family = AF_INET6; 1042e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sin6.sin6_port = htons(port); 1043fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath *res = evutil_new_addrinfo_((struct sockaddr*)&sin6, 1044e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sizeof(sin6), hints); 1045e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (!*res) 1046e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return EVUTIL_EAI_MEMORY; 1047e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 1048e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1049e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1050e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1051e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* Try ipv4. */ 1052e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (hints->ai_family == PF_INET || hints->ai_family == PF_UNSPEC) { 1053e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct sockaddr_in sin; 1054e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley memset(&sin, 0, sizeof(sin)); 1055e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (1==evutil_inet_pton(AF_INET, nodename, &sin.sin_addr)) { 1056e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* Got an ipv6 address. */ 1057e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sin.sin_family = AF_INET; 1058e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sin.sin_port = htons(port); 1059fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath *res = evutil_new_addrinfo_((struct sockaddr*)&sin, 1060e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sizeof(sin), hints); 1061e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (!*res) 1062e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return EVUTIL_EAI_MEMORY; 1063e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 1064e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1065e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1066e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1067e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1068e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* If we have reached this point, we definitely need to do a DNS 1069e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * lookup. */ 1070e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if ((hints->ai_flags & EVUTIL_AI_NUMERICHOST)) { 1071e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* If we're not allowed to do one, then say so. */ 1072e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return EVUTIL_EAI_NONAME; 1073e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1074e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley *portnum = port; 1075e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return EVUTIL_EAI_NEED_RESOLVE; 1076e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 1077e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1078fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifdef EVENT__HAVE_GETADDRINFO 1079e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#define USE_NATIVE_GETADDRINFO 1080e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 1081e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1082e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef USE_NATIVE_GETADDRINFO 1083e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/* A mask of all the flags that we declare, so we can clear them before calling 1084e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * the native getaddrinfo */ 1085e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic const unsigned int ALL_NONNATIVE_AI_FLAGS = 1086e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifndef AI_PASSIVE 1087e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EVUTIL_AI_PASSIVE | 1088e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 1089e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifndef AI_CANONNAME 1090e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EVUTIL_AI_CANONNAME | 1091e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 1092e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifndef AI_NUMERICHOST 1093e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EVUTIL_AI_NUMERICHOST | 1094e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 1095e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifndef AI_NUMERICSERV 1096e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EVUTIL_AI_NUMERICSERV | 1097e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 1098e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifndef AI_ADDRCONFIG 1099e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EVUTIL_AI_ADDRCONFIG | 1100e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 1101e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifndef AI_ALL 1102e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EVUTIL_AI_ALL | 1103e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 1104e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifndef AI_V4MAPPED 1105e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EVUTIL_AI_V4MAPPED | 1106e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 1107e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EVUTIL_AI_LIBEVENT_ALLOCATED; 1108e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1109e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic const unsigned int ALL_NATIVE_AI_FLAGS = 1110e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef AI_PASSIVE 1111e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley AI_PASSIVE | 1112e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 1113e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef AI_CANONNAME 1114e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley AI_CANONNAME | 1115e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 1116e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef AI_NUMERICHOST 1117e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley AI_NUMERICHOST | 1118e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 1119e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef AI_NUMERICSERV 1120e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley AI_NUMERICSERV | 1121e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 1122e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef AI_ADDRCONFIG 1123e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley AI_ADDRCONFIG | 1124e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 1125e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef AI_ALL 1126e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley AI_ALL | 1127e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 1128e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef AI_V4MAPPED 1129e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley AI_V4MAPPED | 1130e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 1131e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 0; 1132e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 1133e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1134e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifndef USE_NATIVE_GETADDRINFO 1135e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/* Helper for systems with no getaddrinfo(): make one or more addrinfos out of 1136e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * a struct hostent. 1137e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley */ 1138e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic struct evutil_addrinfo * 1139e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyaddrinfo_from_hostent(const struct hostent *ent, 1140e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int port, const struct evutil_addrinfo *hints) 1141e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 1142e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int i; 1143e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct sockaddr_in sin; 1144e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct sockaddr_in6 sin6; 1145e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct sockaddr *sa; 1146e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int socklen; 1147e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct evutil_addrinfo *res=NULL, *ai; 1148e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley void *addrp; 1149e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1150e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (ent->h_addrtype == PF_INET) { 1151e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley memset(&sin, 0, sizeof(sin)); 1152e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sin.sin_family = AF_INET; 1153e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sin.sin_port = htons(port); 1154e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sa = (struct sockaddr *)&sin; 1155e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley socklen = sizeof(struct sockaddr_in); 1156e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley addrp = &sin.sin_addr; 1157e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (ent->h_length != sizeof(sin.sin_addr)) { 1158e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley event_warnx("Weird h_length from gethostbyname"); 1159e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return NULL; 1160e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1161e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } else if (ent->h_addrtype == PF_INET6) { 1162e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley memset(&sin6, 0, sizeof(sin6)); 1163e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sin6.sin6_family = AF_INET6; 1164e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sin6.sin6_port = htons(port); 1165e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sa = (struct sockaddr *)&sin6; 1166fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath socklen = sizeof(struct sockaddr_in6); 1167e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley addrp = &sin6.sin6_addr; 1168e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (ent->h_length != sizeof(sin6.sin6_addr)) { 1169e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley event_warnx("Weird h_length from gethostbyname"); 1170e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return NULL; 1171e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1172e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } else 1173e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return NULL; 1174e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1175e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley for (i = 0; ent->h_addr_list[i]; ++i) { 1176e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley memcpy(addrp, ent->h_addr_list[i], ent->h_length); 1177fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath ai = evutil_new_addrinfo_(sa, socklen, hints); 1178e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (!ai) { 1179e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evutil_freeaddrinfo(res); 1180e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return NULL; 1181e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1182fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath res = evutil_addrinfo_append_(res, ai); 1183e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1184e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1185e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (res && ((hints->ai_flags & EVUTIL_AI_CANONNAME) && ent->h_name)) { 1186e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley res->ai_canonname = mm_strdup(ent->h_name); 1187e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (res->ai_canonname == NULL) { 1188e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evutil_freeaddrinfo(res); 1189e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return NULL; 1190e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1191e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1192e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1193e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return res; 1194e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 1195e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 1196e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1197e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/* If the EVUTIL_AI_ADDRCONFIG flag is set on hints->ai_flags, and 1198e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * hints->ai_family is PF_UNSPEC, then revise the value of hints->ai_family so 1199e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * that we'll only get addresses we could maybe connect to. 1200e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley */ 1201e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyvoid 1202fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathevutil_adjust_hints_for_addrconfig_(struct evutil_addrinfo *hints) 1203e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 1204e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (!(hints->ai_flags & EVUTIL_AI_ADDRCONFIG)) 1205e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return; 1206e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (hints->ai_family != PF_UNSPEC) 1207e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return; 1208e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (!have_checked_interfaces) 1209e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evutil_check_interfaces(0); 1210e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (had_ipv4_address && !had_ipv6_address) { 1211e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley hints->ai_family = PF_INET; 1212e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } else if (!had_ipv4_address && had_ipv6_address) { 1213e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley hints->ai_family = PF_INET6; 1214e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1215e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 1216e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1217e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef USE_NATIVE_GETADDRINFO 1218e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic int need_numeric_port_hack_=0; 1219e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic int need_socktype_protocol_hack_=0; 1220e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic int tested_for_getaddrinfo_hacks=0; 1221e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1222e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/* Some older BSDs (like OpenBSD up to 4.6) used to believe that 1223e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley giving a numeric port without giving an ai_socktype was verboten. 1224e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley We test for this so we can apply an appropriate workaround. If it 1225e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley turns out that the bug is present, then: 1226e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1227e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley - If nodename==NULL and servname is numeric, we build an answer 1228fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath ourselves using evutil_getaddrinfo_common_(). 1229e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1230e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley - If nodename!=NULL and servname is numeric, then we set 1231e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley servname=NULL when calling getaddrinfo, and post-process the 1232e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley result to set the ports on it. 1233e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1234e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley We test for this bug at runtime, since otherwise we can't have the 1235e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley same binary run on multiple BSD versions. 1236e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1237e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley - Some versions of Solaris believe that it's nice to leave to protocol 1238e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley field set to 0. We test for this so we can apply an appropriate 1239e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley workaround. 1240e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley*/ 1241fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathstatic struct evutil_addrinfo *ai_find_protocol(struct evutil_addrinfo *ai) 1242fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath{ 1243fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath while (ai) { 1244fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (ai->ai_protocol) 1245fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return ai; 1246fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath ai = ai->ai_next; 1247fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 1248fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return NULL; 1249fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath} 1250e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic void 1251e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileytest_for_getaddrinfo_hacks(void) 1252e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 1253e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int r, r2; 1254fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath struct evutil_addrinfo *ai=NULL, *ai2=NULL, *ai3=NULL; 1255e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct evutil_addrinfo hints; 1256e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1257e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley memset(&hints,0,sizeof(hints)); 1258e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley hints.ai_family = PF_UNSPEC; 1259e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley hints.ai_flags = 1260e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef AI_NUMERICHOST 1261e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley AI_NUMERICHOST | 1262e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 1263e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef AI_NUMERICSERV 1264e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley AI_NUMERICSERV | 1265e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 1266e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 0; 1267e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley r = getaddrinfo("1.2.3.4", "80", &hints, &ai); 1268fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath getaddrinfo("1.2.3.4", NULL, &hints, &ai3); 1269e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley hints.ai_socktype = SOCK_STREAM; 1270e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley r2 = getaddrinfo("1.2.3.4", "80", &hints, &ai2); 1271e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (r2 == 0 && r != 0) { 1272e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley need_numeric_port_hack_=1; 1273e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1274fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (!ai_find_protocol(ai2) || !ai_find_protocol(ai3)) { 1275e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley need_socktype_protocol_hack_=1; 1276e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1277e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1278e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (ai) 1279e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley freeaddrinfo(ai); 1280e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (ai2) 1281e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley freeaddrinfo(ai2); 1282fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (ai3) 1283fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath freeaddrinfo(ai3); 1284e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley tested_for_getaddrinfo_hacks=1; 1285e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 1286e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1287e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic inline int 1288e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyneed_numeric_port_hack(void) 1289e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 1290e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (!tested_for_getaddrinfo_hacks) 1291e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley test_for_getaddrinfo_hacks(); 1292e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return need_numeric_port_hack_; 1293e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 1294e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1295e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic inline int 1296e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyneed_socktype_protocol_hack(void) 1297e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 1298e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (!tested_for_getaddrinfo_hacks) 1299e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley test_for_getaddrinfo_hacks(); 1300e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return need_socktype_protocol_hack_; 1301e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 1302e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1303e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic void 1304e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyapply_numeric_port_hack(int port, struct evutil_addrinfo **ai) 1305e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 1306e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* Now we run through the list and set the ports on all of the 1307e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * results where ports would make sense. */ 1308e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley for ( ; *ai; ai = &(*ai)->ai_next) { 1309e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct sockaddr *sa = (*ai)->ai_addr; 1310e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (sa && sa->sa_family == AF_INET) { 1311e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct sockaddr_in *sin = (struct sockaddr_in*)sa; 1312e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sin->sin_port = htons(port); 1313e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } else if (sa && sa->sa_family == AF_INET6) { 1314e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)sa; 1315e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sin6->sin6_port = htons(port); 1316e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } else { 1317e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* A numeric port makes no sense here; remove this one 1318e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * from the list. */ 1319e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct evutil_addrinfo *victim = *ai; 1320e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley *ai = victim->ai_next; 1321e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley victim->ai_next = NULL; 1322e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley freeaddrinfo(victim); 1323e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1324e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1325e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 1326e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1327e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic int 1328e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyapply_socktype_protocol_hack(struct evutil_addrinfo *ai) 1329e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 1330e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct evutil_addrinfo *ai_new; 1331e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley for (; ai; ai = ai->ai_next) { 1332e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evutil_getaddrinfo_infer_protocols(ai); 1333e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (ai->ai_socktype || ai->ai_protocol) 1334e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley continue; 1335e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley ai_new = mm_malloc(sizeof(*ai_new)); 1336e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (!ai_new) 1337e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 1338e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley memcpy(ai_new, ai, sizeof(*ai_new)); 1339e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley ai->ai_socktype = SOCK_STREAM; 1340e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley ai->ai_protocol = IPPROTO_TCP; 1341e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley ai_new->ai_socktype = SOCK_DGRAM; 1342e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley ai_new->ai_protocol = IPPROTO_UDP; 1343e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1344e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley ai_new->ai_next = ai->ai_next; 1345e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley ai->ai_next = ai_new; 1346e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1347e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 1348e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 1349e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 1350e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1351e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyint 1352e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevutil_getaddrinfo(const char *nodename, const char *servname, 1353e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley const struct evutil_addrinfo *hints_in, struct evutil_addrinfo **res) 1354e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 1355e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef USE_NATIVE_GETADDRINFO 1356e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct evutil_addrinfo hints; 1357e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int portnum=-1, need_np_hack, err; 1358e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1359e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (hints_in) { 1360e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley memcpy(&hints, hints_in, sizeof(hints)); 1361e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } else { 1362e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley memset(&hints, 0, sizeof(hints)); 1363e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley hints.ai_family = PF_UNSPEC; 1364e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1365e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1366e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifndef AI_ADDRCONFIG 1367e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* Not every system has AI_ADDRCONFIG, so fake it. */ 1368e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (hints.ai_family == PF_UNSPEC && 1369e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley (hints.ai_flags & EVUTIL_AI_ADDRCONFIG)) { 1370fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath evutil_adjust_hints_for_addrconfig_(&hints); 1371e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1372e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 1373e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1374e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifndef AI_NUMERICSERV 1375e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* Not every system has AI_NUMERICSERV, so fake it. */ 1376e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (hints.ai_flags & EVUTIL_AI_NUMERICSERV) { 1377e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (servname && parse_numeric_servname(servname)<0) 1378e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return EVUTIL_EAI_NONAME; 1379e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1380e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 1381e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1382e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* Enough operating systems handle enough common non-resolve 1383e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * cases here weirdly enough that we are better off just 1384e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * overriding them. For example: 1385e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * 1386e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * - Windows doesn't like to infer the protocol from the 1387e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * socket type, or fill in socket or protocol types much at 1388e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * all. It also seems to do its own broken implicit 1389e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * always-on version of AI_ADDRCONFIG that keeps it from 1390e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * ever resolving even a literal IPv6 address when 1391e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * ai_addrtype is PF_UNSPEC. 1392e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley */ 1393fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifdef _WIN32 1394e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley { 1395e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int tmp_port; 1396fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath err = evutil_getaddrinfo_common_(nodename,servname,&hints, 1397e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley res, &tmp_port); 1398e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (err == 0 || 1399e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley err == EVUTIL_EAI_MEMORY || 1400e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley err == EVUTIL_EAI_NONAME) 1401e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return err; 1402e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* If we make it here, the system getaddrinfo can 1403e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * have a crack at it. */ 1404e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1405e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 1406e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1407e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* See documentation for need_numeric_port_hack above.*/ 1408e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley need_np_hack = need_numeric_port_hack() && servname && !hints.ai_socktype 1409e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley && ((portnum=parse_numeric_servname(servname)) >= 0); 1410e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (need_np_hack) { 1411e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (!nodename) 1412fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return evutil_getaddrinfo_common_( 1413e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley NULL,servname,&hints, res, &portnum); 1414e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley servname = NULL; 1415e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1416e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1417e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (need_socktype_protocol_hack()) { 1418e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evutil_getaddrinfo_infer_protocols(&hints); 1419e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1420e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1421e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* Make sure that we didn't actually steal any AI_FLAGS values that 1422e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * the system is using. (This is a constant expression, and should ge 1423e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * optimized out.) 1424e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * 1425e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * XXXX Turn this into a compile-time failure rather than a run-time 1426e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * failure. 1427e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley */ 1428e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley EVUTIL_ASSERT((ALL_NONNATIVE_AI_FLAGS & ALL_NATIVE_AI_FLAGS) == 0); 1429e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1430e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* Clear any flags that only libevent understands. */ 1431e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley hints.ai_flags &= ~ALL_NONNATIVE_AI_FLAGS; 1432e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1433e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley err = getaddrinfo(nodename, servname, &hints, res); 1434e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (need_np_hack) 1435e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley apply_numeric_port_hack(portnum, res); 1436e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1437e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (need_socktype_protocol_hack()) { 1438e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (apply_socktype_protocol_hack(*res) < 0) { 1439e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evutil_freeaddrinfo(*res); 1440e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley *res = NULL; 1441e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return EVUTIL_EAI_MEMORY; 1442e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1443e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1444e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return err; 1445e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#else 1446e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int port=0, err; 1447e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct hostent *ent = NULL; 1448e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct evutil_addrinfo hints; 1449e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1450e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (hints_in) { 1451e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley memcpy(&hints, hints_in, sizeof(hints)); 1452e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } else { 1453e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley memset(&hints, 0, sizeof(hints)); 1454e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley hints.ai_family = PF_UNSPEC; 1455e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1456e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1457fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath evutil_adjust_hints_for_addrconfig_(&hints); 1458e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1459fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath err = evutil_getaddrinfo_common_(nodename, servname, &hints, res, &port); 1460e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (err != EVUTIL_EAI_NEED_RESOLVE) { 1461e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* We either succeeded or failed. No need to continue */ 1462e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return err; 1463e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1464e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1465e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley err = 0; 1466e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* Use any of the various gethostbyname_r variants as available. */ 1467e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley { 1468fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifdef EVENT__HAVE_GETHOSTBYNAME_R_6_ARG 1469e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* This one is what glibc provides. */ 1470e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley char buf[2048]; 1471e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct hostent hostent; 1472e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int r; 1473e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley r = gethostbyname_r(nodename, &hostent, buf, sizeof(buf), &ent, 1474e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley &err); 1475fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#elif defined(EVENT__HAVE_GETHOSTBYNAME_R_5_ARG) 1476e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley char buf[2048]; 1477e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct hostent hostent; 1478e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley ent = gethostbyname_r(nodename, &hostent, buf, sizeof(buf), 1479e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley &err); 1480fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#elif defined(EVENT__HAVE_GETHOSTBYNAME_R_3_ARG) 1481e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct hostent_data data; 1482e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct hostent hostent; 1483e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley memset(&data, 0, sizeof(data)); 1484e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley err = gethostbyname_r(nodename, &hostent, &data); 1485e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley ent = err ? NULL : &hostent; 1486e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#else 1487e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* fall back to gethostbyname. */ 1488e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* XXXX This needs a lock everywhere but Windows. */ 1489e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley ent = gethostbyname(nodename); 1490fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifdef _WIN32 1491e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley err = WSAGetLastError(); 1492e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#else 1493e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley err = h_errno; 1494e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 1495e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 1496e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1497e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* Now we have either ent or err set. */ 1498e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (!ent) { 1499e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* XXX is this right for windows ? */ 1500e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley switch (err) { 1501e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case TRY_AGAIN: 1502e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return EVUTIL_EAI_AGAIN; 1503e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case NO_RECOVERY: 1504e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley default: 1505e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return EVUTIL_EAI_FAIL; 1506e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case HOST_NOT_FOUND: 1507e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return EVUTIL_EAI_NONAME; 1508e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case NO_ADDRESS: 1509e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#if NO_DATA != NO_ADDRESS 1510e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case NO_DATA: 1511e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 1512e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return EVUTIL_EAI_NODATA; 1513e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1514e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1515e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1516e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (ent->h_addrtype != hints.ai_family && 1517e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley hints.ai_family != PF_UNSPEC) { 1518e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* This wasn't the type we were hoping for. Too bad 1519e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * we never had a chance to ask gethostbyname for what 1520e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * we wanted. */ 1521e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return EVUTIL_EAI_NONAME; 1522e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1523e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1524e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* Make sure we got _some_ answers. */ 1525e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (ent->h_length == 0) 1526e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return EVUTIL_EAI_NODATA; 1527e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1528e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* If we got an address type we don't know how to make a 1529e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sockaddr for, give up. */ 1530e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (ent->h_addrtype != PF_INET && ent->h_addrtype != PF_INET6) 1531e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return EVUTIL_EAI_FAMILY; 1532e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1533e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley *res = addrinfo_from_hostent(ent, port, &hints); 1534e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (! *res) 1535e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return EVUTIL_EAI_MEMORY; 1536e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1537e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1538e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 1539e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 1540e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 1541e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1542e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyvoid 1543e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevutil_freeaddrinfo(struct evutil_addrinfo *ai) 1544e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 1545fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifdef EVENT__HAVE_GETADDRINFO 1546e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (!(ai->ai_flags & EVUTIL_AI_LIBEVENT_ALLOCATED)) { 1547e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley freeaddrinfo(ai); 1548e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return; 1549e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1550e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 1551e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley while (ai) { 1552e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct evutil_addrinfo *next = ai->ai_next; 1553e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (ai->ai_canonname) 1554e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley mm_free(ai->ai_canonname); 1555e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley mm_free(ai); 1556e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley ai = next; 1557e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1558e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 1559e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1560e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic evdns_getaddrinfo_fn evdns_getaddrinfo_impl = NULL; 1561fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathstatic evdns_getaddrinfo_cancel_fn evdns_getaddrinfo_cancel_impl = NULL; 1562e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1563e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyvoid 1564fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathevutil_set_evdns_getaddrinfo_fn_(evdns_getaddrinfo_fn fn) 1565e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 1566e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (!evdns_getaddrinfo_impl) 1567e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evdns_getaddrinfo_impl = fn; 1568e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 1569fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathvoid 1570fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathevutil_set_evdns_getaddrinfo_cancel_fn_(evdns_getaddrinfo_cancel_fn fn) 1571fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath{ 1572fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (!evdns_getaddrinfo_cancel_impl) 1573fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath evdns_getaddrinfo_cancel_impl = fn; 1574fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath} 1575e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1576e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/* Internal helper function: act like evdns_getaddrinfo if dns_base is set; 1577e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * otherwise do a blocking resolve and pass the result to the callback in the 1578e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * way that evdns_getaddrinfo would. 1579e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley */ 1580fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathstruct evdns_getaddrinfo_request *evutil_getaddrinfo_async_( 1581fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath struct evdns_base *dns_base, 1582e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley const char *nodename, const char *servname, 1583e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley const struct evutil_addrinfo *hints_in, 1584e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley void (*cb)(int, struct evutil_addrinfo *, void *), void *arg) 1585e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 1586e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (dns_base && evdns_getaddrinfo_impl) { 1587fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return evdns_getaddrinfo_impl( 1588e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley dns_base, nodename, servname, hints_in, cb, arg); 1589e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } else { 1590e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct evutil_addrinfo *ai=NULL; 1591e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int err; 1592e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley err = evutil_getaddrinfo(nodename, servname, hints_in, &ai); 1593e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley cb(err, ai, arg); 1594fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return NULL; 1595fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 1596fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath} 1597fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 1598fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathvoid evutil_getaddrinfo_cancel_async_(struct evdns_getaddrinfo_request *data) 1599fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath{ 1600fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (evdns_getaddrinfo_cancel_impl && data) { 1601fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath evdns_getaddrinfo_cancel_impl(data); 1602e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1603e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 1604e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1605e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyconst char * 1606e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevutil_gai_strerror(int err) 1607e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 1608e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* As a sneaky side-benefit, this case statement will get most 1609e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * compilers to tell us if any of the error codes we defined 1610e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * conflict with the platform's native error codes. */ 1611e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley switch (err) { 1612e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case EVUTIL_EAI_CANCEL: 1613e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return "Request canceled"; 1614e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case 0: 1615e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return "No error"; 1616e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1617e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case EVUTIL_EAI_ADDRFAMILY: 1618e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return "address family for nodename not supported"; 1619e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case EVUTIL_EAI_AGAIN: 1620e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return "temporary failure in name resolution"; 1621e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case EVUTIL_EAI_BADFLAGS: 1622e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return "invalid value for ai_flags"; 1623e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case EVUTIL_EAI_FAIL: 1624e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return "non-recoverable failure in name resolution"; 1625e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case EVUTIL_EAI_FAMILY: 1626e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return "ai_family not supported"; 1627e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case EVUTIL_EAI_MEMORY: 1628e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return "memory allocation failure"; 1629e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case EVUTIL_EAI_NODATA: 1630e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return "no address associated with nodename"; 1631e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case EVUTIL_EAI_NONAME: 1632e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return "nodename nor servname provided, or not known"; 1633e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case EVUTIL_EAI_SERVICE: 1634e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return "servname not supported for ai_socktype"; 1635e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case EVUTIL_EAI_SOCKTYPE: 1636e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return "ai_socktype not supported"; 1637e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case EVUTIL_EAI_SYSTEM: 1638e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return "system error"; 1639e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley default: 1640fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#if defined(USE_NATIVE_GETADDRINFO) && defined(_WIN32) 1641e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return gai_strerrorA(err); 1642e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#elif defined(USE_NATIVE_GETADDRINFO) 1643e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return gai_strerror(err); 1644e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#else 1645e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return "Unknown error code"; 1646e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 1647e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1648e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 1649e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1650fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifdef _WIN32 1651fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath/* destructively remove a trailing line terminator from s */ 1652fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathstatic void 1653fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathchomp (char *s) 1654fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath{ 1655fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath size_t len; 1656fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (s && (len = strlen (s)) > 0 && s[len - 1] == '\n') { 1657fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath s[--len] = 0; 1658fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (len > 0 && s[len - 1] == '\r') 1659fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath s[--len] = 0; 1660fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 1661fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath} 1662fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 1663fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath/* FormatMessage returns allocated strings, but evutil_socket_error_to_string 1664fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * is supposed to return a string which is good indefinitely without having 1665fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * to be freed. To make this work without leaking memory, we cache the 1666fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * string the first time FormatMessage is called on a particular error 1667fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * code, and then return the cached string on subsequent calls with the 1668fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * same code. The strings aren't freed until libevent_global_shutdown 1669fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * (or never). We use a linked list to cache the errors, because we 1670fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * only expect there to be a few dozen, and that should be fast enough. 1671fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath */ 1672fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 1673fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathstruct cached_sock_errs_entry { 1674fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath HT_ENTRY(cached_sock_errs_entry) node; 1675fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath DWORD code; 1676fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath char *msg; /* allocated with LocalAlloc; free with LocalFree */ 1677e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley}; 1678fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 1679fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathstatic inline unsigned 1680fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathhash_cached_sock_errs(const struct cached_sock_errs_entry *e) 1681fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath{ 1682fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath /* Use Murmur3's 32-bit finalizer as an integer hash function */ 1683fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath DWORD h = e->code; 1684fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath h ^= h >> 16; 1685fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath h *= 0x85ebca6b; 1686fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath h ^= h >> 13; 1687fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath h *= 0xc2b2ae35; 1688fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath h ^= h >> 16; 1689fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return h; 1690fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath} 1691fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 1692fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathstatic inline int 1693fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamatheq_cached_sock_errs(const struct cached_sock_errs_entry *a, 1694fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath const struct cached_sock_errs_entry *b) 1695fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath{ 1696fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return a->code == b->code; 1697fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath} 1698fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 1699fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifndef EVENT__DISABLE_THREAD_SUPPORT 1700fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathstatic void *windows_socket_errors_lock_ = NULL; 1701fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#endif 1702fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 1703fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathstatic HT_HEAD(cached_sock_errs_map, cached_sock_errs_entry) 1704fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath windows_socket_errors = HT_INITIALIZER(); 1705fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 1706fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan KamathHT_PROTOTYPE(cached_sock_errs_map, 1707fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath cached_sock_errs_entry, 1708fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath node, 1709fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath hash_cached_sock_errs, 1710fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath eq_cached_sock_errs); 1711fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 1712fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan KamathHT_GENERATE(cached_sock_errs_map, 1713fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath cached_sock_errs_entry, 1714fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath node, 1715fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath hash_cached_sock_errs, 1716fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath eq_cached_sock_errs, 1717fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 0.5, 1718fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath mm_malloc, 1719fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath mm_realloc, 1720fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath mm_free); 1721fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 1722e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/** Equivalent to strerror, but for windows socket errors. */ 1723e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyconst char * 1724e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevutil_socket_error_to_string(int errcode) 1725e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 1726fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath struct cached_sock_errs_entry *errs, *newerr, find; 1727fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath char *msg = NULL; 1728fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 1729fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath EVLOCK_LOCK(windows_socket_errors_lock_, 0); 1730fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 1731fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath find.code = errcode; 1732fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath errs = HT_FIND(cached_sock_errs_map, &windows_socket_errors, &find); 1733fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (errs) { 1734fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath msg = errs->msg; 1735fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath goto done; 1736fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 1737fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 1738fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (0 != FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | 1739fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath FORMAT_MESSAGE_IGNORE_INSERTS | 1740fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath FORMAT_MESSAGE_ALLOCATE_BUFFER, 1741fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath NULL, errcode, 0, (char *)&msg, 0, NULL)) 1742fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath chomp (msg); /* because message has trailing newline */ 1743fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath else { 1744fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath size_t len = 50; 1745fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath /* use LocalAlloc because FormatMessage does */ 1746fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath msg = LocalAlloc(LMEM_FIXED, len); 1747fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (!msg) { 1748fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath msg = (char *)"LocalAlloc failed during Winsock error"; 1749fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath goto done; 1750fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 1751fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath evutil_snprintf(msg, len, "winsock error 0x%08x", errcode); 1752fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 1753fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 1754fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath newerr = (struct cached_sock_errs_entry *) 1755fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath mm_malloc(sizeof (struct cached_sock_errs_entry)); 1756fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 1757fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (!newerr) { 1758fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath LocalFree(msg); 1759fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath msg = (char *)"malloc failed during Winsock error"; 1760fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath goto done; 1761fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 1762fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 1763fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath newerr->code = errcode; 1764fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath newerr->msg = msg; 1765fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath HT_INSERT(cached_sock_errs_map, &windows_socket_errors, newerr); 1766fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 1767fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath done: 1768fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath EVLOCK_UNLOCK(windows_socket_errors_lock_, 0); 1769fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 1770fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return msg; 1771fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath} 1772fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 1773fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifndef EVENT__DISABLE_THREAD_SUPPORT 1774fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathint 1775fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathevutil_global_setup_locks_(const int enable_locks) 1776fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath{ 1777fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath EVTHREAD_SETUP_GLOBAL_LOCK(windows_socket_errors_lock_, 0); 1778fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return 0; 1779e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 1780e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 1781e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1782fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathstatic void 1783fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathevutil_free_sock_err_globals(void) 1784fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath{ 1785fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath struct cached_sock_errs_entry **errs, *tofree; 1786fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 1787fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath for (errs = HT_START(cached_sock_errs_map, &windows_socket_errors) 1788fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath ; errs; ) { 1789fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath tofree = *errs; 1790fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath errs = HT_NEXT_RMV(cached_sock_errs_map, 1791fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath &windows_socket_errors, 1792fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath errs); 1793fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath LocalFree(tofree->msg); 1794fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath mm_free(tofree); 1795fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 1796fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 1797fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath HT_CLEAR(cached_sock_errs_map, &windows_socket_errors); 1798fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 1799fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifndef EVENT__DISABLE_THREAD_SUPPORT 1800fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (windows_socket_errors_lock_ != NULL) { 1801fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath EVTHREAD_FREE_LOCK(windows_socket_errors_lock_, 0); 1802fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath windows_socket_errors_lock_ = NULL; 1803fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 1804fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#endif 1805fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath} 1806fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 1807fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#else 1808fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 1809fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifndef EVENT__DISABLE_THREAD_SUPPORT 1810fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathint 1811fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathevutil_global_setup_locks_(const int enable_locks) 1812fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath{ 1813fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return 0; 1814fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath} 1815fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#endif 1816fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 1817fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathstatic void 1818fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathevutil_free_sock_err_globals(void) 1819fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath{ 1820fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath} 1821fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 1822fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#endif 1823fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 1824e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyint 1825e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevutil_snprintf(char *buf, size_t buflen, const char *format, ...) 1826e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 1827e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int r; 1828e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley va_list ap; 1829e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley va_start(ap, format); 1830e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley r = evutil_vsnprintf(buf, buflen, format, ap); 1831e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley va_end(ap); 1832e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return r; 1833e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 1834e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1835e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyint 1836e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevutil_vsnprintf(char *buf, size_t buflen, const char *format, va_list ap) 1837e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 1838e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int r; 1839e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (!buflen) 1840e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 1841fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#if defined(_MSC_VER) || defined(_WIN32) 1842e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley r = _vsnprintf(buf, buflen, format, ap); 1843e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (r < 0) 1844e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley r = _vscprintf(format, ap); 1845e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#elif defined(sgi) 1846e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* Make sure we always use the correct vsnprintf on IRIX */ 1847e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley extern int _xpg5_vsnprintf(char * __restrict, 1848e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley __SGI_LIBC_NAMESPACE_QUALIFIER size_t, 1849e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley const char * __restrict, /* va_list */ char *); 1850e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1851e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley r = _xpg5_vsnprintf(buf, buflen, format, ap); 1852e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#else 1853e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley r = vsnprintf(buf, buflen, format, ap); 1854e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 1855e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley buf[buflen-1] = '\0'; 1856e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return r; 1857e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 1858e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1859e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#define USE_INTERNAL_NTOP 1860e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#define USE_INTERNAL_PTON 1861e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1862e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyconst char * 1863e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevutil_inet_ntop(int af, const void *src, char *dst, size_t len) 1864e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 1865fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#if defined(EVENT__HAVE_INET_NTOP) && !defined(USE_INTERNAL_NTOP) 1866e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return inet_ntop(af, src, dst, len); 1867e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#else 1868e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (af == AF_INET) { 1869e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley const struct in_addr *in = src; 1870e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley const ev_uint32_t a = ntohl(in->s_addr); 1871e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int r; 1872e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley r = evutil_snprintf(dst, len, "%d.%d.%d.%d", 1873e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley (int)(ev_uint8_t)((a>>24)&0xff), 1874e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley (int)(ev_uint8_t)((a>>16)&0xff), 1875e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley (int)(ev_uint8_t)((a>>8 )&0xff), 1876e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley (int)(ev_uint8_t)((a )&0xff)); 1877e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (r<0||(size_t)r>=len) 1878e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return NULL; 1879e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley else 1880e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return dst; 1881e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef AF_INET6 1882e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } else if (af == AF_INET6) { 1883e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley const struct in6_addr *addr = src; 1884e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley char buf[64], *cp; 1885e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int longestGapLen = 0, longestGapPos = -1, i, 1886e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley curGapPos = -1, curGapLen = 0; 1887e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley ev_uint16_t words[8]; 1888e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley for (i = 0; i < 8; ++i) { 1889e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley words[i] = 1890e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley (((ev_uint16_t)addr->s6_addr[2*i])<<8) + addr->s6_addr[2*i+1]; 1891e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1892e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && 1893e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley words[4] == 0 && ((words[5] == 0 && words[6] && words[7]) || 1894e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley (words[5] == 0xffff))) { 1895e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* This is an IPv4 address. */ 1896e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (words[5] == 0) { 1897e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evutil_snprintf(buf, sizeof(buf), "::%d.%d.%d.%d", 1898e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley addr->s6_addr[12], addr->s6_addr[13], 1899e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley addr->s6_addr[14], addr->s6_addr[15]); 1900e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } else { 1901e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evutil_snprintf(buf, sizeof(buf), "::%x:%d.%d.%d.%d", words[5], 1902e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley addr->s6_addr[12], addr->s6_addr[13], 1903e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley addr->s6_addr[14], addr->s6_addr[15]); 1904e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1905e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (strlen(buf) > len) 1906e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return NULL; 1907e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley strlcpy(dst, buf, len); 1908e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return dst; 1909e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1910e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley i = 0; 1911e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley while (i < 8) { 1912e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (words[i] == 0) { 1913e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley curGapPos = i++; 1914e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley curGapLen = 1; 1915e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley while (i<8 && words[i] == 0) { 1916e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley ++i; ++curGapLen; 1917e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1918e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (curGapLen > longestGapLen) { 1919e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley longestGapPos = curGapPos; 1920e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley longestGapLen = curGapLen; 1921e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1922e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } else { 1923e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley ++i; 1924e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1925e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1926e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (longestGapLen<=1) 1927e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley longestGapPos = -1; 1928e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1929e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley cp = buf; 1930e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley for (i = 0; i < 8; ++i) { 1931e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (words[i] == 0 && longestGapPos == i) { 1932e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (i == 0) 1933e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley *cp++ = ':'; 1934e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley *cp++ = ':'; 1935e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley while (i < 8 && words[i] == 0) 1936e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley ++i; 1937e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley --i; /* to compensate for loop increment. */ 1938e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } else { 1939e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evutil_snprintf(cp, 1940e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sizeof(buf)-(cp-buf), "%x", (unsigned)words[i]); 1941e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley cp += strlen(cp); 1942e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (i != 7) 1943e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley *cp++ = ':'; 1944e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1945e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1946e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley *cp = '\0'; 1947e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (strlen(buf) > len) 1948e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return NULL; 1949e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley strlcpy(dst, buf, len); 1950e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return dst; 1951e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 1952e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } else { 1953e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return NULL; 1954e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 1955e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 1956e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 1957e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1958e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyint 1959e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevutil_inet_pton(int af, const char *src, void *dst) 1960e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 1961fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#if defined(EVENT__HAVE_INET_PTON) && !defined(USE_INTERNAL_PTON) 1962e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return inet_pton(af, src, dst); 1963e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#else 1964e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (af == AF_INET) { 1965fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath unsigned a,b,c,d; 1966e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley char more; 1967e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct in_addr *addr = dst; 1968fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (sscanf(src, "%u.%u.%u.%u%c", &a,&b,&c,&d,&more) != 4) 1969e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 1970fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (a > 255) return 0; 1971fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (b > 255) return 0; 1972fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (c > 255) return 0; 1973fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (d > 255) return 0; 1974e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley addr->s_addr = htonl((a<<24) | (b<<16) | (c<<8) | d); 1975e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 1; 1976e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef AF_INET6 1977e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } else if (af == AF_INET6) { 1978e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct in6_addr *out = dst; 1979e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley ev_uint16_t words[8]; 1980e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int gapPos = -1, i, setWords=0; 1981e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley const char *dot = strchr(src, '.'); 1982e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley const char *eow; /* end of words. */ 1983e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (dot == src) 1984e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 1985e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley else if (!dot) 1986e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley eow = src+strlen(src); 1987e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley else { 1988fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath unsigned byte1,byte2,byte3,byte4; 1989e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley char more; 1990fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath for (eow = dot-1; eow >= src && EVUTIL_ISDIGIT_(*eow); --eow) 1991e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley ; 1992e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley ++eow; 1993e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 1994e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* We use "scanf" because some platform inet_aton()s are too lax 1995e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * about IPv4 addresses of the form "1.2.3" */ 1996fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (sscanf(eow, "%u.%u.%u.%u%c", 1997e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley &byte1,&byte2,&byte3,&byte4,&more) != 4) 1998e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 1999e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 2000fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (byte1 > 255 || 2001fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath byte2 > 255 || 2002fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath byte3 > 255 || 2003fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath byte4 > 255) 2004e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 2005e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 2006e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley words[6] = (byte1<<8) | byte2; 2007e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley words[7] = (byte3<<8) | byte4; 2008e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley setWords += 2; 2009e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 2010e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 2011e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley i = 0; 2012e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley while (src < eow) { 2013e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (i > 7) 2014e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 2015fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (EVUTIL_ISXDIGIT_(*src)) { 2016e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley char *next; 2017e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley long r = strtol(src, &next, 16); 2018e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (next > 4+src) 2019e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 2020e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (next == src) 2021e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 2022e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (r<0 || r>65536) 2023e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 2024e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 2025e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley words[i++] = (ev_uint16_t)r; 2026e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley setWords++; 2027e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley src = next; 2028e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (*src != ':' && src != eow) 2029e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 2030e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley ++src; 2031e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } else if (*src == ':' && i > 0 && gapPos==-1) { 2032e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley gapPos = i; 2033e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley ++src; 2034e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } else if (*src == ':' && i == 0 && src[1] == ':' && gapPos==-1) { 2035e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley gapPos = i; 2036e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley src += 2; 2037e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } else { 2038e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 2039e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 2040e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 2041e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 2042e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (setWords > 8 || 2043e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley (setWords == 8 && gapPos != -1) || 2044e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley (setWords < 8 && gapPos == -1)) 2045e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 2046e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 2047e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (gapPos >= 0) { 2048e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int nToMove = setWords - (dot ? 2 : 0) - gapPos; 2049e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int gapLen = 8 - setWords; 2050e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* assert(nToMove >= 0); */ 2051e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (nToMove < 0) 2052e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; /* should be impossible */ 2053e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley memmove(&words[gapPos+gapLen], &words[gapPos], 2054e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sizeof(ev_uint16_t)*nToMove); 2055e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley memset(&words[gapPos], 0, sizeof(ev_uint16_t)*gapLen); 2056e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 2057e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley for (i = 0; i < 8; ++i) { 2058e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley out->s6_addr[2*i ] = words[i] >> 8; 2059e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley out->s6_addr[2*i+1] = words[i] & 0xff; 2060e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 2061e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 2062e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 1; 2063e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 2064e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } else { 2065e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 2066e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 2067e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 2068e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 2069e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 2070e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyint 2071e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevutil_parse_sockaddr_port(const char *ip_as_string, struct sockaddr *out, int *outlen) 2072e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 2073e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int port; 2074e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley char buf[128]; 2075e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley const char *cp, *addr_part, *port_part; 2076e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int is_ipv6; 2077e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley /* recognized formats are: 2078e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * [ipv6]:port 2079e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * ipv6 2080e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * [ipv6] 2081e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * ipv4:port 2082e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * ipv4 2083e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley */ 2084e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 2085e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley cp = strchr(ip_as_string, ':'); 2086e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (*ip_as_string == '[') { 2087fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath size_t len; 2088e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (!(cp = strchr(ip_as_string, ']'))) { 2089e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 2090e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 2091fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath len = ( cp-(ip_as_string + 1) ); 2092fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (len > sizeof(buf)-1) { 2093e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 2094e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 2095e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley memcpy(buf, ip_as_string+1, len); 2096e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley buf[len] = '\0'; 2097e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley addr_part = buf; 2098e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (cp[1] == ':') 2099e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley port_part = cp+2; 2100e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley else 2101e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley port_part = NULL; 2102e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley is_ipv6 = 1; 2103e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } else if (cp && strchr(cp+1, ':')) { 2104e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley is_ipv6 = 1; 2105e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley addr_part = ip_as_string; 2106e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley port_part = NULL; 2107e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } else if (cp) { 2108e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley is_ipv6 = 0; 2109e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (cp - ip_as_string > (int)sizeof(buf)-1) { 2110e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 2111e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 2112e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley memcpy(buf, ip_as_string, cp-ip_as_string); 2113e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley buf[cp-ip_as_string] = '\0'; 2114e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley addr_part = buf; 2115e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley port_part = cp+1; 2116e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } else { 2117e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley addr_part = ip_as_string; 2118e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley port_part = NULL; 2119e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley is_ipv6 = 0; 2120e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 2121e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 2122e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (port_part == NULL) { 2123e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley port = 0; 2124e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } else { 2125e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley port = atoi(port_part); 2126e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (port <= 0 || port > 65535) { 2127e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 2128e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 2129e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 2130e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 2131e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (!addr_part) 2132e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; /* Should be impossible. */ 2133e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef AF_INET6 2134e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (is_ipv6) 2135e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley { 2136e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct sockaddr_in6 sin6; 2137e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley memset(&sin6, 0, sizeof(sin6)); 2138fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifdef EVENT__HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN 2139e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sin6.sin6_len = sizeof(sin6); 2140e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 2141e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sin6.sin6_family = AF_INET6; 2142e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sin6.sin6_port = htons(port); 2143e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (1 != evutil_inet_pton(AF_INET6, addr_part, &sin6.sin6_addr)) 2144e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 2145e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if ((int)sizeof(sin6) > *outlen) 2146e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 2147e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley memset(out, 0, *outlen); 2148e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley memcpy(out, &sin6, sizeof(sin6)); 2149e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley *outlen = sizeof(sin6); 2150e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 2151e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 2152e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley else 2153e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 2154e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley { 2155e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct sockaddr_in sin; 2156e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley memset(&sin, 0, sizeof(sin)); 2157fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifdef EVENT__HAVE_STRUCT_SOCKADDR_IN_SIN_LEN 2158e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sin.sin_len = sizeof(sin); 2159e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 2160e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sin.sin_family = AF_INET; 2161e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sin.sin_port = htons(port); 2162e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (1 != evutil_inet_pton(AF_INET, addr_part, &sin.sin_addr)) 2163e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 2164e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if ((int)sizeof(sin) > *outlen) 2165e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 2166e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley memset(out, 0, *outlen); 2167e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley memcpy(out, &sin, sizeof(sin)); 2168e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley *outlen = sizeof(sin); 2169e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 2170e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 2171e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 2172e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 2173e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyconst char * 2174fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathevutil_format_sockaddr_port_(const struct sockaddr *sa, char *out, size_t outlen) 2175e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 2176e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley char b[128]; 2177e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley const char *res=NULL; 2178e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int port; 2179e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (sa->sa_family == AF_INET) { 2180e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley const struct sockaddr_in *sin = (const struct sockaddr_in*)sa; 2181e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley res = evutil_inet_ntop(AF_INET, &sin->sin_addr,b,sizeof(b)); 2182e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley port = ntohs(sin->sin_port); 2183e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (res) { 2184e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evutil_snprintf(out, outlen, "%s:%d", b, port); 2185e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return out; 2186e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 2187e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } else if (sa->sa_family == AF_INET6) { 2188e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6*)sa; 2189e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley res = evutil_inet_ntop(AF_INET6, &sin6->sin6_addr,b,sizeof(b)); 2190e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley port = ntohs(sin6->sin6_port); 2191e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (res) { 2192e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evutil_snprintf(out, outlen, "[%s]:%d", b, port); 2193e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return out; 2194e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 2195e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 2196e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 2197e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evutil_snprintf(out, outlen, "<addr with socktype %d>", 2198e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley (int)sa->sa_family); 2199e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return out; 2200e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 2201e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 2202e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyint 2203e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevutil_sockaddr_cmp(const struct sockaddr *sa1, const struct sockaddr *sa2, 2204e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int include_port) 2205e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 2206e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley int r; 2207e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (0 != (r = (sa1->sa_family - sa2->sa_family))) 2208e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return r; 2209e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 2210e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (sa1->sa_family == AF_INET) { 2211e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley const struct sockaddr_in *sin1, *sin2; 2212e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sin1 = (const struct sockaddr_in *)sa1; 2213e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sin2 = (const struct sockaddr_in *)sa2; 2214e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (sin1->sin_addr.s_addr < sin2->sin_addr.s_addr) 2215e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 2216e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley else if (sin1->sin_addr.s_addr > sin2->sin_addr.s_addr) 2217e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 1; 2218e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley else if (include_port && 2219e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley (r = ((int)sin1->sin_port - (int)sin2->sin_port))) 2220e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return r; 2221e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley else 2222e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 2223e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 2224e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef AF_INET6 2225e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley else if (sa1->sa_family == AF_INET6) { 2226e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley const struct sockaddr_in6 *sin1, *sin2; 2227e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sin1 = (const struct sockaddr_in6 *)sa1; 2228e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley sin2 = (const struct sockaddr_in6 *)sa2; 2229e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if ((r = memcmp(sin1->sin6_addr.s6_addr, sin2->sin6_addr.s6_addr, 16))) 2230e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return r; 2231e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley else if (include_port && 2232e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley (r = ((int)sin1->sin6_port - (int)sin2->sin6_port))) 2233e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return r; 2234e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley else 2235e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 2236e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 2237e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 2238e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 1; 2239e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 2240e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 2241e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/* Tables to implement ctypes-replacement EVUTIL_IS*() functions. Each table 2242e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * has 256 bits to look up whether a character is in some set or not. This 2243e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * fails on non-ASCII platforms, but so does every other place where we 2244e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * take a char and write it onto the network. 2245e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley **/ 2246e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic const ev_uint32_t EVUTIL_ISALPHA_TABLE[8] = 2247e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley { 0, 0, 0x7fffffe, 0x7fffffe, 0, 0, 0, 0 }; 2248e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic const ev_uint32_t EVUTIL_ISALNUM_TABLE[8] = 2249e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley { 0, 0x3ff0000, 0x7fffffe, 0x7fffffe, 0, 0, 0, 0 }; 2250e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic const ev_uint32_t EVUTIL_ISSPACE_TABLE[8] = { 0x3e00, 0x1, 0, 0, 0, 0, 0, 0 }; 2251e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic const ev_uint32_t EVUTIL_ISXDIGIT_TABLE[8] = 2252e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley { 0, 0x3ff0000, 0x7e, 0x7e, 0, 0, 0, 0 }; 2253e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic const ev_uint32_t EVUTIL_ISDIGIT_TABLE[8] = { 0, 0x3ff0000, 0, 0, 0, 0, 0, 0 }; 2254e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic const ev_uint32_t EVUTIL_ISPRINT_TABLE[8] = 2255e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley { 0, 0xffffffff, 0xffffffff, 0x7fffffff, 0, 0, 0, 0x0 }; 2256e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic const ev_uint32_t EVUTIL_ISUPPER_TABLE[8] = { 0, 0, 0x7fffffe, 0, 0, 0, 0, 0 }; 2257e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic const ev_uint32_t EVUTIL_ISLOWER_TABLE[8] = { 0, 0, 0, 0x7fffffe, 0, 0, 0, 0 }; 2258e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/* Upper-casing and lowercasing tables to map characters to upper/lowercase 2259e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * equivalents. */ 2260e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic const unsigned char EVUTIL_TOUPPER_TABLE[256] = { 2261e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 2262e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, 2263e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, 2264e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63, 2265e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79, 2266e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95, 2267e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 96,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79, 2268e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 80,81,82,83,84,85,86,87,88,89,90,123,124,125,126,127, 2269e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, 2270e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, 2271e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, 2272e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, 2273e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, 2274e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, 2275e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, 2276e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255, 2277e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley}; 2278e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic const unsigned char EVUTIL_TOLOWER_TABLE[256] = { 2279e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 2280e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, 2281e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, 2282e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63, 2283e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 64,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111, 2284e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 112,113,114,115,116,117,118,119,120,121,122,91,92,93,94,95, 2285e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111, 2286e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, 2287e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, 2288e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, 2289e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, 2290e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, 2291e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, 2292e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, 2293e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, 2294e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255, 2295e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley}; 2296e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 2297e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#define IMPL_CTYPE_FN(name) \ 2298fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath int EVUTIL_##name##_(char c) { \ 2299e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley ev_uint8_t u = c; \ 2300e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return !!(EVUTIL_##name##_TABLE[(u >> 5) & 7] & (1 << (u & 31))); \ 2301e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 2302e867981d427db5e0b860d67485838e1f9e8c37daChristopher WileyIMPL_CTYPE_FN(ISALPHA) 2303e867981d427db5e0b860d67485838e1f9e8c37daChristopher WileyIMPL_CTYPE_FN(ISALNUM) 2304e867981d427db5e0b860d67485838e1f9e8c37daChristopher WileyIMPL_CTYPE_FN(ISSPACE) 2305e867981d427db5e0b860d67485838e1f9e8c37daChristopher WileyIMPL_CTYPE_FN(ISDIGIT) 2306e867981d427db5e0b860d67485838e1f9e8c37daChristopher WileyIMPL_CTYPE_FN(ISXDIGIT) 2307e867981d427db5e0b860d67485838e1f9e8c37daChristopher WileyIMPL_CTYPE_FN(ISPRINT) 2308e867981d427db5e0b860d67485838e1f9e8c37daChristopher WileyIMPL_CTYPE_FN(ISLOWER) 2309e867981d427db5e0b860d67485838e1f9e8c37daChristopher WileyIMPL_CTYPE_FN(ISUPPER) 2310e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 2311fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathchar EVUTIL_TOLOWER_(char c) 2312e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 2313e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return ((char)EVUTIL_TOLOWER_TABLE[(ev_uint8_t)c]); 2314e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 2315fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathchar EVUTIL_TOUPPER_(char c) 2316e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 2317e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return ((char)EVUTIL_TOUPPER_TABLE[(ev_uint8_t)c]); 2318e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 2319e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyint 2320e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevutil_ascii_strcasecmp(const char *s1, const char *s2) 2321e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 2322e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley char c1, c2; 2323e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley while (1) { 2324fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath c1 = EVUTIL_TOLOWER_(*s1++); 2325fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath c2 = EVUTIL_TOLOWER_(*s2++); 2326e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (c1 < c2) 2327e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 2328e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley else if (c1 > c2) 2329e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 1; 2330e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley else if (c1 == 0) 2331e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 2332e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 2333e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 2334e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyint evutil_ascii_strncasecmp(const char *s1, const char *s2, size_t n) 2335e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 2336e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley char c1, c2; 2337e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley while (n--) { 2338fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath c1 = EVUTIL_TOLOWER_(*s1++); 2339fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath c2 = EVUTIL_TOLOWER_(*s2++); 2340e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (c1 < c2) 2341e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 2342e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley else if (c1 > c2) 2343e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 1; 2344e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley else if (c1 == 0) 2345e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 2346e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 2347e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 2348e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 2349e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 2350fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathvoid 2351fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathevutil_rtrim_lws_(char *str) 2352fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath{ 2353fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath char *cp; 2354fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 2355fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (str == NULL) 2356fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return; 2357fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 2358fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if ((cp = strchr(str, '\0')) == NULL || (cp == str)) 2359fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return; 2360fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 2361fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath --cp; 2362fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 2363fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath while (*cp == ' ' || *cp == '\t') { 2364fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath *cp = '\0'; 2365fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (cp == str) 2366fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath break; 2367fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath --cp; 2368fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 2369fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath} 2370fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 2371e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic int 2372e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevutil_issetugid(void) 2373e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 2374fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifdef EVENT__HAVE_ISSETUGID 2375e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return issetugid(); 2376e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#else 2377e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 2378fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifdef EVENT__HAVE_GETEUID 2379e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (getuid() != geteuid()) 2380e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 1; 2381e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 2382fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifdef EVENT__HAVE_GETEGID 2383e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (getgid() != getegid()) 2384e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 1; 2385e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 2386e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 2387e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 2388e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 2389e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 2390e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyconst char * 2391fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathevutil_getenv_(const char *varname) 2392e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 2393e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (evutil_issetugid()) 2394e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return NULL; 2395e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 2396e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return getenv(varname); 2397e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 2398e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 2399fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathev_uint32_t 2400fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathevutil_weakrand_seed_(struct evutil_weakrand_state *state, ev_uint32_t seed) 2401e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 2402fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (seed == 0) { 2403fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath struct timeval tv; 2404fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath evutil_gettimeofday(&tv, NULL); 2405fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath seed = (ev_uint32_t)tv.tv_sec + (ev_uint32_t)tv.tv_usec; 2406fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifdef _WIN32 2407fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath seed += (ev_uint32_t) _getpid(); 2408e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#else 2409fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath seed += (ev_uint32_t) getpid(); 2410e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 2411fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 2412fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath state->seed = seed; 2413fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return seed; 2414fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath} 2415fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 2416fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathev_int32_t 2417fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathevutil_weakrand_(struct evutil_weakrand_state *state) 2418fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath{ 2419fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath /* This RNG implementation is a linear congruential generator, with 2420fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * modulus 2^31, multiplier 1103515245, and addend 12345. It's also 2421fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * used by OpenBSD, and by Glibc's TYPE_0 RNG. 2422fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * 2423fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * The linear congruential generator is not an industrial-strength 2424fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * RNG! It's fast, but it can have higher-order patterns. Notably, 2425fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * the low bits tend to have periodicity. 2426fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath */ 2427fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath state->seed = ((state->seed) * 1103515245 + 12345) & 0x7fffffff; 2428fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return (ev_int32_t)(state->seed); 2429fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath} 2430fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 2431fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathev_int32_t 2432fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathevutil_weakrand_range_(struct evutil_weakrand_state *state, ev_int32_t top) 2433fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath{ 2434fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath ev_int32_t divisor, result; 2435fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 2436fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath /* We can't just do weakrand() % top, since the low bits of the LCG 2437fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * are less random than the high ones. (Specifically, since the LCG 2438fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * modulus is 2^N, every 2^m for m<N will divide the modulus, and so 2439fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * therefore the low m bits of the LCG will have period 2^m.) */ 2440fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath divisor = EVUTIL_WEAKRAND_MAX / top; 2441fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath do { 2442fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath result = evutil_weakrand_(state) / divisor; 2443fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } while (result >= top); 2444fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return result; 2445e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 2446e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 2447e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/** 2448e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * Volatile pointer to memset: we use this to keep the compiler from 2449e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * eliminating our call to memset. 2450e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley */ 2451e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyvoid * (*volatile evutil_memset_volatile_)(void *, int, size_t) = memset; 2452e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 2453e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyvoid 2454e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevutil_memclear_(void *mem, size_t len) 2455e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 2456e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley evutil_memset_volatile_(mem, 0, len); 2457e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 2458e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 2459e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyint 2460fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathevutil_sockaddr_is_loopback_(const struct sockaddr *addr) 2461e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 2462e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley static const char LOOPBACK_S6[16] = 2463e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1"; 2464e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (addr->sa_family == AF_INET) { 2465e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct sockaddr_in *sin = (struct sockaddr_in *)addr; 2466e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return (ntohl(sin->sin_addr.s_addr) & 0xff000000) == 0x7f000000; 2467e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } else if (addr->sa_family == AF_INET6) { 2468e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr; 2469e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return !memcmp(sin6->sin6_addr.s6_addr, LOOPBACK_S6, 16); 2470e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 2471e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 2472e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 2473e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 2474e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyint 2475fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathevutil_hex_char_to_int_(char c) 2476e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 2477e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley switch(c) 2478e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley { 2479e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case '0': return 0; 2480e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case '1': return 1; 2481e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case '2': return 2; 2482e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case '3': return 3; 2483e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case '4': return 4; 2484e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case '5': return 5; 2485e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case '6': return 6; 2486e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case '7': return 7; 2487e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case '8': return 8; 2488e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case '9': return 9; 2489e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case 'A': case 'a': return 10; 2490e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case 'B': case 'b': return 11; 2491e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case 'C': case 'c': return 12; 2492e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case 'D': case 'd': return 13; 2493e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case 'E': case 'e': return 14; 2494e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley case 'F': case 'f': return 15; 2495e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley } 2496e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return -1; 2497e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 2498e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 2499fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifdef _WIN32 2500fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan KamathHMODULE 2501fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathevutil_load_windows_system_library_(const TCHAR *library_name) 2502e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{ 2503e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley TCHAR path[MAX_PATH]; 2504e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley unsigned n; 2505e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley n = GetSystemDirectory(path, MAX_PATH); 2506e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley if (n == 0 || n + _tcslen(library_name) + 2 >= MAX_PATH) 2507e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return 0; 2508e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley _tcscat(path, TEXT("\\")); 2509e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley _tcscat(path, library_name); 2510e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley return LoadLibrary(path); 2511e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley} 2512e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif 2513e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley 2514fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath/* Internal wrapper around 'socket' to provide Linux-style support for 2515fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * syscall-saving methods where available. 2516fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * 2517fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * In addition to regular socket behavior, you can use a bitwise or to set the 2518fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * flags EVUTIL_SOCK_NONBLOCK and EVUTIL_SOCK_CLOEXEC in the 'type' argument, 2519fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * to make the socket nonblocking or close-on-exec with as few syscalls as 2520fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * possible. 2521fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath */ 2522fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathevutil_socket_t 2523fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathevutil_socket_(int domain, int type, int protocol) 2524fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath{ 2525fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath evutil_socket_t r; 2526fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC) 2527fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath r = socket(domain, type, protocol); 2528fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (r >= 0) 2529fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return r; 2530fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath else if ((type & (SOCK_NONBLOCK|SOCK_CLOEXEC)) == 0) 2531fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return -1; 2532fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#endif 2533fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#define SOCKET_TYPE_MASK (~(EVUTIL_SOCK_NONBLOCK|EVUTIL_SOCK_CLOEXEC)) 2534fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath r = socket(domain, type & SOCKET_TYPE_MASK, protocol); 2535fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (r < 0) 2536fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return -1; 2537fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (type & EVUTIL_SOCK_NONBLOCK) { 2538fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (evutil_fast_socket_nonblocking(r) < 0) { 2539fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath evutil_closesocket(r); 2540fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return -1; 2541fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 2542fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 2543fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (type & EVUTIL_SOCK_CLOEXEC) { 2544fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (evutil_fast_socket_closeonexec(r) < 0) { 2545fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath evutil_closesocket(r); 2546fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return -1; 2547fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 2548fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 2549fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return r; 2550fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath} 2551fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 2552fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath/* Internal wrapper around 'accept' or 'accept4' to provide Linux-style 2553fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * support for syscall-saving methods where available. 2554fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * 2555fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * In addition to regular accept behavior, you can set one or more of flags 2556fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * EVUTIL_SOCK_NONBLOCK and EVUTIL_SOCK_CLOEXEC in the 'flags' argument, to 2557fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * make the socket nonblocking or close-on-exec with as few syscalls as 2558fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * possible. 2559fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath */ 2560fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathevutil_socket_t 2561fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathevutil_accept4_(evutil_socket_t sockfd, struct sockaddr *addr, 2562fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath ev_socklen_t *addrlen, int flags) 2563fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath{ 2564fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath evutil_socket_t result; 2565fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#if defined(EVENT__HAVE_ACCEPT4) && defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK) 2566fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath result = accept4(sockfd, addr, addrlen, flags); 2567fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (result >= 0 || (errno != EINVAL && errno != ENOSYS)) { 2568fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath /* A nonnegative result means that we succeeded, so return. 2569fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * Failing with EINVAL means that an option wasn't supported, 2570fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * and failing with ENOSYS means that the syscall wasn't 2571fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * there: in those cases we want to fall back. Otherwise, we 2572fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * got a real error, and we should return. */ 2573fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return result; 2574fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 2575fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#endif 2576fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath result = accept(sockfd, addr, addrlen); 2577fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (result < 0) 2578fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return result; 2579fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 2580fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (flags & EVUTIL_SOCK_CLOEXEC) { 2581fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (evutil_fast_socket_closeonexec(result) < 0) { 2582fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath evutil_closesocket(result); 2583fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return -1; 2584fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 2585fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 2586fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (flags & EVUTIL_SOCK_NONBLOCK) { 2587fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (evutil_fast_socket_nonblocking(result) < 0) { 2588fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath evutil_closesocket(result); 2589fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return -1; 2590fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 2591fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 2592fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return result; 2593fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath} 2594fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 2595fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath/* Internal function: Set fd[0] and fd[1] to a pair of fds such that writes on 2596fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * fd[0] get read from fd[1]. Make both fds nonblocking and close-on-exec. 2597fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * Return 0 on success, -1 on failure. 2598fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath */ 2599fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathint 2600fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathevutil_make_internal_pipe_(evutil_socket_t fd[2]) 2601fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath{ 2602fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath /* 2603fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath Making the second socket nonblocking is a bit subtle, given that we 2604fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath ignore any EAGAIN returns when writing to it, and you don't usally 2605fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath do that for a nonblocking socket. But if the kernel gives us EAGAIN, 2606fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath then there's no need to add any more data to the buffer, since 2607fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath the main thread is already either about to wake up and drain it, 2608fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath or woken up and in the process of draining it. 2609fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath */ 2610fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 2611fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#if defined(EVENT__HAVE_PIPE2) 2612fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (pipe2(fd, O_NONBLOCK|O_CLOEXEC) == 0) 2613fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return 0; 2614fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#endif 2615fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#if defined(EVENT__HAVE_PIPE) 2616fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (pipe(fd) == 0) { 2617fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (evutil_fast_socket_nonblocking(fd[0]) < 0 || 2618fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath evutil_fast_socket_nonblocking(fd[1]) < 0 || 2619fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath evutil_fast_socket_closeonexec(fd[0]) < 0 || 2620fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath evutil_fast_socket_closeonexec(fd[1]) < 0) { 2621fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath close(fd[0]); 2622fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath close(fd[1]); 2623fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath fd[0] = fd[1] = -1; 2624fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return -1; 2625fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 2626fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return 0; 2627fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } else { 2628fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath event_warn("%s: pipe", __func__); 2629fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 2630fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#endif 2631fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 2632fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#ifdef _WIN32 2633fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#define LOCAL_SOCKETPAIR_AF AF_INET 2634fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#else 2635fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#define LOCAL_SOCKETPAIR_AF AF_UNIX 2636fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#endif 2637fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (evutil_socketpair(LOCAL_SOCKETPAIR_AF, SOCK_STREAM, 0, fd) == 0) { 2638fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (evutil_fast_socket_nonblocking(fd[0]) < 0 || 2639fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath evutil_fast_socket_nonblocking(fd[1]) < 0 || 2640fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath evutil_fast_socket_closeonexec(fd[0]) < 0 || 2641fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath evutil_fast_socket_closeonexec(fd[1]) < 0) { 2642fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath evutil_closesocket(fd[0]); 2643fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath evutil_closesocket(fd[1]); 2644fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath fd[0] = fd[1] = -1; 2645fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return -1; 2646fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 2647fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return 0; 2648fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 2649fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath fd[0] = fd[1] = -1; 2650fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return -1; 2651fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath} 2652fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 2653fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath/* Wrapper around eventfd on systems that provide it. Unlike the system 2654fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * eventfd, it always supports EVUTIL_EFD_CLOEXEC and EVUTIL_EFD_NONBLOCK as 2655fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath * flags. Returns -1 on error or if eventfd is not supported. 2656fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath */ 2657fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathevutil_socket_t 2658fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathevutil_eventfd_(unsigned initval, int flags) 2659fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath{ 2660fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#if defined(EVENT__HAVE_EVENTFD) && defined(EVENT__HAVE_SYS_EVENTFD_H) 2661fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath int r; 2662fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#if defined(EFD_CLOEXEC) && defined(EFD_NONBLOCK) 2663fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath r = eventfd(initval, flags); 2664fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (r >= 0 || flags == 0) 2665fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return r; 2666fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#endif 2667fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath r = eventfd(initval, 0); 2668fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (r < 0) 2669fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return r; 2670fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (flags & EVUTIL_EFD_CLOEXEC) { 2671fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (evutil_fast_socket_closeonexec(r) < 0) { 2672fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath evutil_closesocket(r); 2673fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return -1; 2674fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 2675fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 2676fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (flags & EVUTIL_EFD_NONBLOCK) { 2677fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath if (evutil_fast_socket_nonblocking(r) < 0) { 2678fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath evutil_closesocket(r); 2679fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return -1; 2680fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 2681fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath } 2682fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return r; 2683fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#else 2684fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath return -1; 2685fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath#endif 2686fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath} 2687fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath 2688fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathvoid 2689fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamathevutil_free_globals_(void) 2690fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath{ 2691fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath evutil_free_secure_rng_globals_(); 2692fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath evutil_free_sock_err_globals(); 2693fc74cb45eafe51162b10a850016c6d2e1f8fd23cNarayan Kamath} 2694