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