Blame libevent/evutil.c

Packit e9ba0d
/*
Packit e9ba0d
 * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
Packit e9ba0d
 *
Packit e9ba0d
 * Redistribution and use in source and binary forms, with or without
Packit e9ba0d
 * modification, are permitted provided that the following conditions
Packit e9ba0d
 * are met:
Packit e9ba0d
 * 1. Redistributions of source code must retain the above copyright
Packit e9ba0d
 *    notice, this list of conditions and the following disclaimer.
Packit e9ba0d
 * 2. Redistributions in binary form must reproduce the above copyright
Packit e9ba0d
 *    notice, this list of conditions and the following disclaimer in the
Packit e9ba0d
 *    documentation and/or other materials provided with the distribution.
Packit e9ba0d
 * 3. The name of the author may not be used to endorse or promote products
Packit e9ba0d
 *    derived from this software without specific prior written permission.
Packit e9ba0d
 *
Packit e9ba0d
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
Packit e9ba0d
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
Packit e9ba0d
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
Packit e9ba0d
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
Packit e9ba0d
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
Packit e9ba0d
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Packit e9ba0d
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Packit e9ba0d
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Packit e9ba0d
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
Packit e9ba0d
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit e9ba0d
 */
Packit e9ba0d
Packit e9ba0d
#include "event2/event-config.h"
Packit e9ba0d
Packit e9ba0d
#define _GNU_SOURCE
Packit e9ba0d
Packit e9ba0d
#ifdef WIN32
Packit e9ba0d
#include <winsock2.h>
Packit e9ba0d
#include <ws2tcpip.h>
Packit e9ba0d
#define WIN32_LEAN_AND_MEAN
Packit e9ba0d
#include <windows.h>
Packit e9ba0d
#undef WIN32_LEAN_AND_MEAN
Packit e9ba0d
#include <io.h>
Packit e9ba0d
#include <tchar.h>
Packit e9ba0d
#endif
Packit e9ba0d
Packit e9ba0d
#include <sys/types.h>
Packit e9ba0d
#ifdef _EVENT_HAVE_SYS_SOCKET_H
Packit e9ba0d
#include <sys/socket.h>
Packit e9ba0d
#endif
Packit e9ba0d
#ifdef _EVENT_HAVE_UNISTD_H
Packit e9ba0d
#include <unistd.h>
Packit e9ba0d
#endif
Packit e9ba0d
#ifdef _EVENT_HAVE_FCNTL_H
Packit e9ba0d
#include <fcntl.h>
Packit e9ba0d
#endif
Packit e9ba0d
#ifdef _EVENT_HAVE_STDLIB_H
Packit e9ba0d
#include <stdlib.h>
Packit e9ba0d
#endif
Packit e9ba0d
#include <errno.h>
Packit e9ba0d
#include <limits.h>
Packit e9ba0d
#include <stdio.h>
Packit e9ba0d
#include <string.h>
Packit e9ba0d
#ifdef _EVENT_HAVE_NETINET_IN_H
Packit e9ba0d
#include <netinet/in.h>
Packit e9ba0d
#endif
Packit e9ba0d
#ifdef _EVENT_HAVE_NETINET_IN6_H
Packit e9ba0d
#include <netinet/in6.h>
Packit e9ba0d
#endif
Packit e9ba0d
#ifdef _EVENT_HAVE_ARPA_INET_H
Packit e9ba0d
#include <arpa/inet.h>
Packit e9ba0d
#endif
Packit e9ba0d
Packit e9ba0d
#ifndef _EVENT_HAVE_GETTIMEOFDAY
Packit e9ba0d
#include <sys/timeb.h>
Packit e9ba0d
#include <time.h>
Packit e9ba0d
#endif
Packit e9ba0d
#include <sys/stat.h>
Packit e9ba0d
Packit e9ba0d
#include "event2/util.h"
Packit e9ba0d
#include "util-internal.h"
Packit e9ba0d
#include "log-internal.h"
Packit e9ba0d
#include "mm-internal.h"
Packit e9ba0d
Packit e9ba0d
#include "strlcpy-internal.h"
Packit e9ba0d
#include "ipv6-internal.h"
Packit e9ba0d
Packit e9ba0d
#ifdef WIN32
Packit e9ba0d
#define open _open
Packit e9ba0d
#define read _read
Packit e9ba0d
#define close _close
Packit e9ba0d
#define fstat _fstati64
Packit e9ba0d
#define stat _stati64
Packit e9ba0d
#define mode_t int
Packit e9ba0d
#endif
Packit e9ba0d
Packit e9ba0d
int
Packit e9ba0d
evutil_open_closeonexec(const char *pathname, int flags, unsigned mode)
Packit e9ba0d
{
Packit e9ba0d
	int fd;
Packit e9ba0d
Packit e9ba0d
#ifdef O_CLOEXEC
Packit e9ba0d
	flags |= O_CLOEXEC;
Packit e9ba0d
#endif
Packit e9ba0d
Packit e9ba0d
	if (flags & O_CREAT)
Packit e9ba0d
		fd = open(pathname, flags, (mode_t)mode);
Packit e9ba0d
	else
Packit e9ba0d
		fd = open(pathname, flags);
Packit e9ba0d
	if (fd < 0)
Packit e9ba0d
		return -1;
Packit e9ba0d
Packit e9ba0d
#if !defined(O_CLOEXEC) && defined(FD_CLOEXEC)
Packit e9ba0d
	if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0)
Packit e9ba0d
		return -1;
Packit e9ba0d
#endif
Packit e9ba0d
Packit e9ba0d
	return fd;
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
/**
Packit e9ba0d
   Read the contents of 'filename' into a newly allocated NUL-terminated
Packit e9ba0d
   string.  Set *content_out to hold this string, and *len_out to hold its
Packit e9ba0d
   length (not including the appended NUL).  If 'is_binary', open the file in
Packit e9ba0d
   binary mode.
Packit e9ba0d
Packit e9ba0d
   Returns 0 on success, -1 if the open fails, and -2 for all other failures.
Packit e9ba0d
Packit e9ba0d
   Used internally only; may go away in a future version.
Packit e9ba0d
 */
Packit e9ba0d
int
Packit e9ba0d
evutil_read_file(const char *filename, char **content_out, size_t *len_out,
Packit e9ba0d
    int is_binary)
