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