Packit e9ba0d
{
Packit e9ba0d
	int fd, r;
Packit e9ba0d
	struct stat st;
Packit e9ba0d
	char *mem;
Packit e9ba0d
	size_t read_so_far=0;
Packit e9ba0d
	int mode = O_RDONLY;
Packit e9ba0d
Packit e9ba0d
	EVUTIL_ASSERT(content_out);
Packit e9ba0d
	EVUTIL_ASSERT(len_out);
Packit e9ba0d
	*content_out = NULL;
Packit e9ba0d
	*len_out = 0;
Packit e9ba0d
Packit e9ba0d
#ifdef O_BINARY
Packit e9ba0d
	if (is_binary)
Packit e9ba0d
		mode |= O_BINARY;
Packit e9ba0d
#endif
Packit e9ba0d
Packit e9ba0d
	fd = evutil_open_closeonexec(filename, mode, 0);
Packit e9ba0d
	if (fd < 0)
Packit e9ba0d
		return -1;
Packit e9ba0d
	if (fstat(fd, &st) || st.st_size < 0 ||
Packit e9ba0d
	    st.st_size > EV_SSIZE_MAX-1 ) {
Packit e9ba0d
		close(fd);
Packit e9ba0d
		return -2;
Packit e9ba0d
	}
Packit e9ba0d
	mem = mm_malloc((size_t)st.st_size + 1);
Packit e9ba0d
	if (!mem) {
Packit e9ba0d
		close(fd);
Packit e9ba0d
		return -2;
Packit e9ba0d
	}
Packit e9ba0d
	read_so_far = 0;
Packit e9ba0d
#ifdef WIN32
Packit e9ba0d
#define N_TO_READ(x) ((x) > INT_MAX) ? INT_MAX : ((int)(x))
Packit e9ba0d
#else
Packit e9ba0d
#define N_TO_READ(x) (x)
Packit e9ba0d
#endif
Packit e9ba0d
	while ((r = read(fd, mem+read_so_far, N_TO_READ(st.st_size - read_so_far))) > 0) {
Packit e9ba0d
		read_so_far += r;
Packit e9ba0d
		if (read_so_far >= (size_t)st.st_size)
Packit e9ba0d
			break;
Packit e9ba0d
		EVUTIL_ASSERT(read_so_far < (size_t)st.st_size);
Packit e9ba0d
	}
Packit e9ba0d
	close(fd);
Packit e9ba0d
	if (r < 0) {
Packit e9ba0d
		mm_free(mem);
Packit e9ba0d
		return -2;
Packit e9ba0d
	}
Packit e9ba0d
	mem[read_so_far] = 0;
Packit e9ba0d
Packit e9ba0d
	*len_out = read_so_far;
Packit e9ba0d
	*content_out = mem;
Packit e9ba0d
	return 0;
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
int
Packit e9ba0d
evutil_socketpair(int family, int type, int protocol, evutil_socket_t fd[2])
Packit e9ba0d
{
Packit e9ba0d
#ifndef WIN32
Packit e9ba0d
	return socketpair(family, type, protocol, fd);
Packit e9ba0d
#else
Packit e9ba0d
	return evutil_ersatz_socketpair(family, type, protocol, fd);
Packit e9ba0d
#endif
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
int
Packit e9ba0d
evutil_ersatz_socketpair(int family, int type, int protocol,
Packit e9ba0d
    evutil_socket_t fd[2])
Packit e9ba0d
{
Packit e9ba0d
	/* This code is originally from Tor.  Used with permission. */
Packit e9ba0d
Packit e9ba0d
	/* This socketpair does not work when localhost is down. So
Packit e9ba0d
	 * it's really not the same thing at all. But it's close enough
Packit e9ba0d
	 * for now, and really, when localhost is down sometimes, we
Packit e9ba0d
	 * have other problems too.
Packit e9ba0d
	 */
Packit e9ba0d
#ifdef WIN32
Packit e9ba0d
#define ERR(e) WSA##e
Packit e9ba0d
#else
Packit e9ba0d
#define ERR(e) e
Packit e9ba0d
#endif
Packit e9ba0d
	evutil_socket_t listener = -1;
Packit e9ba0d
	evutil_socket_t connector = -1;
Packit e9ba0d
	evutil_socket_t acceptor = -1;
Packit e9ba0d
	struct sockaddr_in listen_addr;
Packit e9ba0d
	struct sockaddr_in connect_addr;
Packit e9ba0d
	ev_socklen_t size;
Packit e9ba0d
	int saved_errno = -1;
Packit e9ba0d
Packit e9ba0d
	if (protocol
Packit e9ba0d
		|| (family != AF_INET
Packit e9ba0d
#ifdef AF_UNIX
Packit e9ba0d
		    && family != AF_UNIX
Packit e9ba0d
#endif
Packit e9ba0d
		)) {
Packit e9ba0d
		EVUTIL_SET_SOCKET_ERROR(ERR(EAFNOSUPPORT));
Packit e9ba0d
		return -1;
Packit e9ba0d
	}
Packit e9ba0d
	if (!fd) {
Packit e9ba0d
		EVUTIL_SET_SOCKET_ERROR(ERR(EINVAL));
Packit e9ba0d
		return -1;
Packit e9ba0d
	}
Packit e9ba0d
Packit e9ba0d
	listener = socket(AF_INET, type, 0);
Packit e9ba0d
	if (listener < 0)
Packit e9ba0d
		return -1;
Packit e9ba0d
	memset(&listen_addr, 0, sizeof(listen_addr));
Packit e9ba0d
	listen_addr.sin_family = AF_INET;
Packit e9ba0d
	listen_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
Packit e9ba0d
	listen_addr.sin_port = 0;	/* kernel chooses port.	 */
Packit e9ba0d
	if (bind(listener, (struct sockaddr *) &listen_addr, sizeof (listen_addr))
Packit e9ba0d
		== -1)
Packit e9ba0d
		goto tidy_up_and_fail;
Packit e9ba0d
	if (listen(listener, 1) == -1)
Packit e9ba0d
		goto tidy_up_and_fail;
Packit e9ba0d
Packit e9ba0d
	connector = socket(AF_INET, type, 0);
Packit e9ba0d
	if (connector < 0)
Packit e9ba0d
		goto tidy_up_and_fail;
Packit e9ba0d
	/* We want to find out the port number to connect to.  */
Packit e9ba0d
	size = sizeof(connect_addr);
Packit e9ba0d
	if (getsockname(listener, (struct sockaddr *) &connect_addr, &size) == -1)
Packit e9ba0d
		goto tidy_up_and_fail;
Packit e9ba0d
	if (size != sizeof (connect_addr))
Packit e9ba0d
		goto abort_tidy_up_and_fail;
Packit e9ba0d
	if (connect(connector, (struct sockaddr *) &connect_addr,
Packit e9ba0d
				sizeof(connect_addr)) == -1)
Packit e9ba0d
		goto tidy_up_and_fail;
Packit e9ba0d
Packit e9ba0d
	size = sizeof(listen_addr);
Packit e9ba0d
	acceptor = accept(listener, (struct sockaddr *) &listen_addr, &size);
Packit e9ba0d
	if (acceptor < 0)
Packit e9ba0d
		goto tidy_up_and_fail;
Packit e9ba0d
	if (size != sizeof(listen_addr))
Packit e9ba0d
		goto abort_tidy_up_and_fail;
Packit e9ba0d
	/* Now check we are talking to ourself by matching port and host on the
Packit e9ba0d
	   two sockets.	 */
Packit e9ba0d
	if (getsockname(connector, (struct sockaddr *) &connect_addr, &size) == -1)
Packit e9ba0d
		goto tidy_up_and_fail;
Packit e9ba0d
	if (size != sizeof (connect_addr)
Packit e9ba0d
		|| listen_addr.sin_family != connect_addr.sin_family
Packit e9ba0d
		|| listen_addr.sin_addr.s_addr != connect_addr.sin_addr.s_addr
Packit e9ba0d
		|| listen_addr.sin_port != connect_addr.sin_port)
Packit e9ba0d
		goto abort_tidy_up_and_fail;
Packit e9ba0d
	evutil_closesocket(listener);
Packit e9ba0d
	fd[0] = connector;
Packit e9ba0d
	fd[1] = acceptor;
Packit e9ba0d
Packit e9ba0d
	return 0;
Packit e9ba0d
Packit e9ba0d
 abort_tidy_up_and_fail:
Packit e9ba0d
	saved_errno = ERR(ECONNABORTED);
Packit e9ba0d
 tidy_up_and_fail:
Packit e9ba0d
	if (saved_errno < 0)
Packit e9ba0d
		saved_errno = EVUTIL_SOCKET_ERROR();
Packit e9ba0d
	if (listener != -1)
Packit e9ba0d
		evutil_closesocket(listener);
Packit e9ba0d
	if (connector != -1)
Packit e9ba0d
		evutil_closesocket(connector);
Packit e9ba0d
	if (acceptor != -1)
Packit e9ba0d
		evutil_closesocket(acceptor);
Packit e9ba0d
Packit e9ba0d
	EVUTIL_SET_SOCKET_ERROR(saved_errno);
Packit e9ba0d
	return -1;
Packit e9ba0d
#undef ERR
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
int
Packit e9ba0d
evutil_make_socket_nonblocking(evutil_socket_t fd)
Packit e9ba0d
{
Packit e9ba0d
#ifdef WIN32
Packit e9ba0d
	{
Packit e9ba0d
		u_long nonblocking = 1;
Packit e9ba0d
		if (ioctlsocket(fd, FIONBIO, &nonblocking) == SOCKET_ERROR) {
Packit e9ba0d
			event_sock_warn(fd, "fcntl(%d, F_GETFL)", (int)fd);
Packit e9ba0d
			return -1;
Packit e9ba0d
		}
Packit e9ba0d
	}
Packit e9ba0d
#else
Packit e9ba0d
	{
Packit e9ba0d
		int flags;
Packit e9ba0d
		if ((flags = fcntl(fd, F_GETFL, NULL)) < 0) {
Packit e9ba0d
			event_warn("fcntl(%d, F_GETFL)", fd);
Packit e9ba0d
			return -1;
Packit e9ba0d
		}
Packit e9ba0d
		if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
Packit e9ba0d
			event_warn("fcntl(%d, F_SETFL)", fd);
Packit e9ba0d
			return -1;
Packit e9ba0d
		}
Packit e9ba0d
	}
Packit e9ba0d
#endif
Packit e9ba0d
	return 0;
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
int
Packit e9ba0d
evutil_make_listen_socket_reuseable(evutil_socket_t sock)
Packit e9ba0d
{
Packit e9ba0d
#ifndef WIN32
Packit e9ba0d
	int one = 1;
Packit e9ba0d
	/* REUSEADDR on Unix means, "don't hang on to this address after the
Packit e9ba0d
	 * listener is closed."  On Windows, though, it means "don't keep other
Packit e9ba0d
	 * processes from binding to this address while we're using it. */
Packit e9ba0d
	return setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*) &one,
Packit e9ba0d
	    (ev_socklen_t)sizeof(one));
Packit e9ba0d
#else
Packit e9ba0d
	return 0;
Packit e9ba0d
#endif
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
int
Packit e9ba0d
evutil_make_socket_closeonexec(evutil_socket_t fd)
Packit e9ba0d
{
Packit e9ba0d
#if !defined(WIN32) && defined(_EVENT_HAVE_SETFD)
Packit e9ba0d
	int flags;
Packit e9ba0d
	if ((flags = fcntl(fd, F_GETFD, NULL)) < 0) {
Packit e9ba0d
		event_warn("fcntl(%d, F_GETFD)", fd);
Packit e9ba0d
		return -1;
Packit e9ba0d
	}
Packit e9ba0d
	if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) {
Packit e9ba0d
		event_warn("fcntl(%d, F_SETFD)", fd);
Packit e9ba0d
		return -1;
Packit e9ba0d
	}
Packit e9ba0d
#endif
Packit e9ba0d
	return 0;
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
int
Packit e9ba0d
evutil_closesocket(evutil_socket_t sock)
Packit e9ba0d
{
Packit e9ba0d
#ifndef WIN32
Packit e9ba0d
	return close(sock);
Packit e9ba0d
#else
Packit e9ba0d
	return closesocket(sock);
Packit e9ba0d
#endif
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
ev_int64_t
Packit e9ba0d
evutil_strtoll(const char *s, char **endptr, int base)
Packit e9ba0d
{
Packit e9ba0d
#ifdef _EVENT_HAVE_STRTOLL
Packit e9ba0d
	return (ev_int64_t)strtoll(s, endptr, base);
Packit e9ba0d
#elif _EVENT_SIZEOF_LONG == 8
Packit e9ba0d
	return (ev_int64_t)strtol(s, endptr, base);
Packit e9ba0d
#elif defined(WIN32) && defined(_MSC_VER) && _MSC_VER < 1300
Packit e9ba0d
	/* XXXX on old versions of MS APIs, we only support base
Packit e9ba0d
	 * 10. */
Packit e9ba0d
	ev_int64_t r;
Packit e9ba0d
	if (base != 10)
Packit e9ba0d
		return 0;
Packit e9ba0d
	r = (ev_int64_t) _atoi64(s);
Packit e9ba0d
	while (isspace(*s))
Packit e9ba0d
		++s;
Packit e9ba0d
	if (*s == '-')
Packit e9ba0d
		++s;
Packit e9ba0d
	while (isdigit(*s))
Packit e9ba0d
		++s;
Packit e9ba0d
	if (endptr)
Packit e9ba0d
		*endptr = (char*) s;
Packit e9ba0d
	return r;
Packit e9ba0d
#elif defined(WIN32)
Packit e9ba0d
	return (ev_int64_t) _strtoi64(s, endptr, base);
Packit e9ba0d
#elif defined(_EVENT_SIZEOF_LONG_LONG) && _EVENT_SIZEOF_LONG_LONG == 8
Packit e9ba0d
	long long r;
Packit e9ba0d
	int n;
Packit e9ba0d
	if (base != 10 && base != 16)
Packit e9ba0d
		return 0;
Packit e9ba0d
	if (base == 10) {
Packit e9ba0d
		n = sscanf(s, "%lld", &r);
Packit e9ba0d
	} else {
Packit e9ba0d
		unsigned long long ru=0;
Packit e9ba0d
		n = sscanf(s, "%llx", &ru);
Packit e9ba0d
		if (ru > EV_INT64_MAX)
Packit e9ba0d
			return 0;
Packit e9ba0d
		r = (long long) ru;
Packit e9ba0d
	}
Packit e9ba0d
	if (n != 1)
Packit e9ba0d
		return 0;
Packit e9ba0d
	while (EVUTIL_ISSPACE(*s))
Packit e9ba0d
		++s;
Packit e9ba0d
	if (*s == '-')
Packit e9ba0d
		++s;
Packit e9ba0d
	if (base == 10) {
Packit e9ba0d
		while (EVUTIL_ISDIGIT(*s))
Packit e9ba0d
			++s;
Packit e9ba0d
	} else {
Packit e9ba0d
		while (EVUTIL_ISXDIGIT(*s))
Packit e9ba0d
			++s;
Packit e9ba0d
	}
Packit e9ba0d
	if (endptr)
Packit e9ba0d
		*endptr = (char*) s;
Packit e9ba0d
	return r;
Packit e9ba0d
#else
Packit e9ba0d
#error "I don't know how to parse 64-bit integers."
Packit e9ba0d
#endif
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
#ifndef _EVENT_HAVE_GETTIMEOFDAY
Packit e9ba0d
/* No gettimeofday; this muse be windows. */
Packit e9ba0d
int
Packit e9ba0d
evutil_gettimeofday(struct timeval *tv, struct timezone *tz)
Packit e9ba0d
{
Packit e9ba0d
	struct _timeb tb;
Packit e9ba0d
Packit e9ba0d
	if (tv == NULL)
Packit e9ba0d
		return -1;
Packit e9ba0d
Packit e9ba0d
	/* XXXX
Packit e9ba0d
	 * _ftime is not the greatest interface here; GetSystemTimeAsFileTime
Packit e9ba0d
	 * would give us better resolution, whereas something cobbled together
Packit e9ba0d
	 * with GetTickCount could maybe give us monotonic behavior.
Packit e9ba0d
	 *
Packit e9ba0d
	 * Either way, I think this value might be skewed to ignore the
Packit e9ba0d
	 * timezone, and just return local time.  That's not so good.
Packit e9ba0d
	 */
Packit e9ba0d
	_ftime(&tb);
Packit e9ba0d
	tv->tv_sec = (long) tb.time;
Packit e9ba0d
	tv->tv_usec = ((int) tb.millitm) * 1000;
Packit e9ba0d
	return 0;
Packit e9ba0d
}
Packit e9ba0d
#endif
Packit e9ba0d
Packit e9ba0d
#ifdef WIN32
Packit e9ba0d
int
Packit e9ba0d
evutil_socket_geterror(evutil_socket_t sock)
Packit e9ba0d
{
Packit e9ba0d
	int optval, optvallen=sizeof(optval);
Packit e9ba0d
	int err = WSAGetLastError();
Packit e9ba0d
	if (err == WSAEWOULDBLOCK && sock >= 0) {
Packit e9ba0d
		if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)&optval,
Packit e9ba0d
					   &optvallen))
Packit e9ba0d
			return err;
Packit e9ba0d
		if (optval)
Packit e9ba0d
			return optval;
Packit e9ba0d
	}
Packit e9ba0d
	return err;
Packit e9ba0d
}
Packit e9ba0d
#endif
Packit e9ba0d
Packit e9ba0d
/* XXX we should use an enum here. */
Packit e9ba0d
/* 2 for connection refused, 1 for connected, 0 for not yet, -1 for error. */
Packit e9ba0d
int
Packit e9ba0d
evutil_socket_connect(evutil_socket_t *fd_ptr, struct sockaddr *sa, int socklen)
Packit e9ba0d
{
Packit e9ba0d
	int made_fd = 0;
Packit e9ba0d
Packit e9ba0d
	if (*fd_ptr < 0) {
Packit e9ba0d
		if ((*fd_ptr = socket(sa->sa_family, SOCK_STREAM, 0)) < 0)
Packit e9ba0d
			goto err;
Packit e9ba0d
		made_fd = 1;
Packit e9ba0d
		if (evutil_make_socket_nonblocking(*fd_ptr) < 0) {
Packit e9ba0d
			goto err;
Packit e9ba0d
		}
Packit e9ba0d
	}
Packit e9ba0d
Packit e9ba0d
	if (connect(*fd_ptr, sa, socklen) < 0) {
Packit e9ba0d
		int e = evutil_socket_geterror(*fd_ptr);
Packit e9ba0d
		if (EVUTIL_ERR_CONNECT_RETRIABLE(e))
Packit e9ba0d
			return 0;
Packit e9ba0d
		if (EVUTIL_ERR_CONNECT_REFUSED(e))
Packit e9ba0d
			return 2;
Packit e9ba0d
		goto err;
Packit e9ba0d
	} else {
Packit e9ba0d
		return 1;
Packit e9ba0d
	}
Packit e9ba0d
Packit e9ba0d
err:
Packit e9ba0d
	if (made_fd) {
Packit e9ba0d
		evutil_closesocket(*fd_ptr);
Packit e9ba0d
		*fd_ptr = -1;
Packit e9ba0d
	}
Packit e9ba0d
	return -1;
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
/* Check whether a socket on which we called connect() is done
Packit e9ba0d
   connecting. Return 1 for connected, 0 for not yet, -1 for error.  In the
Packit e9ba0d
   error case, set the current socket errno to the error that happened during
Packit e9ba0d
   the connect operation. */
Packit e9ba0d
int
Packit e9ba0d
evutil_socket_finished_connecting(evutil_socket_t fd)
Packit e9ba0d
{
Packit e9ba0d
	int e;
Packit e9ba0d
	ev_socklen_t elen = sizeof(e);
Packit e9ba0d
Packit e9ba0d
	if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&e, &elen) < 0)
Packit e9ba0d
		return -1;
Packit e9ba0d
Packit e9ba0d
	if (e) {
Packit e9ba0d
		if (EVUTIL_ERR_CONNECT_RETRIABLE(e))
Packit e9ba0d
			return 0;
Packit e9ba0d
		EVUTIL_SET_SOCKET_ERROR(e);
Packit e9ba0d
		return -1;
Packit e9ba0d
	}
Packit e9ba0d
Packit e9ba0d
	return 1;
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
#if (EVUTIL_AI_PASSIVE|EVUTIL_AI_CANONNAME|EVUTIL_AI_NUMERICHOST| \
Packit e9ba0d
     EVUTIL_AI_NUMERICSERV|EVUTIL_AI_V4MAPPED|EVUTIL_AI_ALL| \
Packit e9ba0d
     EVUTIL_AI_ADDRCONFIG) != \
Packit e9ba0d
    (EVUTIL_AI_PASSIVE^EVUTIL_AI_CANONNAME^EVUTIL_AI_NUMERICHOST^ \
Packit e9ba0d
     EVUTIL_AI_NUMERICSERV^EVUTIL_AI_V4MAPPED^EVUTIL_AI_ALL^ \
Packit e9ba0d
     EVUTIL_AI_ADDRCONFIG)
Packit e9ba0d
#error "Some of our EVUTIL_AI_* flags seem to overlap with system AI_* flags"
Packit e9ba0d
#endif
Packit e9ba0d
Packit e9ba0d
/* We sometimes need to know whether we have an ipv4 address and whether we
Packit e9ba0d
   have an ipv6 address. If 'have_checked_interfaces', then we've already done
Packit e9ba0d
   the test.  If 'had_ipv4_address', then it turns out we had an ipv4 address.
Packit e9ba0d
   If 'had_ipv6_address', then it turns out we had an ipv6 address.   These are
Packit e9ba0d
   set by evutil_check_interfaces. */
Packit e9ba0d
static int have_checked_interfaces, had_ipv4_address, had_ipv6_address;
Packit e9ba0d
Packit e9ba0d
/* Macro: True iff the IPv4 address 'addr', in host order, is in 127.0.0.0/8
Packit e9ba0d
 */
Packit e9ba0d
#define EVUTIL_V4ADDR_IS_LOCALHOST(addr) (((addr)>>24) == 127)
Packit e9ba0d
Packit e9ba0d
/* Macro: True iff the IPv4 address 'addr', in host order, is a class D
Packit e9ba0d
 * (multiclass) address.
Packit e9ba0d
 */
Packit e9ba0d
#define EVUTIL_V4ADDR_IS_CLASSD(addr) ((((addr)>>24) & 0xf0) == 0xe0)
Packit e9ba0d
Packit e9ba0d
/* Test whether we have an ipv4 interface and an ipv6 interface.  Return 0 if
Packit e9ba0d
 * the test seemed successful. */
Packit e9ba0d
static int
Packit e9ba0d
evutil_check_interfaces(int force_recheck)
Packit e9ba0d
{
Packit e9ba0d
	const char ZEROES[] = "\x00\x00\x00\x00\x00\x00\x00\x00"
Packit e9ba0d
	    "\x00\x00\x00\x00\x00\x00\x00\x00";
Packit e9ba0d
	evutil_socket_t fd = -1;
Packit e9ba0d
	struct sockaddr_in sin, sin_out;
Packit e9ba0d
	struct sockaddr_in6 sin6, sin6_out;
Packit e9ba0d
	ev_socklen_t sin_out_len = sizeof(sin_out);
Packit e9ba0d
	ev_socklen_t sin6_out_len = sizeof(sin6_out);
Packit e9ba0d
	int r;
Packit e9ba0d
	char buf[128];
Packit e9ba0d
	if (have_checked_interfaces && !force_recheck)
Packit e9ba0d
		return 0;
Packit e9ba0d
Packit e9ba0d
	/* To check whether we have an interface open for a given protocol, we
Packit e9ba0d
	 * try to make a UDP 'connection' to a remote host on the internet.
Packit e9ba0d
	 * We don't actually use it, so the address doesn't matter, but we
Packit e9ba0d
	 * want to pick one that keep us from using a host- or link-local
Packit e9ba0d
	 * interface. */
Packit e9ba0d
	memset(&sin, 0, sizeof(sin));
Packit e9ba0d
	sin.sin_family = AF_INET;
Packit e9ba0d
	sin.sin_port = htons(53);
Packit e9ba0d
	r = evutil_inet_pton(AF_INET, "18.244.0.188", &sin.sin_addr);
Packit e9ba0d
	EVUTIL_ASSERT(r);
Packit e9ba0d
Packit e9ba0d
	memset(&sin6, 0, sizeof(sin6));
Packit e9ba0d
	sin6.sin6_family = AF_INET6;
Packit e9ba0d
	sin6.sin6_port = htons(53);
Packit e9ba0d
	r = evutil_inet_pton(AF_INET6, "2001:4860:b002::68", &sin6.sin6_addr);
Packit e9ba0d
	EVUTIL_ASSERT(r);
Packit e9ba0d
Packit e9ba0d
	memset(&sin_out, 0, sizeof(sin_out));
Packit e9ba0d
	memset(&sin6_out, 0, sizeof(sin6_out));
Packit e9ba0d
Packit e9ba0d
	/* XXX some errnos mean 'no address'; some mean 'not enough sockets'. */
Packit e9ba0d
	if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) >= 0 &&
Packit e9ba0d
	    connect(fd, (struct sockaddr*)&sin, sizeof(sin)) == 0 &&
Packit e9ba0d
	    getsockname(fd, (struct sockaddr*)&sin_out, &sin_out_len) == 0) {
Packit e9ba0d
		/* We might have an IPv4 interface. */
Packit e9ba0d
		ev_uint32_t addr = ntohl(sin_out.sin_addr.s_addr);
Packit e9ba0d
		if (addr == 0 ||
Packit e9ba0d
		    EVUTIL_V4ADDR_IS_LOCALHOST(addr) ||
Packit e9ba0d
		    EVUTIL_V4ADDR_IS_CLASSD(addr)) {
Packit e9ba0d
			evutil_inet_ntop(AF_INET, &sin_out.sin_addr,
Packit e9ba0d
			    buf, sizeof(buf));
Packit e9ba0d
			/* This is a reserved, ipv4compat, ipv4map, loopback,
Packit e9ba0d
			 * link-local or unspecified address.  The host should
Packit e9ba0d
			 * never have given it to us; it could never connect
Packit e9ba0d
			 * to sin. */
Packit e9ba0d
			event_warnx("Got a strange local ipv4 address %s",buf);
Packit e9ba0d
		} else {
Packit e9ba0d
			event_debug(("Detected an IPv4 interface"));
Packit e9ba0d
			had_ipv4_address = 1;
Packit e9ba0d
		}
Packit e9ba0d
	}
Packit e9ba0d
	if (fd >= 0)
Packit e9ba0d
		evutil_closesocket(fd);
Packit e9ba0d
Packit e9ba0d
	if ((fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) >= 0 &&
Packit e9ba0d
	    connect(fd, (struct sockaddr*)&sin6, sizeof(sin6)) == 0 &&
Packit e9ba0d
	    getsockname(fd, (struct sockaddr*)&sin6_out, &sin6_out_len) == 0) {
Packit e9ba0d
		/* We might have an IPv6 interface. */
Packit e9ba0d
		const unsigned char *addr =
Packit e9ba0d
		    (unsigned char*)sin6_out.sin6_addr.s6_addr;
Packit e9ba0d
		if (!memcmp(addr, ZEROES, 8) ||
Packit e9ba0d
		    (addr[0] == 0xfe && (addr[1] & 0xc0) == 0x80)) {
Packit e9ba0d
			/* This is a reserved, ipv4compat, ipv4map, loopback,
Packit e9ba0d
			 * link-local or unspecified address.  The host should
Packit e9ba0d
			 * never have given it to us; it could never connect
Packit e9ba0d
			 * to sin6. */
Packit e9ba0d
			evutil_inet_ntop(AF_INET6, &sin6_out.sin6_addr,
Packit e9ba0d
			    buf, sizeof(buf));
Packit e9ba0d
			event_warnx("Got a strange local ipv6 address %s",buf);
Packit e9ba0d
		} else {
Packit e9ba0d
			event_debug(("Detected an IPv4 interface"));
Packit e9ba0d
			had_ipv6_address = 1;
Packit e9ba0d
		}
Packit e9ba0d
	}
Packit e9ba0d
Packit e9ba0d
	if (fd >= 0)
Packit e9ba0d
		evutil_closesocket(fd);
Packit e9ba0d
Packit e9ba0d
	return 0;
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
/* Internal addrinfo flag.  This one is set when we allocate the addrinfo from
Packit e9ba0d
 * inside libevent.  Otherwise, the built-in getaddrinfo() function allocated
Packit e9ba0d
 * it, and we should trust what they said.
Packit e9ba0d
 **/
Packit e9ba0d
#define EVUTIL_AI_LIBEVENT_ALLOCATED 0x80000000
Packit e9ba0d
Packit e9ba0d
/* Helper: construct a new addrinfo containing the socket address in
Packit e9ba0d
 * 'sa', which must be a sockaddr_in or a sockaddr_in6.  Take the
Packit e9ba0d
 * socktype and protocol info from hints.  If they weren't set, then
Packit e9ba0d
 * allocate both a TCP and a UDP addrinfo.
Packit e9ba0d
 */
Packit e9ba0d
struct evutil_addrinfo *
Packit e9ba0d
evutil_new_addrinfo(struct sockaddr *sa, ev_socklen_t socklen,
Packit e9ba0d
    const struct evutil_addrinfo *hints)
Packit e9ba0d
{
Packit e9ba0d
	struct evutil_addrinfo *res;
Packit e9ba0d
	EVUTIL_ASSERT(hints);
Packit e9ba0d
Packit e9ba0d
	if (hints->ai_socktype == 0 && hints->ai_protocol == 0) {
Packit e9ba0d
		/* Indecisive user! Give them a UDP and a TCP. */
Packit e9ba0d
		struct evutil_addrinfo *r1, *r2;
Packit e9ba0d
		struct evutil_addrinfo tmp;
Packit e9ba0d
		memcpy(&tmp, hints, sizeof(tmp));
Packit e9ba0d
		tmp.ai_socktype = SOCK_STREAM; tmp.ai_protocol = IPPROTO_TCP;
Packit e9ba0d
		r1 = evutil_new_addrinfo(sa, socklen, &tmp);
Packit e9ba0d
		if (!r1)
Packit e9ba0d
			return NULL;
Packit e9ba0d
		tmp.ai_socktype = SOCK_DGRAM; tmp.ai_protocol = IPPROTO_UDP;
Packit e9ba0d
		r2 = evutil_new_addrinfo(sa, socklen, &tmp);
Packit e9ba0d
		if (!r2) {
Packit e9ba0d
			evutil_freeaddrinfo(r1);
Packit e9ba0d
			return NULL;
Packit e9ba0d
		}
Packit e9ba0d
		r1->ai_next = r2;
Packit e9ba0d
		return r1;
Packit e9ba0d
	}
Packit e9ba0d
Packit e9ba0d
	/* We're going to allocate extra space to hold the sockaddr. */
Packit e9ba0d
	res = mm_calloc(1,sizeof(struct evutil_addrinfo)+socklen);
Packit e9ba0d
	if (!res)
Packit e9ba0d
		return NULL;
Packit e9ba0d
	res->ai_addr = (struct sockaddr*)
Packit e9ba0d
	    (((char*)res) + sizeof(struct evutil_addrinfo));
Packit e9ba0d
	memcpy(res->ai_addr, sa, socklen);
Packit e9ba0d
	res->ai_addrlen = socklen;
Packit e9ba0d
	res->ai_family = sa->sa_family; /* Same or not? XXX */
Packit e9ba0d
	res->ai_flags = EVUTIL_AI_LIBEVENT_ALLOCATED;
Packit e9ba0d
	res->ai_socktype = hints->ai_socktype;
Packit e9ba0d
	res->ai_protocol = hints->ai_protocol;
Packit e9ba0d
Packit e9ba0d
	return res;
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
/* Append the addrinfo 'append' to the end of 'first', and return the start of
Packit e9ba0d
 * the list.  Either element can be NULL, in which case we return the element
Packit e9ba0d
 * that is not NULL. */
Packit e9ba0d
struct evutil_addrinfo *
Packit e9ba0d
evutil_addrinfo_append(struct evutil_addrinfo *first,
Packit e9ba0d
    struct evutil_addrinfo *append)
Packit e9ba0d
{
Packit e9ba0d
	struct evutil_addrinfo *ai = first;
Packit e9ba0d
	if (!ai)
Packit e9ba0d
		return append;
Packit e9ba0d
	while (ai->ai_next)
Packit e9ba0d
		ai = ai->ai_next;
Packit e9ba0d
	ai->ai_next = append;
Packit e9ba0d
Packit e9ba0d
	return first;
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
static int
Packit e9ba0d
parse_numeric_servname(const char *servname)
Packit e9ba0d
{
Packit e9ba0d
	int n;
Packit e9ba0d
	char *endptr=NULL;
Packit e9ba0d
	n = (int) strtol(servname, &endptr, 10);
Packit e9ba0d
	if (n>=0 && n <= 65535 && servname[0] && endptr && !endptr[0])
Packit e9ba0d
		return n;
Packit e9ba0d
	else
Packit e9ba0d
		return -1;
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
/** Parse a service name in 'servname', which can be a decimal port.
Packit e9ba0d
 * Return the port number, or -1 on error.
Packit e9ba0d
 */
Packit e9ba0d
static int
Packit e9ba0d
evutil_parse_servname(const char *servname, const char *protocol,
Packit e9ba0d
    const struct evutil_addrinfo *hints)
Packit e9ba0d
{
Packit e9ba0d
	int n = parse_numeric_servname(servname);
Packit e9ba0d
	if (n>=0)
Packit e9ba0d
		return n;
Packit e9ba0d
#if defined(_EVENT_HAVE_GETSERVBYNAME) || defined(WIN32)
Packit e9ba0d
	if (!(hints->ai_flags & EVUTIL_AI_NUMERICSERV)) {
Packit e9ba0d
		struct servent *ent = getservbyname(servname, protocol);
Packit e9ba0d
		if (ent) {
Packit e9ba0d
			return ntohs(ent->s_port);
Packit e9ba0d
		}
Packit e9ba0d
	}
Packit e9ba0d
#endif
Packit e9ba0d
	return -1;
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
/* Return a string corresponding to a protocol number that we can pass to
Packit e9ba0d
 * getservyname.  */
Packit e9ba0d
static const char *
Packit e9ba0d
evutil_unparse_protoname(int proto)
Packit e9ba0d
{
Packit e9ba0d
	switch (proto) {
Packit e9ba0d
	case 0:
Packit e9ba0d
		return NULL;
Packit e9ba0d
	case IPPROTO_TCP:
Packit e9ba0d
		return "tcp";
Packit e9ba0d
	case IPPROTO_UDP:
Packit e9ba0d
		return "udp";
Packit e9ba0d
#ifdef IPPROTO_SCTP
Packit e9ba0d
	case IPPROTO_SCTP:
Packit e9ba0d
		return "sctp";
Packit e9ba0d
#endif
Packit e9ba0d
	default:
Packit e9ba0d
#ifdef _EVENT_HAVE_GETPROTOBYNUMBER
Packit e9ba0d
		{
Packit e9ba0d
			struct protoent *ent = getprotobynumber(proto);
Packit e9ba0d
			if (ent)
Packit e9ba0d
				return ent->p_name;
Packit e9ba0d
		}
Packit e9ba0d
#endif
Packit e9ba0d
		return NULL;
Packit e9ba0d
	}
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
static void
Packit e9ba0d
evutil_getaddrinfo_infer_protocols(struct evutil_addrinfo *hints)
Packit e9ba0d
{
Packit e9ba0d
	/* If we can guess the protocol from the socktype, do so. */
Packit e9ba0d
	if (!hints->ai_protocol && hints->ai_socktype) {
Packit e9ba0d
		if (hints->ai_socktype == SOCK_DGRAM)
Packit e9ba0d
			hints->ai_protocol = IPPROTO_UDP;
Packit e9ba0d
		else if (hints->ai_socktype == SOCK_STREAM)
Packit e9ba0d
			hints->ai_protocol = IPPROTO_TCP;
Packit e9ba0d
	}
Packit e9ba0d
Packit e9ba0d
	/* Set the socktype if it isn't set. */
Packit e9ba0d
	if (!hints->ai_socktype && hints->ai_protocol) {
Packit e9ba0d
		if (hints->ai_protocol == IPPROTO_UDP)
Packit e9ba0d
			hints->ai_socktype = SOCK_DGRAM;
Packit e9ba0d
		else if (hints->ai_protocol == IPPROTO_TCP)
Packit e9ba0d
			hints->ai_socktype = SOCK_STREAM;
Packit e9ba0d
#ifdef IPPROTO_SCTP
Packit e9ba0d
		else if (hints->ai_protocol == IPPROTO_SCTP)
Packit e9ba0d
			hints->ai_socktype = SOCK_STREAM;
Packit e9ba0d
#endif
Packit e9ba0d
	}
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
#if AF_UNSPEC != PF_UNSPEC
Packit e9ba0d
#error "I cannot build on a system where AF_UNSPEC != PF_UNSPEC"
Packit e9ba0d
#endif
Packit e9ba0d
Packit e9ba0d
/** Implements the part of looking up hosts by name that's common to both
Packit e9ba0d
 * the blocking and nonblocking resolver:
Packit e9ba0d
 *   - Adjust 'hints' to have a reasonable socktype and protocol.
Packit e9ba0d
 *   - Look up the port based on 'servname', and store it in *portnum,
Packit e9ba0d
 *   - Handle the nodename==NULL case
Packit e9ba0d
 *   - Handle some invalid arguments cases.
Packit e9ba0d
 *   - Handle the cases where nodename is an IPv4 or IPv6 address.
Packit e9ba0d
 *
Packit e9ba0d
 * If we need the resolver to look up the hostname, we return
Packit e9ba0d
 * EVUTIL_EAI_NEED_RESOLVE.  Otherwise, we can completely implement
Packit e9ba0d
 * getaddrinfo: we return 0 or an appropriate EVUTIL_EAI_* error, and
Packit e9ba0d
 * set *res as getaddrinfo would.
Packit e9ba0d
 */
Packit e9ba0d
int
Packit e9ba0d
evutil_getaddrinfo_common(const char *nodename, const char *servname,
Packit e9ba0d
    struct evutil_addrinfo *hints, struct evutil_addrinfo **res, int *portnum)
Packit e9ba0d
{
Packit e9ba0d
	int port = 0;
Packit e9ba0d
	const char *pname;
Packit e9ba0d
Packit e9ba0d
	if (nodename == NULL && servname == NULL)
Packit e9ba0d
		return EVUTIL_EAI_NONAME;
Packit e9ba0d
Packit e9ba0d
	/* We only understand 3 families */
Packit e9ba0d
	if (hints->ai_family != PF_UNSPEC && hints->ai_family != PF_INET &&
Packit e9ba0d
	    hints->ai_family != PF_INET6)
Packit e9ba0d
		return EVUTIL_EAI_FAMILY;
Packit e9ba0d
Packit e9ba0d
	evutil_getaddrinfo_infer_protocols(hints);
Packit e9ba0d
Packit e9ba0d
	/* Look up the port number and protocol, if possible. */
Packit e9ba0d
	pname = evutil_unparse_protoname(hints->ai_protocol);
Packit e9ba0d
	if (servname) {
Packit e9ba0d
		/* XXXX We could look at the protocol we got back from
Packit e9ba0d
		 * getservbyname, but it doesn't seem too useful. */
Packit e9ba0d
		port = evutil_parse_servname(servname, pname, hints);
Packit e9ba0d
		if (port < 0) {
Packit e9ba0d
			return EVUTIL_EAI_NONAME;
Packit e9ba0d
		}
Packit e9ba0d
	}
Packit e9ba0d
Packit e9ba0d
	/* If we have no node name, then we're supposed to bind to 'any' and
Packit e9ba0d
	 * connect to localhost. */
Packit e9ba0d
	if (nodename == NULL) {
Packit e9ba0d
		struct evutil_addrinfo *res4=NULL, *res6=NULL;
Packit e9ba0d
		if (hints->ai_family != PF_INET) { /* INET6 or UNSPEC. */
Packit e9ba0d
			struct sockaddr_in6 sin6;
Packit e9ba0d
			memset(&sin6, 0, sizeof(sin6));
Packit e9ba0d
			sin6.sin6_family = AF_INET6;
Packit e9ba0d
			sin6.sin6_port = htons(port);
Packit e9ba0d
			if (hints->ai_flags & EVUTIL_AI_PASSIVE) {
Packit e9ba0d
				/* Bind to :: */
Packit e9ba0d
			} else {
Packit e9ba0d
				/* connect to ::1 */
Packit e9ba0d
				sin6.sin6_addr.s6_addr[15] = 1;
Packit e9ba0d
			}
Packit e9ba0d
			res6 = evutil_new_addrinfo((struct sockaddr*)&sin6,
Packit e9ba0d
			    sizeof(sin6), hints);
Packit e9ba0d
			if (!res6)
Packit e9ba0d
				return EVUTIL_EAI_MEMORY;
Packit e9ba0d
		}
Packit e9ba0d
Packit e9ba0d
		if (hints->ai_family != PF_INET6) { /* INET or UNSPEC */
Packit e9ba0d
			struct sockaddr_in sin;
Packit e9ba0d
			memset(&sin, 0, sizeof(sin));
Packit e9ba0d
			sin.sin_family = AF_INET;
Packit e9ba0d
			sin.sin_port = htons(port);
Packit e9ba0d
			if (hints->ai_flags & EVUTIL_AI_PASSIVE) {
Packit e9ba0d
				/* Bind to 0.0.0.0 */
Packit e9ba0d
			} else {
Packit e9ba0d
				/* connect to 127.0.0.1 */
Packit e9ba0d
				sin.sin_addr.s_addr = htonl(0x7f000001);
Packit e9ba0d
			}
Packit e9ba0d
			res4 = evutil_new_addrinfo((struct sockaddr*)&sin,
Packit e9ba0d
			    sizeof(sin), hints);
Packit e9ba0d
			if (!res4) {
Packit e9ba0d
				if (res6)
Packit e9ba0d
					evutil_freeaddrinfo(res6);
Packit e9ba0d
				return EVUTIL_EAI_MEMORY;
Packit e9ba0d
			}
Packit e9ba0d
		}
Packit e9ba0d
		*res = evutil_addrinfo_append(res4, res6);
Packit e9ba0d
		return 0;
Packit e9ba0d
	}
Packit e9ba0d
Packit e9ba0d
	/* If we can, we should try to parse the hostname without resolving
Packit e9ba0d
	 * it. */
Packit e9ba0d
	/* Try ipv6. */
Packit e9ba0d
	if (hints->ai_family == PF_INET6 || hints->ai_family == PF_UNSPEC) {
Packit e9ba0d
		struct sockaddr_in6 sin6;
Packit e9ba0d
		memset(&sin6, 0, sizeof(sin6));
Packit e9ba0d
		if (1==evutil_inet_pton(AF_INET6, nodename, &sin6.sin6_addr)) {
Packit e9ba0d
			/* Got an ipv6 address. */
Packit e9ba0d
			sin6.sin6_family = AF_INET6;
Packit e9ba0d
			sin6.sin6_port = htons(port);
Packit e9ba0d
			*res = evutil_new_addrinfo((struct sockaddr*)&sin6,
Packit e9ba0d
			    sizeof(sin6), hints);
Packit e9ba0d
			if (!*res)
Packit e9ba0d
				return EVUTIL_EAI_MEMORY;
Packit e9ba0d
			return 0;
Packit e9ba0d
		}
Packit e9ba0d
	}
Packit e9ba0d
Packit e9ba0d
	/* Try ipv4. */
Packit e9ba0d
	if (hints->ai_family == PF_INET || hints->ai_family == PF_UNSPEC) {
Packit e9ba0d
		struct sockaddr_in sin;
Packit e9ba0d
		memset(&sin, 0, sizeof(sin));
Packit e9ba0d
		if (1==evutil_inet_pton(AF_INET, nodename, &sin.sin_addr)) {
Packit e9ba0d
			/* Got an ipv6 address. */
Packit e9ba0d
			sin.sin_family = AF_INET;
Packit e9ba0d
			sin.sin_port = htons(port);
Packit e9ba0d
			*res = evutil_new_addrinfo((struct sockaddr*)&sin,
Packit e9ba0d
			    sizeof(sin), hints);
Packit e9ba0d
			if (!*res)
Packit e9ba0d
				return EVUTIL_EAI_MEMORY;
Packit e9ba0d
			return 0;
Packit e9ba0d
		}
Packit e9ba0d
	}
Packit e9ba0d
Packit e9ba0d
Packit e9ba0d
	/* If we have reached this point, we definitely need to do a DNS
Packit e9ba0d
	 * lookup. */
Packit e9ba0d
	if ((hints->ai_flags & EVUTIL_AI_NUMERICHOST)) {
Packit e9ba0d
		/* If we're not allowed to do one, then say so. */
Packit e9ba0d
		return EVUTIL_EAI_NONAME;
Packit e9ba0d
	}
Packit e9ba0d
	*portnum = port;
Packit e9ba0d
	return EVUTIL_EAI_NEED_RESOLVE;
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
#ifdef _EVENT_HAVE_GETADDRINFO
Packit e9ba0d
#define USE_NATIVE_GETADDRINFO
Packit e9ba0d
#endif
Packit e9ba0d
Packit e9ba0d
#ifdef USE_NATIVE_GETADDRINFO
Packit e9ba0d
/* A mask of all the flags that we declare, so we can clear them before calling
Packit e9ba0d
 * the native getaddrinfo */
Packit e9ba0d
static const unsigned int ALL_NONNATIVE_AI_FLAGS =
Packit e9ba0d
#ifndef AI_PASSIVE
Packit e9ba0d
    EVUTIL_AI_PASSIVE |
Packit e9ba0d
#endif
Packit e9ba0d
#ifndef AI_CANONNAME
Packit e9ba0d
    EVUTIL_AI_CANONNAME |
Packit e9ba0d
#endif
Packit e9ba0d
#ifndef AI_NUMERICHOST
Packit e9ba0d
    EVUTIL_AI_NUMERICHOST |
Packit e9ba0d
#endif
Packit e9ba0d
#ifndef AI_NUMERICSERV
Packit e9ba0d
    EVUTIL_AI_NUMERICSERV |
Packit e9ba0d
#endif
Packit e9ba0d
#ifndef AI_ADDRCONFIG
Packit e9ba0d
    EVUTIL_AI_ADDRCONFIG |
Packit e9ba0d
#endif
Packit e9ba0d
#ifndef AI_ALL
Packit e9ba0d
    EVUTIL_AI_ALL |
Packit e9ba0d
#endif
Packit e9ba0d
#ifndef AI_V4MAPPED
Packit e9ba0d
    EVUTIL_AI_V4MAPPED |
Packit e9ba0d
#endif
Packit e9ba0d
    EVUTIL_AI_LIBEVENT_ALLOCATED;
Packit e9ba0d
Packit e9ba0d
static const unsigned int ALL_NATIVE_AI_FLAGS =
Packit e9ba0d
#ifdef AI_PASSIVE
Packit e9ba0d
    AI_PASSIVE |
Packit e9ba0d
#endif
Packit e9ba0d
#ifdef AI_CANONNAME
Packit e9ba0d
    AI_CANONNAME |
Packit e9ba0d
#endif
Packit e9ba0d
#ifdef AI_NUMERICHOST
Packit e9ba0d
    AI_NUMERICHOST |
Packit e9ba0d
#endif
Packit e9ba0d
#ifdef AI_NUMERICSERV
Packit e9ba0d
    AI_NUMERICSERV |
Packit e9ba0d
#endif
Packit e9ba0d
#ifdef AI_ADDRCONFIG
Packit e9ba0d
    AI_ADDRCONFIG |
Packit e9ba0d
#endif
Packit e9ba0d
#ifdef AI_ALL
Packit e9ba0d
    AI_ALL |
Packit e9ba0d
#endif
Packit e9ba0d
#ifdef AI_V4MAPPED
Packit e9ba0d
    AI_V4MAPPED |
Packit e9ba0d
#endif
Packit e9ba0d
    0;
Packit e9ba0d
#endif
Packit e9ba0d
Packit e9ba0d
#ifndef USE_NATIVE_GETADDRINFO
Packit e9ba0d
/* Helper for systems with no getaddrinfo(): make one or more addrinfos out of
Packit e9ba0d
 * a struct hostent.
Packit e9ba0d
 */
Packit e9ba0d
static struct evutil_addrinfo *
Packit e9ba0d
addrinfo_from_hostent(const struct hostent *ent,
Packit e9ba0d
    int port, const struct evutil_addrinfo *hints)
Packit e9ba0d
{
Packit e9ba0d
	int i;
Packit e9ba0d
	struct sockaddr_in sin;
Packit e9ba0d
	struct sockaddr_in6 sin6;
Packit e9ba0d
	struct sockaddr *sa;
Packit e9ba0d
	int socklen;
Packit e9ba0d
	struct evutil_addrinfo *res=NULL, *ai;
Packit e9ba0d
	void *addrp;
Packit e9ba0d
Packit e9ba0d
	if (ent->h_addrtype == PF_INET) {
Packit e9ba0d
		memset(&sin, 0, sizeof(sin));
Packit e9ba0d
		sin.sin_family = AF_INET;
Packit e9ba0d
		sin.sin_port = htons(port);
Packit e9ba0d
		sa = (struct sockaddr *)&sin;
Packit e9ba0d
		socklen = sizeof(struct sockaddr_in);
Packit e9ba0d
		addrp = &sin.sin_addr;
Packit e9ba0d
		if (ent->h_length != sizeof(sin.sin_addr)) {
Packit e9ba0d
			event_warnx("Weird h_length from gethostbyname");
Packit e9ba0d
			return NULL;
Packit e9ba0d
		}
Packit e9ba0d
	} else if (ent->h_addrtype == PF_INET6) {
Packit e9ba0d
		memset(&sin6, 0, sizeof(sin6));
Packit e9ba0d
		sin6.sin6_family = AF_INET6;
Packit e9ba0d
		sin6.sin6_port = htons(port);
Packit e9ba0d
		sa = (struct sockaddr *)&sin;;
Packit e9ba0d
		socklen = sizeof(struct sockaddr_in);
Packit e9ba0d
		addrp = &sin6.sin6_addr;
Packit e9ba0d
		if (ent->h_length != sizeof(sin6.sin6_addr)) {
Packit e9ba0d
			event_warnx("Weird h_length from gethostbyname");
Packit e9ba0d
			return NULL;
Packit e9ba0d
		}
Packit e9ba0d
	} else
Packit e9ba0d
		return NULL;
Packit e9ba0d
Packit e9ba0d
	for (i = 0; ent->h_addr_list[i]; ++i) {
Packit e9ba0d
		memcpy(addrp, ent->h_addr_list[i], ent->h_length);
Packit e9ba0d
		ai = evutil_new_addrinfo(sa, socklen, hints);
Packit e9ba0d
		if (!ai) {
Packit e9ba0d
			evutil_freeaddrinfo(res);
Packit e9ba0d
			return NULL;
Packit e9ba0d
		}
Packit e9ba0d
		res = evutil_addrinfo_append(res, ai);
Packit e9ba0d
	}
Packit e9ba0d
Packit e9ba0d
	if (res && ((hints->ai_flags & EVUTIL_AI_CANONNAME) && ent->h_name)) {
Packit e9ba0d
		res->ai_canonname = mm_strdup(ent->h_name);
Packit e9ba0d
		if (res->ai_canonname == NULL) {
Packit e9ba0d
			evutil_freeaddrinfo(res);
Packit e9ba0d
			return NULL;
Packit e9ba0d
		}
Packit e9ba0d
	}
Packit e9ba0d
Packit e9ba0d
	return res;
Packit e9ba0d
}
Packit e9ba0d
#endif
Packit e9ba0d
Packit e9ba0d
/* If the EVUTIL_AI_ADDRCONFIG flag is set on hints->ai_flags, and
Packit e9ba0d
 * hints->ai_family is PF_UNSPEC, then revise the value of hints->ai_family so
Packit e9ba0d
 * that we'll only get addresses we could maybe connect to.
Packit e9ba0d
 */
Packit e9ba0d
void
Packit e9ba0d
evutil_adjust_hints_for_addrconfig(struct evutil_addrinfo *hints)
Packit e9ba0d
{
Packit e9ba0d
	if (!(hints->ai_flags & EVUTIL_AI_ADDRCONFIG))
Packit e9ba0d
		return;
Packit e9ba0d
	if (hints->ai_family != PF_UNSPEC)
Packit e9ba0d
		return;
Packit e9ba0d
	if (!have_checked_interfaces)
Packit e9ba0d
		evutil_check_interfaces(0);
Packit e9ba0d
	if (had_ipv4_address && !had_ipv6_address) {
Packit e9ba0d
		hints->ai_family = PF_INET;
Packit e9ba0d
	} else if (!had_ipv4_address && had_ipv6_address) {
Packit e9ba0d
		hints->ai_family = PF_INET6;
Packit e9ba0d
	}
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
#ifdef USE_NATIVE_GETADDRINFO
Packit e9ba0d
static int need_numeric_port_hack_=0;
Packit e9ba0d
static int need_socktype_protocol_hack_=0;
Packit e9ba0d
static int tested_for_getaddrinfo_hacks=0;
Packit e9ba0d
Packit e9ba0d
/* Some older BSDs (like OpenBSD up to 4.6) used to believe that
Packit e9ba0d
   giving a numeric port without giving an ai_socktype was verboten.
Packit e9ba0d
   We test for this so we can apply an appropriate workaround.  If it
Packit e9ba0d
   turns out that the bug is present, then:
Packit e9ba0d
Packit e9ba0d
    - If nodename==NULL and servname is numeric, we build an answer
Packit e9ba0d
      ourselves using evutil_getaddrinfo_common().
Packit e9ba0d
Packit e9ba0d
    - If nodename!=NULL and servname is numeric, then we set
Packit e9ba0d
      servname=NULL when calling getaddrinfo, and post-process the
Packit e9ba0d
      result to set the ports on it.
Packit e9ba0d
Packit e9ba0d
   We test for this bug at runtime, since otherwise we can't have the
Packit e9ba0d
   same binary run on multiple BSD versions.
Packit e9ba0d
Packit e9ba0d
   - Some versions of Solaris believe that it's nice to leave to protocol
Packit e9ba0d
     field set to 0.  We test for this so we can apply an appropriate
Packit e9ba0d
     workaround.
Packit e9ba0d
*/
Packit e9ba0d
static void
Packit e9ba0d
test_for_getaddrinfo_hacks(void)
Packit e9ba0d
{
Packit e9ba0d
	int r, r2;
Packit e9ba0d
	struct evutil_addrinfo *ai=NULL, *ai2=NULL;
Packit e9ba0d
	struct evutil_addrinfo hints;
Packit e9ba0d
Packit e9ba0d
	memset(&hints,0,sizeof(hints));
Packit e9ba0d
	hints.ai_family = PF_UNSPEC;
Packit e9ba0d
	hints.ai_flags =
Packit e9ba0d
#ifdef AI_NUMERICHOST
Packit e9ba0d
	    AI_NUMERICHOST |
Packit e9ba0d
#endif
Packit e9ba0d
#ifdef AI_NUMERICSERV
Packit e9ba0d
	    AI_NUMERICSERV |
Packit e9ba0d
#endif
Packit e9ba0d
	    0;
Packit e9ba0d
	r = getaddrinfo("1.2.3.4", "80", &hints, &ai;;
Packit e9ba0d
	hints.ai_socktype = SOCK_STREAM;
Packit e9ba0d
	r2 = getaddrinfo("1.2.3.4", "80", &hints, &ai2);
Packit e9ba0d
	if (r2 == 0 && r != 0) {
Packit e9ba0d
		need_numeric_port_hack_=1;
Packit e9ba0d
	}
Packit e9ba0d
	if (ai2 && ai2->ai_protocol == 0) {
Packit e9ba0d
		need_socktype_protocol_hack_=1;
Packit e9ba0d
	}
Packit e9ba0d
Packit e9ba0d
	if (ai)
Packit e9ba0d
		freeaddrinfo(ai);
Packit e9ba0d
	if (ai2)
Packit e9ba0d
		freeaddrinfo(ai2);
Packit e9ba0d
	tested_for_getaddrinfo_hacks=1;
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
static inline int
Packit e9ba0d
need_numeric_port_hack(void)
Packit e9ba0d
{
Packit e9ba0d
	if (!tested_for_getaddrinfo_hacks)
Packit e9ba0d
		test_for_getaddrinfo_hacks();
Packit e9ba0d
	return need_numeric_port_hack_;
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
static inline int
Packit e9ba0d
need_socktype_protocol_hack(void)
Packit e9ba0d
{
Packit e9ba0d
	if (!tested_for_getaddrinfo_hacks)
Packit e9ba0d
		test_for_getaddrinfo_hacks();
Packit e9ba0d
	return need_socktype_protocol_hack_;
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
static void
Packit e9ba0d
apply_numeric_port_hack(int port, struct evutil_addrinfo **ai)
Packit e9ba0d
{
Packit e9ba0d
	/* Now we run through the list and set the ports on all of the
Packit e9ba0d
	 * results where ports would make sense. */
Packit e9ba0d
	for ( ; *ai; ai = &(*ai)->ai_next) {
Packit e9ba0d
		struct sockaddr *sa = (*ai)->ai_addr;
Packit e9ba0d
		if (sa && sa->sa_family == AF_INET) {
Packit e9ba0d
			struct sockaddr_in *sin = (struct sockaddr_in*)sa;
Packit e9ba0d
			sin->sin_port = htons(port);
Packit e9ba0d
		} else if (sa && sa->sa_family == AF_INET6) {
Packit e9ba0d
			struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)sa;
Packit e9ba0d
			sin6->sin6_port = htons(port);
Packit e9ba0d
		} else {
Packit e9ba0d
			/* A numeric port makes no sense here; remove this one
Packit e9ba0d
			 * from the list. */
Packit e9ba0d
			struct evutil_addrinfo *victim = *ai;
Packit e9ba0d
			*ai = victim->ai_next;
Packit e9ba0d
			victim->ai_next = NULL;
Packit e9ba0d
			freeaddrinfo(victim);
Packit e9ba0d
		}
Packit e9ba0d
	}
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
static int
Packit e9ba0d
apply_socktype_protocol_hack(struct evutil_addrinfo *ai)
Packit e9ba0d
{
Packit e9ba0d
	struct evutil_addrinfo *ai_new;
Packit e9ba0d
	for (; ai; ai = ai->ai_next) {
Packit e9ba0d
		evutil_getaddrinfo_infer_protocols(ai);
Packit e9ba0d
		if (ai->ai_socktype || ai->ai_protocol)
Packit e9ba0d
			continue;
Packit e9ba0d
		ai_new = mm_malloc(sizeof(*ai_new));
Packit e9ba0d
		if (!ai_new)
Packit e9ba0d
			return -1;
Packit e9ba0d
		memcpy(ai_new, ai, sizeof(*ai_new));
Packit e9ba0d
		ai->ai_socktype = SOCK_STREAM;
Packit e9ba0d
		ai->ai_protocol = IPPROTO_TCP;
Packit e9ba0d
		ai_new->ai_socktype = SOCK_DGRAM;
Packit e9ba0d
		ai_new->ai_protocol = IPPROTO_UDP;
Packit e9ba0d
Packit e9ba0d
		ai_new->ai_next = ai->ai_next;
Packit e9ba0d
		ai->ai_next = ai_new;
Packit e9ba0d
	}
Packit e9ba0d
	return 0;
Packit e9ba0d
}
Packit e9ba0d
#endif
Packit e9ba0d
Packit e9ba0d
int
Packit e9ba0d
evutil_getaddrinfo(const char *nodename, const char *servname,
Packit e9ba0d
    const struct evutil_addrinfo *hints_in, struct evutil_addrinfo **res)
Packit e9ba0d
{
Packit e9ba0d
#ifdef USE_NATIVE_GETADDRINFO
Packit e9ba0d
	struct evutil_addrinfo hints;
Packit e9ba0d
	int portnum=-1, need_np_hack, err;
Packit e9ba0d
Packit e9ba0d
	if (hints_in) {
Packit e9ba0d
		memcpy(&hints, hints_in, sizeof(hints));
Packit e9ba0d
	} else {
Packit e9ba0d
		memset(&hints, 0, sizeof(hints));
Packit e9ba0d
		hints.ai_family = PF_UNSPEC;
Packit e9ba0d
	}
Packit e9ba0d
Packit e9ba0d
#ifndef AI_ADDRCONFIG
Packit e9ba0d
	/* Not every system has AI_ADDRCONFIG, so fake it. */
Packit e9ba0d
	if (hints.ai_family == PF_UNSPEC &&
Packit e9ba0d
	    (hints.ai_flags & EVUTIL_AI_ADDRCONFIG)) {
Packit e9ba0d
		evutil_adjust_hints_for_addrconfig(&hints);
Packit e9ba0d
	}
Packit e9ba0d
#endif
Packit e9ba0d
Packit e9ba0d
#ifndef AI_NUMERICSERV
Packit e9ba0d
	/* Not every system has AI_NUMERICSERV, so fake it. */
Packit e9ba0d
	if (hints.ai_flags & EVUTIL_AI_NUMERICSERV) {
Packit e9ba0d
		if (servname && parse_numeric_servname(servname)<0)
Packit e9ba0d
			return EVUTIL_EAI_NONAME;
Packit e9ba0d
	}
Packit e9ba0d
#endif
Packit e9ba0d
Packit e9ba0d
	/* Enough operating systems handle enough common non-resolve
Packit e9ba0d
	 * cases here weirdly enough that we are better off just
Packit e9ba0d
	 * overriding them.  For example:
Packit e9ba0d
	 *
Packit e9ba0d
	 * - Windows doesn't like to infer the protocol from the
Packit e9ba0d
	 *   socket type, or fill in socket or protocol types much at
Packit e9ba0d
	 *   all.  It also seems to do its own broken implicit
Packit e9ba0d
	 *   always-on version of AI_ADDRCONFIG that keeps it from
Packit e9ba0d
	 *   ever resolving even a literal IPv6 address when
Packit e9ba0d
	 *   ai_addrtype is PF_UNSPEC.
Packit e9ba0d
	 */
Packit e9ba0d
#ifdef WIN32
Packit e9ba0d
	{
Packit e9ba0d
		int tmp_port;
Packit e9ba0d
		err = evutil_getaddrinfo_common(nodename,servname,&hints,
Packit e9ba0d
		    res, &tmp_port);
Packit e9ba0d
		if (err == 0 ||
Packit e9ba0d
		    err == EVUTIL_EAI_MEMORY ||
Packit e9ba0d
		    err == EVUTIL_EAI_NONAME)
Packit e9ba0d
			return err;
Packit e9ba0d
		/* If we make it here, the system getaddrinfo can
Packit e9ba0d
		 * have a crack at it. */
Packit e9ba0d
	}
Packit e9ba0d
#endif
Packit e9ba0d
Packit e9ba0d
	/* See documentation for need_numeric_port_hack above.*/
Packit e9ba0d
	need_np_hack = need_numeric_port_hack() && servname && !hints.ai_socktype
Packit e9ba0d
	    && ((portnum=parse_numeric_servname(servname)) >= 0);
Packit e9ba0d
	if (need_np_hack) {
Packit e9ba0d
		if (!nodename)
Packit e9ba0d
			return evutil_getaddrinfo_common(
Packit e9ba0d
				NULL,servname,&hints, res, &portnum);
Packit e9ba0d
		servname = NULL;
Packit e9ba0d
	}
Packit e9ba0d
Packit e9ba0d
	if (need_socktype_protocol_hack()) {
Packit e9ba0d
		evutil_getaddrinfo_infer_protocols(&hints);
Packit e9ba0d
	}
Packit e9ba0d
Packit e9ba0d
	/* Make sure that we didn't actually steal any AI_FLAGS values that
Packit e9ba0d
	 * the system is using.  (This is a constant expression, and should ge
Packit e9ba0d
	 * optimized out.)
Packit e9ba0d
	 *
Packit e9ba0d
	 * XXXX Turn this into a compile-time failure rather than a run-time
Packit e9ba0d
	 * failure.
Packit e9ba0d
	 */
Packit e9ba0d
	EVUTIL_ASSERT((ALL_NONNATIVE_AI_FLAGS & ALL_NATIVE_AI_FLAGS) == 0);
Packit e9ba0d
Packit e9ba0d
	/* Clear any flags that only libevent understands. */
Packit e9ba0d
	hints.ai_flags &= ~ALL_NONNATIVE_AI_FLAGS;
Packit e9ba0d
Packit e9ba0d
	err = getaddrinfo(nodename, servname, &hints, res);
Packit e9ba0d
	if (need_np_hack)
Packit e9ba0d
		apply_numeric_port_hack(portnum, res);
Packit e9ba0d
Packit e9ba0d
	if (need_socktype_protocol_hack()) {
Packit e9ba0d
		if (apply_socktype_protocol_hack(*res) < 0) {
Packit e9ba0d
			evutil_freeaddrinfo(*res);
Packit e9ba0d
			*res = NULL;
Packit e9ba0d
			return EVUTIL_EAI_MEMORY;
Packit e9ba0d
		}
Packit e9ba0d
	}
Packit e9ba0d
	return err;
Packit e9ba0d
#else
Packit e9ba0d
	int port=0, err;
Packit e9ba0d
	struct hostent *ent = NULL;
Packit e9ba0d
	struct evutil_addrinfo hints;
Packit e9ba0d
Packit e9ba0d
	if (hints_in) {
Packit e9ba0d
		memcpy(&hints, hints_in, sizeof(hints));
Packit e9ba0d
	} else {
Packit e9ba0d
		memset(&hints, 0, sizeof(hints));
Packit e9ba0d
		hints.ai_family = PF_UNSPEC;
Packit e9ba0d
	}
Packit e9ba0d
Packit e9ba0d
	evutil_adjust_hints_for_addrconfig(&hints);
Packit e9ba0d
Packit e9ba0d
	err = evutil_getaddrinfo_common(nodename, servname, &hints, res, &port);
Packit e9ba0d
	if (err != EVUTIL_EAI_NEED_RESOLVE) {
Packit e9ba0d
		/* We either succeeded or failed.  No need to continue */
Packit e9ba0d
		return err;
Packit e9ba0d
	}
Packit e9ba0d
Packit e9ba0d
	err = 0;
Packit e9ba0d
	/* Use any of the various gethostbyname_r variants as available. */
Packit e9ba0d
	{
Packit e9ba0d
#ifdef _EVENT_HAVE_GETHOSTBYNAME_R_6_ARG
Packit e9ba0d
		/* This one is what glibc provides. */
Packit e9ba0d
		char buf[2048];
Packit e9ba0d
		struct hostent hostent;
Packit e9ba0d
		int r;
Packit e9ba0d
		r = gethostbyname_r(nodename, &hostent, buf, sizeof(buf), &ent,
Packit e9ba0d
		    &err;;
Packit e9ba0d
#elif defined(_EVENT_HAVE_GETHOSTBYNAME_R_5_ARG)
Packit e9ba0d
		char buf[2048];
Packit e9ba0d
		struct hostent hostent;
Packit e9ba0d
		ent = gethostbyname_r(nodename, &hostent, buf, sizeof(buf),
Packit e9ba0d
		    &err;;
Packit e9ba0d
#elif defined(_EVENT_HAVE_GETHOSTBYNAME_R_3_ARG)
Packit e9ba0d
		struct hostent_data data;
Packit e9ba0d
		struct hostent hostent;
Packit e9ba0d
		memset(&data, 0, sizeof(data));
Packit e9ba0d
		err = gethostbyname_r(nodename, &hostent, &data);
Packit e9ba0d
		ent = err ? NULL : &hostent;
Packit e9ba0d
#else
Packit e9ba0d
		/* fall back to gethostbyname. */
Packit e9ba0d
		/* XXXX This needs a lock everywhere but Windows. */
Packit e9ba0d
		ent = gethostbyname(nodename);
Packit e9ba0d
#ifdef WIN32
Packit e9ba0d
		err = WSAGetLastError();
Packit e9ba0d
#else
Packit e9ba0d
		err = h_errno;
Packit e9ba0d
#endif
Packit e9ba0d
#endif
Packit e9ba0d
Packit e9ba0d
		/* Now we have either ent or err set. */
Packit e9ba0d
		if (!ent) {
Packit e9ba0d
			/* XXX is this right for windows ? */
Packit e9ba0d
			switch (err) {
Packit e9ba0d
			case TRY_AGAIN:
Packit e9ba0d
				return EVUTIL_EAI_AGAIN;
Packit e9ba0d
			case NO_RECOVERY:
Packit e9ba0d
			default:
Packit e9ba0d
				return EVUTIL_EAI_FAIL;
Packit e9ba0d
			case HOST_NOT_FOUND:
Packit e9ba0d
				return EVUTIL_EAI_NONAME;
Packit e9ba0d
			case NO_ADDRESS:
Packit e9ba0d
#if NO_DATA != NO_ADDRESS
Packit e9ba0d
			case NO_DATA:
Packit e9ba0d
#endif
Packit e9ba0d
				return EVUTIL_EAI_NODATA;
Packit e9ba0d
			}
Packit e9ba0d
		}
Packit e9ba0d
Packit e9ba0d
		if (ent->h_addrtype != hints.ai_family &&
Packit e9ba0d
		    hints.ai_family != PF_UNSPEC) {
Packit e9ba0d
			/* This wasn't the type we were hoping for.  Too bad
Packit e9ba0d
			 * we never had a chance to ask gethostbyname for what
Packit e9ba0d
			 * we wanted. */
Packit e9ba0d
			return EVUTIL_EAI_NONAME;
Packit e9ba0d
		}
Packit e9ba0d
Packit e9ba0d
		/* Make sure we got _some_ answers. */
Packit e9ba0d
		if (ent->h_length == 0)
Packit e9ba0d
			return EVUTIL_EAI_NODATA;
Packit e9ba0d
Packit e9ba0d
		/* If we got an address type we don't know how to make a
Packit e9ba0d
		   sockaddr for, give up. */
Packit e9ba0d
		if (ent->h_addrtype != PF_INET && ent->h_addrtype != PF_INET6)
Packit e9ba0d
			return EVUTIL_EAI_FAMILY;
Packit e9ba0d
Packit e9ba0d
		*res = addrinfo_from_hostent(ent, port, &hints);
Packit e9ba0d
		if (! *res)
Packit e9ba0d
			return EVUTIL_EAI_MEMORY;
Packit e9ba0d
	}
Packit e9ba0d
Packit e9ba0d
	return 0;
Packit e9ba0d
#endif
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
void
Packit e9ba0d
evutil_freeaddrinfo(struct evutil_addrinfo *ai)
Packit e9ba0d
{
Packit e9ba0d
#ifdef _EVENT_HAVE_GETADDRINFO
Packit e9ba0d
	if (!(ai->ai_flags & EVUTIL_AI_LIBEVENT_ALLOCATED)) {
Packit e9ba0d
		freeaddrinfo(ai);
Packit e9ba0d
		return;
Packit e9ba0d
	}
Packit e9ba0d
#endif
Packit e9ba0d
	while (ai) {
Packit e9ba0d
		struct evutil_addrinfo *next = ai->ai_next;
Packit e9ba0d
		if (ai->ai_canonname)
Packit e9ba0d
			mm_free(ai->ai_canonname);
Packit e9ba0d
		mm_free(ai);
Packit e9ba0d
		ai = next;
Packit e9ba0d
	}
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
static evdns_getaddrinfo_fn evdns_getaddrinfo_impl = NULL;
Packit e9ba0d
Packit e9ba0d
void
Packit e9ba0d
evutil_set_evdns_getaddrinfo_fn(evdns_getaddrinfo_fn fn)
Packit e9ba0d
{
Packit e9ba0d
	if (!evdns_getaddrinfo_impl)
Packit e9ba0d
		evdns_getaddrinfo_impl = fn;
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
/* Internal helper function: act like evdns_getaddrinfo if dns_base is set;
Packit e9ba0d
 * otherwise do a blocking resolve and pass the result to the callback in the
Packit e9ba0d
 * way that evdns_getaddrinfo would.
Packit e9ba0d
 */
Packit e9ba0d
int
Packit e9ba0d
evutil_getaddrinfo_async(struct evdns_base *dns_base,
Packit e9ba0d
    const char *nodename, const char *servname,
Packit e9ba0d
    const struct evutil_addrinfo *hints_in,
Packit e9ba0d
    void (*cb)(int, struct evutil_addrinfo *, void *), void *arg)
Packit e9ba0d
{
Packit e9ba0d
	if (dns_base && evdns_getaddrinfo_impl) {
Packit e9ba0d
		evdns_getaddrinfo_impl(
Packit e9ba0d
			dns_base, nodename, servname, hints_in, cb, arg);
Packit e9ba0d
	} else {
Packit e9ba0d
		struct evutil_addrinfo *ai=NULL;
Packit e9ba0d
		int err;
Packit e9ba0d
		err = evutil_getaddrinfo(nodename, servname, hints_in, &ai;;
Packit e9ba0d
		cb(err, ai, arg);
Packit e9ba0d
	}
Packit e9ba0d
	return 0;
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
const char *
Packit e9ba0d
evutil_gai_strerror(int err)
Packit e9ba0d
{
Packit e9ba0d
	/* As a sneaky side-benefit, this case statement will get most
Packit e9ba0d
	 * compilers to tell us if any of the error codes we defined
Packit e9ba0d
	 * conflict with the platform's native error codes. */
Packit e9ba0d
	switch (err) {
Packit e9ba0d
	case EVUTIL_EAI_CANCEL:
Packit e9ba0d
		return "Request canceled";
Packit e9ba0d
	case 0:
Packit e9ba0d
		return "No error";
Packit e9ba0d
Packit e9ba0d
	case EVUTIL_EAI_ADDRFAMILY:
Packit e9ba0d
		return "address family for nodename not supported";
Packit e9ba0d
	case EVUTIL_EAI_AGAIN:
Packit e9ba0d
		return "temporary failure in name resolution";
Packit e9ba0d
	case EVUTIL_EAI_BADFLAGS:
Packit e9ba0d
		return "invalid value for ai_flags";
Packit e9ba0d
	case EVUTIL_EAI_FAIL:
Packit e9ba0d
		return "non-recoverable failure in name resolution";
Packit e9ba0d
	case EVUTIL_EAI_FAMILY:
Packit e9ba0d
		return "ai_family not supported";
Packit e9ba0d
	case EVUTIL_EAI_MEMORY:
Packit e9ba0d
		return "memory allocation failure";
Packit e9ba0d
	case EVUTIL_EAI_NODATA:
Packit e9ba0d
		return "no address associated with nodename";
Packit e9ba0d
	case EVUTIL_EAI_NONAME:
Packit e9ba0d
		return "nodename nor servname provided, or not known";
Packit e9ba0d
	case EVUTIL_EAI_SERVICE:
Packit e9ba0d
		return "servname not supported for ai_socktype";
Packit e9ba0d
	case EVUTIL_EAI_SOCKTYPE:
Packit e9ba0d
		return "ai_socktype not supported";
Packit e9ba0d
	case EVUTIL_EAI_SYSTEM:
Packit e9ba0d
		return "system error";
Packit e9ba0d
	default:
Packit e9ba0d
#if defined(USE_NATIVE_GETADDRINFO) && defined(WIN32)
Packit e9ba0d
		return gai_strerrorA(err);
Packit e9ba0d
#elif defined(USE_NATIVE_GETADDRINFO)
Packit e9ba0d
		return gai_strerror(err);
Packit e9ba0d
#else
Packit e9ba0d
		return "Unknown error code";
Packit e9ba0d
#endif
Packit e9ba0d
	}
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
#ifdef WIN32
Packit e9ba0d
#define E(code, s) { code, (s " [" #code " ]") }
Packit e9ba0d
static struct { int code; const char *msg; } windows_socket_errors[] = {
Packit e9ba0d
  E(WSAEINTR, "Interrupted function call"),
Packit e9ba0d
  E(WSAEACCES, "Permission denied"),
Packit e9ba0d
  E(WSAEFAULT, "Bad address"),
Packit e9ba0d
  E(WSAEINVAL, "Invalid argument"),
Packit e9ba0d
  E(WSAEMFILE, "Too many open files"),
Packit e9ba0d
  E(WSAEWOULDBLOCK,  "Resource temporarily unavailable"),
Packit e9ba0d
  E(WSAEINPROGRESS, "Operation now in progress"),
Packit e9ba0d
  E(WSAEALREADY, "Operation already in progress"),
Packit e9ba0d
  E(WSAENOTSOCK, "Socket operation on nonsocket"),
Packit e9ba0d
  E(WSAEDESTADDRREQ, "Destination address required"),
Packit e9ba0d
  E(WSAEMSGSIZE, "Message too long"),
Packit e9ba0d
  E(WSAEPROTOTYPE, "Protocol wrong for socket"),
Packit e9ba0d
  E(WSAENOPROTOOPT, "Bad protocol option"),
Packit e9ba0d
  E(WSAEPROTONOSUPPORT, "Protocol not supported"),
Packit e9ba0d
  E(WSAESOCKTNOSUPPORT, "Socket type not supported"),
Packit e9ba0d
  /* What's the difference between NOTSUPP and NOSUPPORT? :) */
Packit e9ba0d
  E(WSAEOPNOTSUPP, "Operation not supported"),
Packit e9ba0d
  E(WSAEPFNOSUPPORT,  "Protocol family not supported"),
Packit e9ba0d
  E(WSAEAFNOSUPPORT, "Address family not supported by protocol family"),
Packit e9ba0d
  E(WSAEADDRINUSE, "Address already in use"),
Packit e9ba0d
  E(WSAEADDRNOTAVAIL, "Cannot assign requested address"),
Packit e9ba0d
  E(WSAENETDOWN, "Network is down"),
Packit e9ba0d
  E(WSAENETUNREACH, "Network is unreachable"),
Packit e9ba0d
  E(WSAENETRESET, "Network dropped connection on reset"),
Packit e9ba0d
  E(WSAECONNABORTED, "Software caused connection abort"),
Packit e9ba0d
  E(WSAECONNRESET, "Connection reset by peer"),
Packit e9ba0d
  E(WSAENOBUFS, "No buffer space available"),
Packit e9ba0d
  E(WSAEISCONN, "Socket is already connected"),
Packit e9ba0d
  E(WSAENOTCONN, "Socket is not connected"),
Packit e9ba0d
  E(WSAESHUTDOWN, "Cannot send after socket shutdown"),
Packit e9ba0d
  E(WSAETIMEDOUT, "Connection timed out"),
Packit e9ba0d
  E(WSAECONNREFUSED, "Connection refused"),
Packit e9ba0d
  E(WSAEHOSTDOWN, "Host is down"),
Packit e9ba0d
  E(WSAEHOSTUNREACH, "No route to host"),
Packit e9ba0d
  E(WSAEPROCLIM, "Too many processes"),
Packit e9ba0d
Packit e9ba0d
  /* Yes, some of these start with WSA, not WSAE. No, I don't know why. */
Packit e9ba0d
  E(WSASYSNOTREADY, "Network subsystem is unavailable"),
Packit e9ba0d
  E(WSAVERNOTSUPPORTED, "Winsock.dll out of range"),
Packit e9ba0d
  E(WSANOTINITIALISED, "Successful WSAStartup not yet performed"),
Packit e9ba0d
  E(WSAEDISCON, "Graceful shutdown now in progress"),
Packit e9ba0d
#ifdef WSATYPE_NOT_FOUND
Packit e9ba0d
  E(WSATYPE_NOT_FOUND, "Class type not found"),
Packit e9ba0d
#endif
Packit e9ba0d
  E(WSAHOST_NOT_FOUND, "Host not found"),
Packit e9ba0d
  E(WSATRY_AGAIN, "Nonauthoritative host not found"),
Packit e9ba0d
  E(WSANO_RECOVERY, "This is a nonrecoverable error"),
Packit e9ba0d
  E(WSANO_DATA, "Valid name, no data record of requested type)"),
Packit e9ba0d
Packit e9ba0d
  /* There are some more error codes whose numeric values are marked
Packit e9ba0d
   * OS dependent. They start with WSA_, apparently for the same
Packit e9ba0d
   * reason that practitioners of some craft traditions deliberately
Packit e9ba0d
   * introduce imperfections into their baskets and rugs "to allow the
Packit e9ba0d
   * evil spirits to escape."  If we catch them, then our binaries
Packit e9ba0d
   * might not report consistent results across versions of Windows.
Packit e9ba0d
   * Thus, I'm going to let them all fall through.
Packit e9ba0d
   */
Packit e9ba0d
  { -1, NULL },
Packit e9ba0d
};
Packit e9ba0d
#undef E
Packit e9ba0d
/** Equivalent to strerror, but for windows socket errors. */
Packit e9ba0d
const char *
Packit e9ba0d
evutil_socket_error_to_string(int errcode)
Packit e9ba0d
{
Packit e9ba0d
  /* XXXX Is there really no built-in function to do this? */
Packit e9ba0d
  int i;
Packit e9ba0d
  for (i=0; windows_socket_errors[i].code >= 0; ++i) {
Packit e9ba0d
    if (errcode == windows_socket_errors[i].code)
Packit e9ba0d
      return windows_socket_errors[i].msg;
Packit e9ba0d
  }
Packit e9ba0d
  return strerror(errcode);
Packit e9ba0d
}
Packit e9ba0d
#endif
Packit e9ba0d
Packit e9ba0d
int
Packit e9ba0d
evutil_snprintf(char *buf, size_t buflen, const char *format, ...)
Packit e9ba0d
{
Packit e9ba0d
	int r;
Packit e9ba0d
	va_list ap;
Packit e9ba0d
	va_start(ap, format);
Packit e9ba0d
	r = evutil_vsnprintf(buf, buflen, format, ap);
Packit e9ba0d
	va_end(ap);
Packit e9ba0d
	return r;
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
int
Packit e9ba0d
evutil_vsnprintf(char *buf, size_t buflen, const char *format, va_list ap)
Packit e9ba0d
{
Packit e9ba0d
	int r;
Packit e9ba0d
	if (!buflen)
Packit e9ba0d
		return 0;
Packit e9ba0d
#if defined(_MSC_VER) || defined(WIN32)
Packit e9ba0d
	r = _vsnprintf(buf, buflen, format, ap);
Packit e9ba0d
	if (r < 0)
Packit e9ba0d
		r = _vscprintf(format, ap);
Packit e9ba0d
#elif defined(sgi)
Packit e9ba0d
	/* Make sure we always use the correct vsnprintf on IRIX */
Packit e9ba0d
	extern int      _xpg5_vsnprintf(char * __restrict,
Packit e9ba0d
		__SGI_LIBC_NAMESPACE_QUALIFIER size_t,
Packit e9ba0d
		const char * __restrict, /* va_list */ char *);
Packit e9ba0d
Packit e9ba0d
	r = _xpg5_vsnprintf(buf, buflen, format, ap);
Packit e9ba0d
#else
Packit e9ba0d
	r = vsnprintf(buf, buflen, format, ap);
Packit e9ba0d
#endif
Packit e9ba0d
	buf[buflen-1] = '\0';
Packit e9ba0d
	return r;
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
#define USE_INTERNAL_NTOP
Packit e9ba0d
#define USE_INTERNAL_PTON
Packit e9ba0d
Packit e9ba0d
const char *
Packit e9ba0d
evutil_inet_ntop(int af, const void *src, char *dst, size_t len)
Packit e9ba0d
{
Packit e9ba0d
#if defined(_EVENT_HAVE_INET_NTOP) && !defined(USE_INTERNAL_NTOP)
Packit e9ba0d
	return inet_ntop(af, src, dst, len);
Packit e9ba0d
#else
Packit e9ba0d
	if (af == AF_INET) {
Packit e9ba0d
		const struct in_addr *in = src;
Packit e9ba0d
		const ev_uint32_t a = ntohl(in->s_addr);
Packit e9ba0d
		int r;
Packit e9ba0d
		r = evutil_snprintf(dst, len, "%d.%d.%d.%d",
Packit e9ba0d
		    (int)(ev_uint8_t)((a>>24)&0xff),
Packit e9ba0d
		    (int)(ev_uint8_t)((a>>16)&0xff),
Packit e9ba0d
		    (int)(ev_uint8_t)((a>>8 )&0xff),
Packit e9ba0d
		    (int)(ev_uint8_t)((a    )&0xff));
Packit e9ba0d
		if (r<0||(size_t)r>=len)
Packit e9ba0d
			return NULL;
Packit e9ba0d
		else
Packit e9ba0d
			return dst;
Packit e9ba0d
#ifdef AF_INET6
Packit e9ba0d
	} else if (af == AF_INET6) {
Packit e9ba0d
		const struct in6_addr *addr = src;
Packit e9ba0d
		char buf[64], *cp;
Packit e9ba0d
		int longestGapLen = 0, longestGapPos = -1, i,
Packit e9ba0d
			curGapPos = -1, curGapLen = 0;
Packit e9ba0d
		ev_uint16_t words[8];
Packit e9ba0d
		for (i = 0; i < 8; ++i) {
Packit e9ba0d
			words[i] =
Packit e9ba0d
			    (((ev_uint16_t)addr->s6_addr[2*i])<<8) + addr->s6_addr[2*i+1];
Packit e9ba0d
		}
Packit e9ba0d
		if (words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 &&
Packit e9ba0d
		    words[4] == 0 && ((words[5] == 0 && words[6] && words[7]) ||
Packit e9ba0d
			(words[5] == 0xffff))) {
Packit e9ba0d
			/* This is an IPv4 address. */
Packit e9ba0d
			if (words[5] == 0) {
Packit e9ba0d
				evutil_snprintf(buf, sizeof(buf), "::%d.%d.%d.%d",
Packit e9ba0d
				    addr->s6_addr[12], addr->s6_addr[13],
Packit e9ba0d
				    addr->s6_addr[14], addr->s6_addr[15]);
Packit e9ba0d
			} else {
Packit e9ba0d
				evutil_snprintf(buf, sizeof(buf), "::%x:%d.%d.%d.%d", words[5],
Packit e9ba0d
				    addr->s6_addr[12], addr->s6_addr[13],
Packit e9ba0d
				    addr->s6_addr[14], addr->s6_addr[15]);
Packit e9ba0d
			}
Packit e9ba0d
			if (strlen(buf) > len)
Packit e9ba0d
				return NULL;
Packit e9ba0d
			strlcpy(dst, buf, len);
Packit e9ba0d
			return dst;
Packit e9ba0d
		}
Packit e9ba0d
		i = 0;
Packit e9ba0d
		while (i < 8) {
Packit e9ba0d
			if (words[i] == 0) {
Packit e9ba0d
				curGapPos = i++;
Packit e9ba0d
				curGapLen = 1;
Packit e9ba0d
				while (i<8 && words[i] == 0) {
Packit e9ba0d
					++i; ++curGapLen;
Packit e9ba0d
				}
Packit e9ba0d
				if (curGapLen > longestGapLen) {
Packit e9ba0d
					longestGapPos = curGapPos;
Packit e9ba0d
					longestGapLen = curGapLen;
Packit e9ba0d
				}
Packit e9ba0d
			} else {
Packit e9ba0d
				++i;
Packit e9ba0d
			}
Packit e9ba0d
		}
Packit e9ba0d
		if (longestGapLen<=1)
Packit e9ba0d
			longestGapPos = -1;
Packit e9ba0d
Packit e9ba0d
		cp = buf;
Packit e9ba0d
		for (i = 0; i < 8; ++i) {
Packit e9ba0d
			if (words[i] == 0 && longestGapPos == i) {
Packit e9ba0d
				if (i == 0)
Packit e9ba0d
					*cp++ = ':';
Packit e9ba0d
				*cp++ = ':';
Packit e9ba0d
				while (i < 8 && words[i] == 0)
Packit e9ba0d
					++i;
Packit e9ba0d
				--i; /* to compensate for loop increment. */
Packit e9ba0d
			} else {
Packit e9ba0d
				evutil_snprintf(cp,
Packit e9ba0d
								sizeof(buf)-(cp-buf), "%x", (unsigned)words[i]);
Packit e9ba0d
				cp += strlen(cp);
Packit e9ba0d
				if (i != 7)
Packit e9ba0d
					*cp++ = ':';
Packit e9ba0d
			}
Packit e9ba0d
		}
Packit e9ba0d
		*cp = '\0';
Packit e9ba0d
		if (strlen(buf) > len)
Packit e9ba0d
			return NULL;
Packit e9ba0d
		strlcpy(dst, buf, len);
Packit e9ba0d
		return dst;
Packit e9ba0d
#endif
Packit e9ba0d
	} else {
Packit e9ba0d
		return NULL;
Packit e9ba0d
	}
Packit e9ba0d
#endif
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
int
Packit e9ba0d
evutil_inet_pton(int af, const char *src, void *dst)
Packit e9ba0d
{
Packit e9ba0d
#if defined(_EVENT_HAVE_INET_PTON) && !defined(USE_INTERNAL_PTON)
Packit e9ba0d
	return inet_pton(af, src, dst);
Packit e9ba0d
#else
Packit e9ba0d
	if (af == AF_INET) {
Packit e9ba0d
		int a,b,c,d;
Packit e9ba0d
		char more;
Packit e9ba0d
		struct in_addr *addr = dst;
Packit e9ba0d
		if (sscanf(src, "%d.%d.%d.%d%c", &a,&b,&c,&d,&more) != 4)
Packit e9ba0d
			return 0;
Packit e9ba0d
		if (a < 0 || a > 255) return 0;
Packit e9ba0d
		if (b < 0 || b > 255) return 0;
Packit e9ba0d
		if (c < 0 || c > 255) return 0;
Packit e9ba0d
		if (d < 0 || d > 255) return 0;
Packit e9ba0d
		addr->s_addr = htonl((a<<24) | (b<<16) | (c<<8) | d);
Packit e9ba0d
		return 1;
Packit e9ba0d
#ifdef AF_INET6
Packit e9ba0d
	} else if (af == AF_INET6) {
Packit e9ba0d
		struct in6_addr *out = dst;
Packit e9ba0d
		ev_uint16_t words[8];
Packit e9ba0d
		int gapPos = -1, i, setWords=0;
Packit e9ba0d
		const char *dot = strchr(src, '.');
Packit e9ba0d
		const char *eow; /* end of words. */
Packit e9ba0d
		if (dot == src)
Packit e9ba0d
			return 0;
Packit e9ba0d
		else if (!dot)
Packit e9ba0d
			eow = src+strlen(src);
Packit e9ba0d
		else {
Packit e9ba0d
			int byte1,byte2,byte3,byte4;
Packit e9ba0d
			char more;
Packit e9ba0d
			for (eow = dot-1; eow >= src && EVUTIL_ISDIGIT(*eow); --eow)
Packit e9ba0d
				;
Packit e9ba0d
			++eow;
Packit e9ba0d
Packit e9ba0d
			/* We use "scanf" because some platform inet_aton()s are too lax
Packit e9ba0d
			 * about IPv4 addresses of the form "1.2.3" */
Packit e9ba0d
			if (sscanf(eow, "%d.%d.%d.%d%c",
Packit e9ba0d
					   &byte1,&byte2,&byte3,&byte4,&more) != 4)
Packit e9ba0d
				return 0;
Packit e9ba0d
Packit e9ba0d
			if (byte1 > 255 || byte1 < 0 ||
Packit e9ba0d
				byte2 > 255 || byte2 < 0 ||
Packit e9ba0d
				byte3 > 255 || byte3 < 0 ||
Packit e9ba0d
				byte4 > 255 || byte4 < 0)
Packit e9ba0d
				return 0;
Packit e9ba0d
Packit e9ba0d
			words[6] = (byte1<<8) | byte2;
Packit e9ba0d
			words[7] = (byte3<<8) | byte4;
Packit e9ba0d
			setWords += 2;
Packit e9ba0d
		}
Packit e9ba0d
Packit e9ba0d
		i = 0;
Packit e9ba0d
		while (src < eow) {
Packit e9ba0d
			if (i > 7)
Packit e9ba0d
				return 0;
Packit e9ba0d
			if (EVUTIL_ISXDIGIT(*src)) {
Packit e9ba0d
				char *next;
Packit e9ba0d
				long r = strtol(src, &next, 16);
Packit e9ba0d
				if (next > 4+src)
Packit e9ba0d
					return 0;
Packit e9ba0d
				if (next == src)
Packit e9ba0d
					return 0;
Packit e9ba0d
				if (r<0 || r>65536)
Packit e9ba0d
					return 0;
Packit e9ba0d
Packit e9ba0d
				words[i++] = (ev_uint16_t)r;
Packit e9ba0d
				setWords++;
Packit e9ba0d
				src = next;
Packit e9ba0d
				if (*src != ':' && src != eow)
Packit e9ba0d
					return 0;
Packit e9ba0d
				++src;
Packit e9ba0d
			} else if (*src == ':' && i > 0 && gapPos==-1) {
Packit e9ba0d
				gapPos = i;
Packit e9ba0d
				++src;
Packit e9ba0d
			} else if (*src == ':' && i == 0 && src[1] == ':' && gapPos==-1) {
Packit e9ba0d
				gapPos = i;
Packit e9ba0d
				src += 2;
Packit e9ba0d
			} else {
Packit e9ba0d
				return 0;
Packit e9ba0d
			}
Packit e9ba0d
		}
Packit e9ba0d
Packit e9ba0d
		if (setWords > 8 ||
Packit e9ba0d
			(setWords == 8 && gapPos != -1) ||
Packit e9ba0d
			(setWords < 8 && gapPos == -1))
Packit e9ba0d
			return 0;
Packit e9ba0d
Packit e9ba0d
		if (gapPos >= 0) {
Packit e9ba0d
			int nToMove = setWords - (dot ? 2 : 0) - gapPos;
Packit e9ba0d
			int gapLen = 8 - setWords;
Packit e9ba0d
			/* assert(nToMove >= 0); */
Packit e9ba0d
			if (nToMove < 0)
Packit e9ba0d
				return -1; /* should be impossible */
Packit e9ba0d
			memmove(&words[gapPos+gapLen], &words[gapPos],
Packit e9ba0d
					sizeof(ev_uint16_t)*nToMove);
Packit e9ba0d
			memset(&words[gapPos], 0, sizeof(ev_uint16_t)*gapLen);
Packit e9ba0d
		}
Packit e9ba0d
		for (i = 0; i < 8; ++i) {
Packit e9ba0d
			out->s6_addr[2*i  ] = words[i] >> 8;
Packit e9ba0d
			out->s6_addr[2*i+1] = words[i] & 0xff;
Packit e9ba0d
		}
Packit e9ba0d
Packit e9ba0d
		return 1;
Packit e9ba0d
#endif
Packit e9ba0d
	} else {
Packit e9ba0d
		return -1;
Packit e9ba0d
	}
Packit e9ba0d
#endif
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
int
Packit e9ba0d
evutil_parse_sockaddr_port(const char *ip_as_string, struct sockaddr *out, int *outlen)
Packit e9ba0d
{
Packit e9ba0d
	int port;
Packit e9ba0d
	char buf[128];
Packit e9ba0d
	const char *cp, *addr_part, *port_part;
Packit e9ba0d
	int is_ipv6;
Packit e9ba0d
	/* recognized formats are:
Packit e9ba0d
	 * [ipv6]:port
Packit e9ba0d
	 * ipv6
Packit e9ba0d
	 * [ipv6]
Packit e9ba0d
	 * ipv4:port
Packit e9ba0d
	 * ipv4
Packit e9ba0d
	 */
Packit e9ba0d
Packit e9ba0d
	cp = strchr(ip_as_string, ':');
Packit e9ba0d
	if (*ip_as_string == '[') {
Packit e9ba0d
		int len;
Packit e9ba0d
		if (!(cp = strchr(ip_as_string, ']'))) {
Packit e9ba0d
			return -1;
Packit e9ba0d
		}
Packit e9ba0d
		len = (int) ( cp-(ip_as_string + 1) );
Packit e9ba0d
		if (len > (int)sizeof(buf)-1) {
Packit e9ba0d
			return -1;
Packit e9ba0d
		}
Packit e9ba0d
		memcpy(buf, ip_as_string+1, len);
Packit e9ba0d
		buf[len] = '\0';
Packit e9ba0d
		addr_part = buf;
Packit e9ba0d
		if (cp[1] == ':')
Packit e9ba0d
			port_part = cp+2;
Packit e9ba0d
		else
Packit e9ba0d
			port_part = NULL;
Packit e9ba0d
		is_ipv6 = 1;
Packit e9ba0d
	} else if (cp && strchr(cp+1, ':')) {
Packit e9ba0d
		is_ipv6 = 1;
Packit e9ba0d
		addr_part = ip_as_string;
Packit e9ba0d
		port_part = NULL;
Packit e9ba0d
	} else if (cp) {
Packit e9ba0d
		is_ipv6 = 0;
Packit e9ba0d
		if (cp - ip_as_string > (int)sizeof(buf)-1) {
Packit e9ba0d
			return -1;
Packit e9ba0d
		}
Packit e9ba0d
		memcpy(buf, ip_as_string, cp-ip_as_string);
Packit e9ba0d
		buf[cp-ip_as_string] = '\0';
Packit e9ba0d
		addr_part = buf;
Packit e9ba0d
		port_part = cp+1;
Packit e9ba0d
	} else {
Packit e9ba0d
		addr_part = ip_as_string;
Packit e9ba0d
		port_part = NULL;
Packit e9ba0d
		is_ipv6 = 0;
Packit e9ba0d
	}
Packit e9ba0d
Packit e9ba0d
	if (port_part == NULL) {
Packit e9ba0d
		port = 0;
Packit e9ba0d
	} else {
Packit e9ba0d
		port = atoi(port_part);
Packit e9ba0d
		if (port <= 0 || port > 65535) {
Packit e9ba0d
			return -1;
Packit e9ba0d
		}
Packit e9ba0d
	}
Packit e9ba0d
Packit e9ba0d
	if (!addr_part)
Packit e9ba0d
		return -1; /* Should be impossible. */
Packit e9ba0d
#ifdef AF_INET6
Packit e9ba0d
	if (is_ipv6)
Packit e9ba0d
	{
Packit e9ba0d
		struct sockaddr_in6 sin6;
Packit e9ba0d
		memset(&sin6, 0, sizeof(sin6));
Packit e9ba0d
#ifdef _EVENT_HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
Packit e9ba0d
		sin6.sin6_len = sizeof(sin6);
Packit e9ba0d
#endif
Packit e9ba0d
		sin6.sin6_family = AF_INET6;
Packit e9ba0d
		sin6.sin6_port = htons(port);
Packit e9ba0d
		if (1 != evutil_inet_pton(AF_INET6, addr_part, &sin6.sin6_addr))
Packit e9ba0d
			return -1;
Packit e9ba0d
		if ((int)sizeof(sin6) > *outlen)
Packit e9ba0d
			return -1;
Packit e9ba0d
		memset(out, 0, *outlen);
Packit e9ba0d
		memcpy(out, &sin6, sizeof(sin6));
Packit e9ba0d
		*outlen = sizeof(sin6);
Packit e9ba0d
		return 0;
Packit e9ba0d
	}
Packit e9ba0d
	else
Packit e9ba0d
#endif
Packit e9ba0d
	{
Packit e9ba0d
		struct sockaddr_in sin;
Packit e9ba0d
		memset(&sin, 0, sizeof(sin));
Packit e9ba0d
#ifdef _EVENT_HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
Packit e9ba0d
		sin.sin_len = sizeof(sin);
Packit e9ba0d
#endif
Packit e9ba0d
		sin.sin_family = AF_INET;
Packit e9ba0d
		sin.sin_port = htons(port);
Packit e9ba0d
		if (1 != evutil_inet_pton(AF_INET, addr_part, &sin.sin_addr))
Packit e9ba0d
			return -1;
Packit e9ba0d
		if ((int)sizeof(sin) > *outlen)
Packit e9ba0d
			return -1;
Packit e9ba0d
		memset(out, 0, *outlen);
Packit e9ba0d
		memcpy(out, &sin, sizeof(sin));
Packit e9ba0d
		*outlen = sizeof(sin);
Packit e9ba0d
		return 0;
Packit e9ba0d
	}
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
const char *
Packit e9ba0d
evutil_format_sockaddr_port(const struct sockaddr *sa, char *out, size_t outlen)
Packit e9ba0d
{
Packit e9ba0d
	char b[128];
Packit e9ba0d
	const char *res=NULL;
Packit e9ba0d
	int port;
Packit e9ba0d
	if (sa->sa_family == AF_INET) {
Packit e9ba0d
		const struct sockaddr_in *sin = (const struct sockaddr_in*)sa;
Packit e9ba0d
		res = evutil_inet_ntop(AF_INET, &sin->sin_addr,b,sizeof(b));
Packit e9ba0d
		port = ntohs(sin->sin_port);
Packit e9ba0d
		if (res) {
Packit e9ba0d
			evutil_snprintf(out, outlen, "%s:%d", b, port);
Packit e9ba0d
			return out;
Packit e9ba0d
		}
Packit e9ba0d
	} else if (sa->sa_family == AF_INET6) {
Packit e9ba0d
		const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6*)sa;
Packit e9ba0d
		res = evutil_inet_ntop(AF_INET6, &sin6->sin6_addr,b,sizeof(b));
Packit e9ba0d
		port = ntohs(sin6->sin6_port);
Packit e9ba0d
		if (res) {
Packit e9ba0d
			evutil_snprintf(out, outlen, "[%s]:%d", b, port);
Packit e9ba0d
			return out;
Packit e9ba0d
		}
Packit e9ba0d
	}
Packit e9ba0d
Packit e9ba0d
	evutil_snprintf(out, outlen, "<addr with socktype %d>",
Packit e9ba0d
	    (int)sa->sa_family);
Packit e9ba0d
	return out;
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
int
Packit e9ba0d
evutil_sockaddr_cmp(const struct sockaddr *sa1, const struct sockaddr *sa2,
Packit e9ba0d
    int include_port)
Packit e9ba0d
{
Packit e9ba0d
	int r;
Packit e9ba0d
	if (0 != (r = (sa1->sa_family - sa2->sa_family)))
Packit e9ba0d
		return r;
Packit e9ba0d
Packit e9ba0d
	if (sa1->sa_family == AF_INET) {
Packit e9ba0d
		const struct sockaddr_in *sin1, *sin2;
Packit e9ba0d
		sin1 = (const struct sockaddr_in *)sa1;
Packit e9ba0d
		sin2 = (const struct sockaddr_in *)sa2;
Packit e9ba0d
		if (sin1->sin_addr.s_addr < sin2->sin_addr.s_addr)
Packit e9ba0d
			return -1;
Packit e9ba0d
		else if (sin1->sin_addr.s_addr > sin2->sin_addr.s_addr)
Packit e9ba0d
			return 1;
Packit e9ba0d
		else if (include_port &&
Packit e9ba0d
		    (r = ((int)sin1->sin_port - (int)sin2->sin_port)))
Packit e9ba0d
			return r;
Packit e9ba0d
		else
Packit e9ba0d
			return 0;
Packit e9ba0d
	}
Packit e9ba0d
#ifdef AF_INET6
Packit e9ba0d
	else if (sa1->sa_family == AF_INET6) {
Packit e9ba0d
		const struct sockaddr_in6 *sin1, *sin2;
Packit e9ba0d
		sin1 = (const struct sockaddr_in6 *)sa1;
Packit e9ba0d
		sin2 = (const struct sockaddr_in6 *)sa2;
Packit e9ba0d
		if ((r = memcmp(sin1->sin6_addr.s6_addr, sin2->sin6_addr.s6_addr, 16)))
Packit e9ba0d
			return r;
Packit e9ba0d
		else if (include_port &&
Packit e9ba0d
		    (r = ((int)sin1->sin6_port - (int)sin2->sin6_port)))
Packit e9ba0d
			return r;
Packit e9ba0d
		else
Packit e9ba0d
			return 0;
Packit e9ba0d
	}
Packit e9ba0d
#endif
Packit e9ba0d
	return 1;
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
/* Tables to implement ctypes-replacement EVUTIL_IS*() functions.  Each table
Packit e9ba0d
 * has 256 bits to look up whether a character is in some set or not.  This
Packit e9ba0d
 * fails on non-ASCII platforms, but so does every other place where we
Packit e9ba0d
 * take a char and write it onto the network.
Packit e9ba0d
 **/
Packit e9ba0d
static const ev_uint32_t EVUTIL_ISALPHA_TABLE[8] =
Packit e9ba0d
  { 0, 0, 0x7fffffe, 0x7fffffe, 0, 0, 0, 0 };
Packit e9ba0d
static const ev_uint32_t EVUTIL_ISALNUM_TABLE[8] =
Packit e9ba0d
  { 0, 0x3ff0000, 0x7fffffe, 0x7fffffe, 0, 0, 0, 0 };
Packit e9ba0d
static const ev_uint32_t EVUTIL_ISSPACE_TABLE[8] = { 0x3e00, 0x1, 0, 0, 0, 0, 0, 0 };
Packit e9ba0d
static const ev_uint32_t EVUTIL_ISXDIGIT_TABLE[8] =
Packit e9ba0d
  { 0, 0x3ff0000, 0x7e, 0x7e, 0, 0, 0, 0 };
Packit e9ba0d
static const ev_uint32_t EVUTIL_ISDIGIT_TABLE[8] = { 0, 0x3ff0000, 0, 0, 0, 0, 0, 0 };
Packit e9ba0d
static const ev_uint32_t EVUTIL_ISPRINT_TABLE[8] =
Packit e9ba0d
  { 0, 0xffffffff, 0xffffffff, 0x7fffffff, 0, 0, 0, 0x0 };
Packit e9ba0d
static const ev_uint32_t EVUTIL_ISUPPER_TABLE[8] = { 0, 0, 0x7fffffe, 0, 0, 0, 0, 0 };
Packit e9ba0d
static const ev_uint32_t EVUTIL_ISLOWER_TABLE[8] = { 0, 0, 0, 0x7fffffe, 0, 0, 0, 0 };
Packit e9ba0d
/* Upper-casing and lowercasing tables to map characters to upper/lowercase
Packit e9ba0d
 * equivalents. */
Packit e9ba0d
static const unsigned char EVUTIL_TOUPPER_TABLE[256] = {
Packit e9ba0d
  0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
Packit e9ba0d
  16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
Packit e9ba0d
  32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,
Packit e9ba0d
  48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,
Packit e9ba0d
  64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,
Packit e9ba0d
  80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,
Packit e9ba0d
  96,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,
Packit e9ba0d
  80,81,82,83,84,85,86,87,88,89,90,123,124,125,126,127,
Packit e9ba0d
  128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
Packit e9ba0d
  144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
Packit e9ba0d
  160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
Packit e9ba0d
  176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
Packit e9ba0d
  192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
Packit e9ba0d
  208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
Packit e9ba0d
  224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
Packit e9ba0d
  240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,
Packit e9ba0d
};
Packit e9ba0d
static const unsigned char EVUTIL_TOLOWER_TABLE[256] = {
Packit e9ba0d
  0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
Packit e9ba0d
  16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
Packit e9ba0d
  32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,
Packit e9ba0d
  48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,
Packit e9ba0d
  64,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,
Packit e9ba0d
  112,113,114,115,116,117,118,119,120,121,122,91,92,93,94,95,
Packit e9ba0d
  96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,
Packit e9ba0d
  112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
Packit e9ba0d
  128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
Packit e9ba0d
  144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
Packit e9ba0d
  160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
Packit e9ba0d
  176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
Packit e9ba0d
  192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
Packit e9ba0d
  208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
Packit e9ba0d
  224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
Packit e9ba0d
  240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,
Packit e9ba0d
};
Packit e9ba0d
Packit e9ba0d
#define IMPL_CTYPE_FN(name)						\
Packit e9ba0d
	int EVUTIL_##name(char c) {					\
Packit e9ba0d
		ev_uint8_t u = c;					\
Packit e9ba0d
		return !!(EVUTIL_##name##_TABLE[(u >> 5) & 7] & (1 << (u & 31))); \
Packit e9ba0d
	}
Packit e9ba0d
IMPL_CTYPE_FN(ISALPHA)
Packit e9ba0d
IMPL_CTYPE_FN(ISALNUM)
Packit e9ba0d
IMPL_CTYPE_FN(ISSPACE)
Packit e9ba0d
IMPL_CTYPE_FN(ISDIGIT)
Packit e9ba0d
IMPL_CTYPE_FN(ISXDIGIT)
Packit e9ba0d
IMPL_CTYPE_FN(ISPRINT)
Packit e9ba0d
IMPL_CTYPE_FN(ISLOWER)
Packit e9ba0d
IMPL_CTYPE_FN(ISUPPER)
Packit e9ba0d
Packit e9ba0d
char EVUTIL_TOLOWER(char c)
Packit e9ba0d
{
Packit e9ba0d
	return ((char)EVUTIL_TOLOWER_TABLE[(ev_uint8_t)c]);
Packit e9ba0d
}
Packit e9ba0d
char EVUTIL_TOUPPER(char c)
Packit e9ba0d
{
Packit e9ba0d
	return ((char)EVUTIL_TOUPPER_TABLE[(ev_uint8_t)c]);
Packit e9ba0d
}
Packit e9ba0d
int
Packit e9ba0d
evutil_ascii_strcasecmp(const char *s1, const char *s2)
Packit e9ba0d
{
Packit e9ba0d
	char c1, c2;
Packit e9ba0d
	while (1) {
Packit e9ba0d
		c1 = EVUTIL_TOLOWER(*s1++);
Packit e9ba0d
		c2 = EVUTIL_TOLOWER(*s2++);
Packit e9ba0d
		if (c1 < c2)
Packit e9ba0d
			return -1;
Packit e9ba0d
		else if (c1 > c2)
Packit e9ba0d
			return 1;
Packit e9ba0d
		else if (c1 == 0)
Packit e9ba0d
			return 0;
Packit e9ba0d
	}
Packit e9ba0d
}
Packit e9ba0d
int evutil_ascii_strncasecmp(const char *s1, const char *s2, size_t n)
Packit e9ba0d
{
Packit e9ba0d
	char c1, c2;
Packit e9ba0d
	while (n--) {
Packit e9ba0d
		c1 = EVUTIL_TOLOWER(*s1++);
Packit e9ba0d
		c2 = EVUTIL_TOLOWER(*s2++);
Packit e9ba0d
		if (c1 < c2)
Packit e9ba0d
			return -1;
Packit e9ba0d
		else if (c1 > c2)
Packit e9ba0d
			return 1;
Packit e9ba0d
		else if (c1 == 0)
Packit e9ba0d
			return 0;
Packit e9ba0d
	}
Packit e9ba0d
	return 0;
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
static int
Packit e9ba0d
evutil_issetugid(void)
Packit e9ba0d
{
Packit e9ba0d
#ifdef _EVENT_HAVE_ISSETUGID
Packit e9ba0d
	return issetugid();
Packit e9ba0d
#else
Packit e9ba0d
Packit e9ba0d
#ifdef _EVENT_HAVE_GETEUID
Packit e9ba0d
	if (getuid() != geteuid())
Packit e9ba0d
		return 1;
Packit e9ba0d
#endif
Packit e9ba0d
#ifdef _EVENT_HAVE_GETEGID
Packit e9ba0d
	if (getgid() != getegid())
Packit e9ba0d
		return 1;
Packit e9ba0d
#endif
Packit e9ba0d
	return 0;
Packit e9ba0d
#endif
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
const char *
Packit e9ba0d
evutil_getenv(const char *varname)
Packit e9ba0d
{
Packit e9ba0d
	if (evutil_issetugid())
Packit e9ba0d
		return NULL;
Packit e9ba0d
Packit e9ba0d
	return getenv(varname);
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
long
Packit e9ba0d
_evutil_weakrand(void)
Packit e9ba0d
{
Packit e9ba0d
#ifdef WIN32
Packit e9ba0d
	return rand();
Packit e9ba0d
#else
Packit e9ba0d
	return random();
Packit e9ba0d
#endif
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
/**
Packit e9ba0d
 * Volatile pointer to memset: we use this to keep the compiler from
Packit e9ba0d
 * eliminating our call to memset.
Packit e9ba0d
 */
Packit e9ba0d
void * (*volatile evutil_memset_volatile_)(void *, int, size_t) = memset;
Packit e9ba0d
Packit e9ba0d
void
Packit e9ba0d
evutil_memclear_(void *mem, size_t len)
Packit e9ba0d
{
Packit e9ba0d
	evutil_memset_volatile_(mem, 0, len);
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
int
Packit e9ba0d
evutil_sockaddr_is_loopback(const struct sockaddr *addr)
Packit e9ba0d
{
Packit e9ba0d
	static const char LOOPBACK_S6[16] =
Packit e9ba0d
	    "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1";
Packit e9ba0d
	if (addr->sa_family == AF_INET) {
Packit e9ba0d
		struct sockaddr_in *sin = (struct sockaddr_in *)addr;
Packit e9ba0d
		return (ntohl(sin->sin_addr.s_addr) & 0xff000000) == 0x7f000000;
Packit e9ba0d
	} else if (addr->sa_family == AF_INET6) {
Packit e9ba0d
		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr;
Packit e9ba0d
		return !memcmp(sin6->sin6_addr.s6_addr, LOOPBACK_S6, 16);
Packit e9ba0d
	}
Packit e9ba0d
	return 0;
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
#define MAX_SECONDS_IN_MSEC_LONG \
Packit e9ba0d
	(((LONG_MAX) - 999) / 1000)
Packit e9ba0d
Packit e9ba0d
long
Packit e9ba0d
evutil_tv_to_msec(const struct timeval *tv)
Packit e9ba0d
{
Packit e9ba0d
	if (tv->tv_usec > 1000000 || tv->tv_sec > MAX_SECONDS_IN_MSEC_LONG)
Packit e9ba0d
		return -1;
Packit e9ba0d
Packit e9ba0d
	return (tv->tv_sec * 1000) + ((tv->tv_usec + 999) / 1000);
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
int
Packit e9ba0d
evutil_hex_char_to_int(char c)
Packit e9ba0d
{
Packit e9ba0d
	switch(c)
Packit e9ba0d
	{
Packit e9ba0d
		case '0': return 0;
Packit e9ba0d
		case '1': return 1;
Packit e9ba0d
		case '2': return 2;
Packit e9ba0d
		case '3': return 3;
Packit e9ba0d
		case '4': return 4;
Packit e9ba0d
		case '5': return 5;
Packit e9ba0d
		case '6': return 6;
Packit e9ba0d
		case '7': return 7;
Packit e9ba0d
		case '8': return 8;
Packit e9ba0d
		case '9': return 9;
Packit e9ba0d
		case 'A': case 'a': return 10;
Packit e9ba0d
		case 'B': case 'b': return 11;
Packit e9ba0d
		case 'C': case 'c': return 12;
Packit e9ba0d
		case 'D': case 'd': return 13;
Packit e9ba0d
		case 'E': case 'e': return 14;
Packit e9ba0d
		case 'F': case 'f': return 15;
Packit e9ba0d
	}
Packit e9ba0d
	return -1;
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
#ifdef WIN32
Packit e9ba0d
HANDLE
Packit e9ba0d
evutil_load_windows_system_library(const TCHAR *library_name)
Packit e9ba0d
{
Packit e9ba0d
  TCHAR path[MAX_PATH];
Packit e9ba0d
  unsigned n;
Packit e9ba0d
  n = GetSystemDirectory(path, MAX_PATH);
Packit e9ba0d
  if (n == 0 || n + _tcslen(library_name) + 2 >= MAX_PATH)
Packit e9ba0d
    return 0;
Packit e9ba0d
  _tcscat(path, TEXT("\\"));
Packit e9ba0d
  _tcscat(path, library_name);
Packit e9ba0d
  return LoadLibrary(path);
Packit e9ba0d
}
Packit e9ba0d
#endif
Packit e9ba0d