ipc/chromium/src/third_party/libevent/evutil.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /*
michael@0 2 * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
michael@0 3 *
michael@0 4 * Redistribution and use in source and binary forms, with or without
michael@0 5 * modification, are permitted provided that the following conditions
michael@0 6 * are met:
michael@0 7 * 1. Redistributions of source code must retain the above copyright
michael@0 8 * notice, this list of conditions and the following disclaimer.
michael@0 9 * 2. Redistributions in binary form must reproduce the above copyright
michael@0 10 * notice, this list of conditions and the following disclaimer in the
michael@0 11 * documentation and/or other materials provided with the distribution.
michael@0 12 * 3. The name of the author may not be used to endorse or promote products
michael@0 13 * derived from this software without specific prior written permission.
michael@0 14 *
michael@0 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
michael@0 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
michael@0 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
michael@0 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
michael@0 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
michael@0 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
michael@0 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
michael@0 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
michael@0 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
michael@0 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
michael@0 25 */
michael@0 26
michael@0 27 #include "event2/event-config.h"
michael@0 28
michael@0 29 #define _GNU_SOURCE
michael@0 30
michael@0 31 #ifdef WIN32
michael@0 32 #include <winsock2.h>
michael@0 33 #include <ws2tcpip.h>
michael@0 34 #define WIN32_LEAN_AND_MEAN
michael@0 35 #include <windows.h>
michael@0 36 #undef WIN32_LEAN_AND_MEAN
michael@0 37 #include <io.h>
michael@0 38 #include <tchar.h>
michael@0 39 #endif
michael@0 40
michael@0 41 #include <sys/types.h>
michael@0 42 #ifdef _EVENT_HAVE_SYS_SOCKET_H
michael@0 43 #include <sys/socket.h>
michael@0 44 #endif
michael@0 45 #ifdef _EVENT_HAVE_UNISTD_H
michael@0 46 #include <unistd.h>
michael@0 47 #endif
michael@0 48 #ifdef _EVENT_HAVE_FCNTL_H
michael@0 49 #include <fcntl.h>
michael@0 50 #endif
michael@0 51 #ifdef _EVENT_HAVE_STDLIB_H
michael@0 52 #include <stdlib.h>
michael@0 53 #endif
michael@0 54 #include <errno.h>
michael@0 55 #include <limits.h>
michael@0 56 #include <stdio.h>
michael@0 57 #include <string.h>
michael@0 58 #ifdef _EVENT_HAVE_NETINET_IN_H
michael@0 59 #include <netinet/in.h>
michael@0 60 #endif
michael@0 61 #ifdef _EVENT_HAVE_NETINET_IN6_H
michael@0 62 #include <netinet/in6.h>
michael@0 63 #endif
michael@0 64 #ifdef _EVENT_HAVE_ARPA_INET_H
michael@0 65 #include <arpa/inet.h>
michael@0 66 #endif
michael@0 67
michael@0 68 #ifndef _EVENT_HAVE_GETTIMEOFDAY
michael@0 69 #include <sys/timeb.h>
michael@0 70 #include <time.h>
michael@0 71 #endif
michael@0 72 #include <sys/stat.h>
michael@0 73
michael@0 74 #include "event2/util.h"
michael@0 75 #include "util-internal.h"
michael@0 76 #include "log-internal.h"
michael@0 77 #include "mm-internal.h"
michael@0 78
michael@0 79 #include "strlcpy-internal.h"
michael@0 80 #include "ipv6-internal.h"
michael@0 81
michael@0 82 #ifdef WIN32
michael@0 83 #define open _open
michael@0 84 #define read _read
michael@0 85 #define close _close
michael@0 86 #define fstat _fstati64
michael@0 87 #define stat _stati64
michael@0 88 #define mode_t int
michael@0 89 #endif
michael@0 90
michael@0 91 int
michael@0 92 evutil_open_closeonexec(const char *pathname, int flags, unsigned mode)
michael@0 93 {
michael@0 94 int fd;
michael@0 95
michael@0 96 #ifdef O_CLOEXEC
michael@0 97 flags |= O_CLOEXEC;
michael@0 98 #endif
michael@0 99
michael@0 100 if (flags & O_CREAT)
michael@0 101 fd = open(pathname, flags, (mode_t)mode);
michael@0 102 else
michael@0 103 fd = open(pathname, flags);
michael@0 104 if (fd < 0)
michael@0 105 return -1;
michael@0 106
michael@0 107 #if !defined(O_CLOEXEC) && defined(FD_CLOEXEC)
michael@0 108 if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0)
michael@0 109 return -1;
michael@0 110 #endif
michael@0 111
michael@0 112 return fd;
michael@0 113 }
michael@0 114
michael@0 115 /**
michael@0 116 Read the contents of 'filename' into a newly allocated NUL-terminated
michael@0 117 string. Set *content_out to hold this string, and *len_out to hold its
michael@0 118 length (not including the appended NUL). If 'is_binary', open the file in
michael@0 119 binary mode.
michael@0 120
michael@0 121 Returns 0 on success, -1 if the open fails, and -2 for all other failures.
michael@0 122
michael@0 123 Used internally only; may go away in a future version.
michael@0 124 */
michael@0 125 int
michael@0 126 evutil_read_file(const char *filename, char **content_out, size_t *len_out,
michael@0 127 int is_binary)
michael@0 128 {
michael@0 129 int fd, r;
michael@0 130 struct stat st;
michael@0 131 char *mem;
michael@0 132 size_t read_so_far=0;
michael@0 133 int mode = O_RDONLY;
michael@0 134
michael@0 135 EVUTIL_ASSERT(content_out);
michael@0 136 EVUTIL_ASSERT(len_out);
michael@0 137 *content_out = NULL;
michael@0 138 *len_out = 0;
michael@0 139
michael@0 140 #ifdef O_BINARY
michael@0 141 if (is_binary)
michael@0 142 mode |= O_BINARY;
michael@0 143 #endif
michael@0 144
michael@0 145 fd = evutil_open_closeonexec(filename, mode, 0);
michael@0 146 if (fd < 0)
michael@0 147 return -1;
michael@0 148 if (fstat(fd, &st) || st.st_size < 0 ||
michael@0 149 st.st_size > EV_SSIZE_MAX-1 ) {
michael@0 150 close(fd);
michael@0 151 return -2;
michael@0 152 }
michael@0 153 mem = mm_malloc((size_t)st.st_size + 1);
michael@0 154 if (!mem) {
michael@0 155 close(fd);
michael@0 156 return -2;
michael@0 157 }
michael@0 158 read_so_far = 0;
michael@0 159 #ifdef WIN32
michael@0 160 #define N_TO_READ(x) ((x) > INT_MAX) ? INT_MAX : ((int)(x))
michael@0 161 #else
michael@0 162 #define N_TO_READ(x) (x)
michael@0 163 #endif
michael@0 164 while ((r = read(fd, mem+read_so_far, N_TO_READ(st.st_size - read_so_far))) > 0) {
michael@0 165 read_so_far += r;
michael@0 166 if (read_so_far >= (size_t)st.st_size)
michael@0 167 break;
michael@0 168 EVUTIL_ASSERT(read_so_far < (size_t)st.st_size);
michael@0 169 }
michael@0 170 close(fd);
michael@0 171 if (r < 0) {
michael@0 172 mm_free(mem);
michael@0 173 return -2;
michael@0 174 }
michael@0 175 mem[read_so_far] = 0;
michael@0 176
michael@0 177 *len_out = read_so_far;
michael@0 178 *content_out = mem;
michael@0 179 return 0;
michael@0 180 }
michael@0 181
michael@0 182 int
michael@0 183 evutil_socketpair(int family, int type, int protocol, evutil_socket_t fd[2])
michael@0 184 {
michael@0 185 #ifndef WIN32
michael@0 186 return socketpair(family, type, protocol, fd);
michael@0 187 #else
michael@0 188 return evutil_ersatz_socketpair(family, type, protocol, fd);
michael@0 189 #endif
michael@0 190 }
michael@0 191
michael@0 192 int
michael@0 193 evutil_ersatz_socketpair(int family, int type, int protocol,
michael@0 194 evutil_socket_t fd[2])
michael@0 195 {
michael@0 196 /* This code is originally from Tor. Used with permission. */
michael@0 197
michael@0 198 /* This socketpair does not work when localhost is down. So
michael@0 199 * it's really not the same thing at all. But it's close enough
michael@0 200 * for now, and really, when localhost is down sometimes, we
michael@0 201 * have other problems too.
michael@0 202 */
michael@0 203 #ifdef WIN32
michael@0 204 #define ERR(e) WSA##e
michael@0 205 #else
michael@0 206 #define ERR(e) e
michael@0 207 #endif
michael@0 208 evutil_socket_t listener = -1;
michael@0 209 evutil_socket_t connector = -1;
michael@0 210 evutil_socket_t acceptor = -1;
michael@0 211 struct sockaddr_in listen_addr;
michael@0 212 struct sockaddr_in connect_addr;
michael@0 213 ev_socklen_t size;
michael@0 214 int saved_errno = -1;
michael@0 215
michael@0 216 if (protocol
michael@0 217 || (family != AF_INET
michael@0 218 #ifdef AF_UNIX
michael@0 219 && family != AF_UNIX
michael@0 220 #endif
michael@0 221 )) {
michael@0 222 EVUTIL_SET_SOCKET_ERROR(ERR(EAFNOSUPPORT));
michael@0 223 return -1;
michael@0 224 }
michael@0 225 if (!fd) {
michael@0 226 EVUTIL_SET_SOCKET_ERROR(ERR(EINVAL));
michael@0 227 return -1;
michael@0 228 }
michael@0 229
michael@0 230 listener = socket(AF_INET, type, 0);
michael@0 231 if (listener < 0)
michael@0 232 return -1;
michael@0 233 memset(&listen_addr, 0, sizeof(listen_addr));
michael@0 234 listen_addr.sin_family = AF_INET;
michael@0 235 listen_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
michael@0 236 listen_addr.sin_port = 0; /* kernel chooses port. */
michael@0 237 if (bind(listener, (struct sockaddr *) &listen_addr, sizeof (listen_addr))
michael@0 238 == -1)
michael@0 239 goto tidy_up_and_fail;
michael@0 240 if (listen(listener, 1) == -1)
michael@0 241 goto tidy_up_and_fail;
michael@0 242
michael@0 243 connector = socket(AF_INET, type, 0);
michael@0 244 if (connector < 0)
michael@0 245 goto tidy_up_and_fail;
michael@0 246 /* We want to find out the port number to connect to. */
michael@0 247 size = sizeof(connect_addr);
michael@0 248 if (getsockname(listener, (struct sockaddr *) &connect_addr, &size) == -1)
michael@0 249 goto tidy_up_and_fail;
michael@0 250 if (size != sizeof (connect_addr))
michael@0 251 goto abort_tidy_up_and_fail;
michael@0 252 if (connect(connector, (struct sockaddr *) &connect_addr,
michael@0 253 sizeof(connect_addr)) == -1)
michael@0 254 goto tidy_up_and_fail;
michael@0 255
michael@0 256 size = sizeof(listen_addr);
michael@0 257 acceptor = accept(listener, (struct sockaddr *) &listen_addr, &size);
michael@0 258 if (acceptor < 0)
michael@0 259 goto tidy_up_and_fail;
michael@0 260 if (size != sizeof(listen_addr))
michael@0 261 goto abort_tidy_up_and_fail;
michael@0 262 evutil_closesocket(listener);
michael@0 263 /* Now check we are talking to ourself by matching port and host on the
michael@0 264 two sockets. */
michael@0 265 if (getsockname(connector, (struct sockaddr *) &connect_addr, &size) == -1)
michael@0 266 goto tidy_up_and_fail;
michael@0 267 if (size != sizeof (connect_addr)
michael@0 268 || listen_addr.sin_family != connect_addr.sin_family
michael@0 269 || listen_addr.sin_addr.s_addr != connect_addr.sin_addr.s_addr
michael@0 270 || listen_addr.sin_port != connect_addr.sin_port)
michael@0 271 goto abort_tidy_up_and_fail;
michael@0 272 fd[0] = connector;
michael@0 273 fd[1] = acceptor;
michael@0 274
michael@0 275 return 0;
michael@0 276
michael@0 277 abort_tidy_up_and_fail:
michael@0 278 saved_errno = ERR(ECONNABORTED);
michael@0 279 tidy_up_and_fail:
michael@0 280 if (saved_errno < 0)
michael@0 281 saved_errno = EVUTIL_SOCKET_ERROR();
michael@0 282 if (listener != -1)
michael@0 283 evutil_closesocket(listener);
michael@0 284 if (connector != -1)
michael@0 285 evutil_closesocket(connector);
michael@0 286 if (acceptor != -1)
michael@0 287 evutil_closesocket(acceptor);
michael@0 288
michael@0 289 EVUTIL_SET_SOCKET_ERROR(saved_errno);
michael@0 290 return -1;
michael@0 291 #undef ERR
michael@0 292 }
michael@0 293
michael@0 294 int
michael@0 295 evutil_make_socket_nonblocking(evutil_socket_t fd)
michael@0 296 {
michael@0 297 #ifdef WIN32
michael@0 298 {
michael@0 299 u_long nonblocking = 1;
michael@0 300 if (ioctlsocket(fd, FIONBIO, &nonblocking) == SOCKET_ERROR) {
michael@0 301 event_sock_warn(fd, "fcntl(%d, F_GETFL)", (int)fd);
michael@0 302 return -1;
michael@0 303 }
michael@0 304 }
michael@0 305 #else
michael@0 306 {
michael@0 307 int flags;
michael@0 308 if ((flags = fcntl(fd, F_GETFL, NULL)) < 0) {
michael@0 309 event_warn("fcntl(%d, F_GETFL)", fd);
michael@0 310 return -1;
michael@0 311 }
michael@0 312 if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
michael@0 313 event_warn("fcntl(%d, F_SETFL)", fd);
michael@0 314 return -1;
michael@0 315 }
michael@0 316 }
michael@0 317 #endif
michael@0 318 return 0;
michael@0 319 }
michael@0 320
michael@0 321 int
michael@0 322 evutil_make_listen_socket_reuseable(evutil_socket_t sock)
michael@0 323 {
michael@0 324 #ifndef WIN32
michael@0 325 int one = 1;
michael@0 326 /* REUSEADDR on Unix means, "don't hang on to this address after the
michael@0 327 * listener is closed." On Windows, though, it means "don't keep other
michael@0 328 * processes from binding to this address while we're using it. */
michael@0 329 return setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*) &one,
michael@0 330 (ev_socklen_t)sizeof(one));
michael@0 331 #else
michael@0 332 return 0;
michael@0 333 #endif
michael@0 334 }
michael@0 335
michael@0 336 int
michael@0 337 evutil_make_socket_closeonexec(evutil_socket_t fd)
michael@0 338 {
michael@0 339 #if !defined(WIN32) && defined(_EVENT_HAVE_SETFD)
michael@0 340 int flags;
michael@0 341 if ((flags = fcntl(fd, F_GETFD, NULL)) < 0) {
michael@0 342 event_warn("fcntl(%d, F_GETFD)", fd);
michael@0 343 return -1;
michael@0 344 }
michael@0 345 if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) {
michael@0 346 event_warn("fcntl(%d, F_SETFD)", fd);
michael@0 347 return -1;
michael@0 348 }
michael@0 349 #endif
michael@0 350 return 0;
michael@0 351 }
michael@0 352
michael@0 353 int
michael@0 354 evutil_closesocket(evutil_socket_t sock)
michael@0 355 {
michael@0 356 #ifndef WIN32
michael@0 357 return close(sock);
michael@0 358 #else
michael@0 359 return closesocket(sock);
michael@0 360 #endif
michael@0 361 }
michael@0 362
michael@0 363 ev_int64_t
michael@0 364 evutil_strtoll(const char *s, char **endptr, int base)
michael@0 365 {
michael@0 366 #ifdef _EVENT_HAVE_STRTOLL
michael@0 367 return (ev_int64_t)strtoll(s, endptr, base);
michael@0 368 #elif _EVENT_SIZEOF_LONG == 8
michael@0 369 return (ev_int64_t)strtol(s, endptr, base);
michael@0 370 #elif defined(WIN32) && defined(_MSC_VER) && _MSC_VER < 1300
michael@0 371 /* XXXX on old versions of MS APIs, we only support base
michael@0 372 * 10. */
michael@0 373 ev_int64_t r;
michael@0 374 if (base != 10)
michael@0 375 return 0;
michael@0 376 r = (ev_int64_t) _atoi64(s);
michael@0 377 while (isspace(*s))
michael@0 378 ++s;
michael@0 379 if (*s == '-')
michael@0 380 ++s;
michael@0 381 while (isdigit(*s))
michael@0 382 ++s;
michael@0 383 if (endptr)
michael@0 384 *endptr = (char*) s;
michael@0 385 return r;
michael@0 386 #elif defined(WIN32)
michael@0 387 return (ev_int64_t) _strtoi64(s, endptr, base);
michael@0 388 #elif defined(_EVENT_SIZEOF_LONG_LONG) && _EVENT_SIZEOF_LONG_LONG == 8
michael@0 389 long long r;
michael@0 390 int n;
michael@0 391 if (base != 10 && base != 16)
michael@0 392 return 0;
michael@0 393 if (base == 10) {
michael@0 394 n = sscanf(s, "%lld", &r);
michael@0 395 } else {
michael@0 396 unsigned long long ru=0;
michael@0 397 n = sscanf(s, "%llx", &ru);
michael@0 398 if (ru > EV_INT64_MAX)
michael@0 399 return 0;
michael@0 400 r = (long long) ru;
michael@0 401 }
michael@0 402 if (n != 1)
michael@0 403 return 0;
michael@0 404 while (EVUTIL_ISSPACE(*s))
michael@0 405 ++s;
michael@0 406 if (*s == '-')
michael@0 407 ++s;
michael@0 408 if (base == 10) {
michael@0 409 while (EVUTIL_ISDIGIT(*s))
michael@0 410 ++s;
michael@0 411 } else {
michael@0 412 while (EVUTIL_ISXDIGIT(*s))
michael@0 413 ++s;
michael@0 414 }
michael@0 415 if (endptr)
michael@0 416 *endptr = (char*) s;
michael@0 417 return r;
michael@0 418 #else
michael@0 419 #error "I don't know how to parse 64-bit integers."
michael@0 420 #endif
michael@0 421 }
michael@0 422
michael@0 423 #ifndef _EVENT_HAVE_GETTIMEOFDAY
michael@0 424 /* No gettimeofday; this muse be windows. */
michael@0 425 int
michael@0 426 evutil_gettimeofday(struct timeval *tv, struct timezone *tz)
michael@0 427 {
michael@0 428 struct _timeb tb;
michael@0 429
michael@0 430 if (tv == NULL)
michael@0 431 return -1;
michael@0 432
michael@0 433 /* XXXX
michael@0 434 * _ftime is not the greatest interface here; GetSystemTimeAsFileTime
michael@0 435 * would give us better resolution, whereas something cobbled together
michael@0 436 * with GetTickCount could maybe give us monotonic behavior.
michael@0 437 *
michael@0 438 * Either way, I think this value might be skewed to ignore the
michael@0 439 * timezone, and just return local time. That's not so good.
michael@0 440 */
michael@0 441 _ftime(&tb);
michael@0 442 tv->tv_sec = (long) tb.time;
michael@0 443 tv->tv_usec = ((int) tb.millitm) * 1000;
michael@0 444 return 0;
michael@0 445 }
michael@0 446 #endif
michael@0 447
michael@0 448 #ifdef WIN32
michael@0 449 int
michael@0 450 evutil_socket_geterror(evutil_socket_t sock)
michael@0 451 {
michael@0 452 int optval, optvallen=sizeof(optval);
michael@0 453 int err = WSAGetLastError();
michael@0 454 if (err == WSAEWOULDBLOCK && sock >= 0) {
michael@0 455 if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)&optval,
michael@0 456 &optvallen))
michael@0 457 return err;
michael@0 458 if (optval)
michael@0 459 return optval;
michael@0 460 }
michael@0 461 return err;
michael@0 462 }
michael@0 463 #endif
michael@0 464
michael@0 465 /* XXX we should use an enum here. */
michael@0 466 /* 2 for connection refused, 1 for connected, 0 for not yet, -1 for error. */
michael@0 467 int
michael@0 468 evutil_socket_connect(evutil_socket_t *fd_ptr, struct sockaddr *sa, int socklen)
michael@0 469 {
michael@0 470 int made_fd = 0;
michael@0 471
michael@0 472 if (*fd_ptr < 0) {
michael@0 473 if ((*fd_ptr = socket(sa->sa_family, SOCK_STREAM, 0)) < 0)
michael@0 474 goto err;
michael@0 475 made_fd = 1;
michael@0 476 if (evutil_make_socket_nonblocking(*fd_ptr) < 0) {
michael@0 477 goto err;
michael@0 478 }
michael@0 479 }
michael@0 480
michael@0 481 if (connect(*fd_ptr, sa, socklen) < 0) {
michael@0 482 int e = evutil_socket_geterror(*fd_ptr);
michael@0 483 if (EVUTIL_ERR_CONNECT_RETRIABLE(e))
michael@0 484 return 0;
michael@0 485 if (EVUTIL_ERR_CONNECT_REFUSED(e))
michael@0 486 return 2;
michael@0 487 goto err;
michael@0 488 } else {
michael@0 489 return 1;
michael@0 490 }
michael@0 491
michael@0 492 err:
michael@0 493 if (made_fd) {
michael@0 494 evutil_closesocket(*fd_ptr);
michael@0 495 *fd_ptr = -1;
michael@0 496 }
michael@0 497 return -1;
michael@0 498 }
michael@0 499
michael@0 500 /* Check whether a socket on which we called connect() is done
michael@0 501 connecting. Return 1 for connected, 0 for not yet, -1 for error. In the
michael@0 502 error case, set the current socket errno to the error that happened during
michael@0 503 the connect operation. */
michael@0 504 int
michael@0 505 evutil_socket_finished_connecting(evutil_socket_t fd)
michael@0 506 {
michael@0 507 int e;
michael@0 508 ev_socklen_t elen = sizeof(e);
michael@0 509
michael@0 510 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&e, &elen) < 0)
michael@0 511 return -1;
michael@0 512
michael@0 513 if (e) {
michael@0 514 if (EVUTIL_ERR_CONNECT_RETRIABLE(e))
michael@0 515 return 0;
michael@0 516 EVUTIL_SET_SOCKET_ERROR(e);
michael@0 517 return -1;
michael@0 518 }
michael@0 519
michael@0 520 return 1;
michael@0 521 }
michael@0 522
michael@0 523 #if (EVUTIL_AI_PASSIVE|EVUTIL_AI_CANONNAME|EVUTIL_AI_NUMERICHOST| \
michael@0 524 EVUTIL_AI_NUMERICSERV|EVUTIL_AI_V4MAPPED|EVUTIL_AI_ALL| \
michael@0 525 EVUTIL_AI_ADDRCONFIG) != \
michael@0 526 (EVUTIL_AI_PASSIVE^EVUTIL_AI_CANONNAME^EVUTIL_AI_NUMERICHOST^ \
michael@0 527 EVUTIL_AI_NUMERICSERV^EVUTIL_AI_V4MAPPED^EVUTIL_AI_ALL^ \
michael@0 528 EVUTIL_AI_ADDRCONFIG)
michael@0 529 #error "Some of our EVUTIL_AI_* flags seem to overlap with system AI_* flags"
michael@0 530 #endif
michael@0 531
michael@0 532 /* We sometimes need to know whether we have an ipv4 address and whether we
michael@0 533 have an ipv6 address. If 'have_checked_interfaces', then we've already done
michael@0 534 the test. If 'had_ipv4_address', then it turns out we had an ipv4 address.
michael@0 535 If 'had_ipv6_address', then it turns out we had an ipv6 address. These are
michael@0 536 set by evutil_check_interfaces. */
michael@0 537 static int have_checked_interfaces, had_ipv4_address, had_ipv6_address;
michael@0 538
michael@0 539 /* Macro: True iff the IPv4 address 'addr', in host order, is in 127.0.0.0/8
michael@0 540 */
michael@0 541 #define EVUTIL_V4ADDR_IS_LOCALHOST(addr) (((addr)>>24) == 127)
michael@0 542
michael@0 543 /* Macro: True iff the IPv4 address 'addr', in host order, is a class D
michael@0 544 * (multiclass) address.
michael@0 545 */
michael@0 546 #define EVUTIL_V4ADDR_IS_CLASSD(addr) ((((addr)>>24) & 0xf0) == 0xe0)
michael@0 547
michael@0 548 /* Test whether we have an ipv4 interface and an ipv6 interface. Return 0 if
michael@0 549 * the test seemed successful. */
michael@0 550 static int
michael@0 551 evutil_check_interfaces(int force_recheck)
michael@0 552 {
michael@0 553 const char ZEROES[] = "\x00\x00\x00\x00\x00\x00\x00\x00"
michael@0 554 "\x00\x00\x00\x00\x00\x00\x00\x00";
michael@0 555 evutil_socket_t fd = -1;
michael@0 556 struct sockaddr_in sin, sin_out;
michael@0 557 struct sockaddr_in6 sin6, sin6_out;
michael@0 558 ev_socklen_t sin_out_len = sizeof(sin_out);
michael@0 559 ev_socklen_t sin6_out_len = sizeof(sin6_out);
michael@0 560 int r;
michael@0 561 char buf[128];
michael@0 562 if (have_checked_interfaces && !force_recheck)
michael@0 563 return 0;
michael@0 564
michael@0 565 /* To check whether we have an interface open for a given protocol, we
michael@0 566 * try to make a UDP 'connection' to a remote host on the internet.
michael@0 567 * We don't actually use it, so the address doesn't matter, but we
michael@0 568 * want to pick one that keep us from using a host- or link-local
michael@0 569 * interface. */
michael@0 570 memset(&sin, 0, sizeof(sin));
michael@0 571 sin.sin_family = AF_INET;
michael@0 572 sin.sin_port = htons(53);
michael@0 573 r = evutil_inet_pton(AF_INET, "18.244.0.188", &sin.sin_addr);
michael@0 574 EVUTIL_ASSERT(r);
michael@0 575
michael@0 576 memset(&sin6, 0, sizeof(sin6));
michael@0 577 sin6.sin6_family = AF_INET6;
michael@0 578 sin6.sin6_port = htons(53);
michael@0 579 r = evutil_inet_pton(AF_INET6, "2001:4860:b002::68", &sin6.sin6_addr);
michael@0 580 EVUTIL_ASSERT(r);
michael@0 581
michael@0 582 memset(&sin_out, 0, sizeof(sin_out));
michael@0 583 memset(&sin6_out, 0, sizeof(sin6_out));
michael@0 584
michael@0 585 /* XXX some errnos mean 'no address'; some mean 'not enough sockets'. */
michael@0 586 if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) >= 0 &&
michael@0 587 connect(fd, (struct sockaddr*)&sin, sizeof(sin)) == 0 &&
michael@0 588 getsockname(fd, (struct sockaddr*)&sin_out, &sin_out_len) == 0) {
michael@0 589 /* We might have an IPv4 interface. */
michael@0 590 ev_uint32_t addr = ntohl(sin_out.sin_addr.s_addr);
michael@0 591 if (addr == 0 ||
michael@0 592 EVUTIL_V4ADDR_IS_LOCALHOST(addr) ||
michael@0 593 EVUTIL_V4ADDR_IS_CLASSD(addr)) {
michael@0 594 evutil_inet_ntop(AF_INET, &sin_out.sin_addr,
michael@0 595 buf, sizeof(buf));
michael@0 596 /* This is a reserved, ipv4compat, ipv4map, loopback,
michael@0 597 * link-local or unspecified address. The host should
michael@0 598 * never have given it to us; it could never connect
michael@0 599 * to sin. */
michael@0 600 event_warnx("Got a strange local ipv4 address %s",buf);
michael@0 601 } else {
michael@0 602 event_debug(("Detected an IPv4 interface"));
michael@0 603 had_ipv4_address = 1;
michael@0 604 }
michael@0 605 }
michael@0 606 if (fd >= 0)
michael@0 607 evutil_closesocket(fd);
michael@0 608
michael@0 609 if ((fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) >= 0 &&
michael@0 610 connect(fd, (struct sockaddr*)&sin6, sizeof(sin6)) == 0 &&
michael@0 611 getsockname(fd, (struct sockaddr*)&sin6_out, &sin6_out_len) == 0) {
michael@0 612 /* We might have an IPv6 interface. */
michael@0 613 const unsigned char *addr =
michael@0 614 (unsigned char*)sin6_out.sin6_addr.s6_addr;
michael@0 615 if (!memcmp(addr, ZEROES, 8) ||
michael@0 616 (addr[0] == 0xfe && (addr[1] & 0xc0) == 0x80)) {
michael@0 617 /* This is a reserved, ipv4compat, ipv4map, loopback,
michael@0 618 * link-local or unspecified address. The host should
michael@0 619 * never have given it to us; it could never connect
michael@0 620 * to sin6. */
michael@0 621 evutil_inet_ntop(AF_INET6, &sin6_out.sin6_addr,
michael@0 622 buf, sizeof(buf));
michael@0 623 event_warnx("Got a strange local ipv6 address %s",buf);
michael@0 624 } else {
michael@0 625 event_debug(("Detected an IPv4 interface"));
michael@0 626 had_ipv6_address = 1;
michael@0 627 }
michael@0 628 }
michael@0 629
michael@0 630 if (fd >= 0)
michael@0 631 evutil_closesocket(fd);
michael@0 632
michael@0 633 return 0;
michael@0 634 }
michael@0 635
michael@0 636 /* Internal addrinfo flag. This one is set when we allocate the addrinfo from
michael@0 637 * inside libevent. Otherwise, the built-in getaddrinfo() function allocated
michael@0 638 * it, and we should trust what they said.
michael@0 639 **/
michael@0 640 #define EVUTIL_AI_LIBEVENT_ALLOCATED 0x80000000
michael@0 641
michael@0 642 /* Helper: construct a new addrinfo containing the socket address in
michael@0 643 * 'sa', which must be a sockaddr_in or a sockaddr_in6. Take the
michael@0 644 * socktype and protocol info from hints. If they weren't set, then
michael@0 645 * allocate both a TCP and a UDP addrinfo.
michael@0 646 */
michael@0 647 struct evutil_addrinfo *
michael@0 648 evutil_new_addrinfo(struct sockaddr *sa, ev_socklen_t socklen,
michael@0 649 const struct evutil_addrinfo *hints)
michael@0 650 {
michael@0 651 struct evutil_addrinfo *res;
michael@0 652 EVUTIL_ASSERT(hints);
michael@0 653
michael@0 654 if (hints->ai_socktype == 0 && hints->ai_protocol == 0) {
michael@0 655 /* Indecisive user! Give them a UDP and a TCP. */
michael@0 656 struct evutil_addrinfo *r1, *r2;
michael@0 657 struct evutil_addrinfo tmp;
michael@0 658 memcpy(&tmp, hints, sizeof(tmp));
michael@0 659 tmp.ai_socktype = SOCK_STREAM; tmp.ai_protocol = IPPROTO_TCP;
michael@0 660 r1 = evutil_new_addrinfo(sa, socklen, &tmp);
michael@0 661 if (!r1)
michael@0 662 return NULL;
michael@0 663 tmp.ai_socktype = SOCK_DGRAM; tmp.ai_protocol = IPPROTO_UDP;
michael@0 664 r2 = evutil_new_addrinfo(sa, socklen, &tmp);
michael@0 665 if (!r2) {
michael@0 666 evutil_freeaddrinfo(r1);
michael@0 667 return NULL;
michael@0 668 }
michael@0 669 r1->ai_next = r2;
michael@0 670 return r1;
michael@0 671 }
michael@0 672
michael@0 673 /* We're going to allocate extra space to hold the sockaddr. */
michael@0 674 res = mm_calloc(1,sizeof(struct evutil_addrinfo)+socklen);
michael@0 675 if (!res)
michael@0 676 return NULL;
michael@0 677 res->ai_addr = (struct sockaddr*)
michael@0 678 (((char*)res) + sizeof(struct evutil_addrinfo));
michael@0 679 memcpy(res->ai_addr, sa, socklen);
michael@0 680 res->ai_addrlen = socklen;
michael@0 681 res->ai_family = sa->sa_family; /* Same or not? XXX */
michael@0 682 res->ai_flags = EVUTIL_AI_LIBEVENT_ALLOCATED;
michael@0 683 res->ai_socktype = hints->ai_socktype;
michael@0 684 res->ai_protocol = hints->ai_protocol;
michael@0 685
michael@0 686 return res;
michael@0 687 }
michael@0 688
michael@0 689 /* Append the addrinfo 'append' to the end of 'first', and return the start of
michael@0 690 * the list. Either element can be NULL, in which case we return the element
michael@0 691 * that is not NULL. */
michael@0 692 struct evutil_addrinfo *
michael@0 693 evutil_addrinfo_append(struct evutil_addrinfo *first,
michael@0 694 struct evutil_addrinfo *append)
michael@0 695 {
michael@0 696 struct evutil_addrinfo *ai = first;
michael@0 697 if (!ai)
michael@0 698 return append;
michael@0 699 while (ai->ai_next)
michael@0 700 ai = ai->ai_next;
michael@0 701 ai->ai_next = append;
michael@0 702
michael@0 703 return first;
michael@0 704 }
michael@0 705
michael@0 706 static int
michael@0 707 parse_numeric_servname(const char *servname)
michael@0 708 {
michael@0 709 int n;
michael@0 710 char *endptr=NULL;
michael@0 711 n = (int) strtol(servname, &endptr, 10);
michael@0 712 if (n>=0 && n <= 65535 && servname[0] && endptr && !endptr[0])
michael@0 713 return n;
michael@0 714 else
michael@0 715 return -1;
michael@0 716 }
michael@0 717
michael@0 718 /** Parse a service name in 'servname', which can be a decimal port.
michael@0 719 * Return the port number, or -1 on error.
michael@0 720 */
michael@0 721 static int
michael@0 722 evutil_parse_servname(const char *servname, const char *protocol,
michael@0 723 const struct evutil_addrinfo *hints)
michael@0 724 {
michael@0 725 int n = parse_numeric_servname(servname);
michael@0 726 if (n>=0)
michael@0 727 return n;
michael@0 728 #if defined(_EVENT_HAVE_GETSERVBYNAME) || defined(WIN32)
michael@0 729 if (!(hints->ai_flags & EVUTIL_AI_NUMERICSERV)) {
michael@0 730 struct servent *ent = getservbyname(servname, protocol);
michael@0 731 if (ent) {
michael@0 732 return ntohs(ent->s_port);
michael@0 733 }
michael@0 734 }
michael@0 735 #endif
michael@0 736 return -1;
michael@0 737 }
michael@0 738
michael@0 739 /* Return a string corresponding to a protocol number that we can pass to
michael@0 740 * getservyname. */
michael@0 741 static const char *
michael@0 742 evutil_unparse_protoname(int proto)
michael@0 743 {
michael@0 744 switch (proto) {
michael@0 745 case 0:
michael@0 746 return NULL;
michael@0 747 case IPPROTO_TCP:
michael@0 748 return "tcp";
michael@0 749 case IPPROTO_UDP:
michael@0 750 return "udp";
michael@0 751 #ifdef IPPROTO_SCTP
michael@0 752 case IPPROTO_SCTP:
michael@0 753 return "sctp";
michael@0 754 #endif
michael@0 755 default:
michael@0 756 #ifdef _EVENT_HAVE_GETPROTOBYNUMBER
michael@0 757 {
michael@0 758 struct protoent *ent = getprotobynumber(proto);
michael@0 759 if (ent)
michael@0 760 return ent->p_name;
michael@0 761 }
michael@0 762 #endif
michael@0 763 return NULL;
michael@0 764 }
michael@0 765 }
michael@0 766
michael@0 767 static void
michael@0 768 evutil_getaddrinfo_infer_protocols(struct evutil_addrinfo *hints)
michael@0 769 {
michael@0 770 /* If we can guess the protocol from the socktype, do so. */
michael@0 771 if (!hints->ai_protocol && hints->ai_socktype) {
michael@0 772 if (hints->ai_socktype == SOCK_DGRAM)
michael@0 773 hints->ai_protocol = IPPROTO_UDP;
michael@0 774 else if (hints->ai_socktype == SOCK_STREAM)
michael@0 775 hints->ai_protocol = IPPROTO_TCP;
michael@0 776 }
michael@0 777
michael@0 778 /* Set the socktype if it isn't set. */
michael@0 779 if (!hints->ai_socktype && hints->ai_protocol) {
michael@0 780 if (hints->ai_protocol == IPPROTO_UDP)
michael@0 781 hints->ai_socktype = SOCK_DGRAM;
michael@0 782 else if (hints->ai_protocol == IPPROTO_TCP)
michael@0 783 hints->ai_socktype = SOCK_STREAM;
michael@0 784 #ifdef IPPROTO_SCTP
michael@0 785 else if (hints->ai_protocol == IPPROTO_SCTP)
michael@0 786 hints->ai_socktype = SOCK_STREAM;
michael@0 787 #endif
michael@0 788 }
michael@0 789 }
michael@0 790
michael@0 791 #if AF_UNSPEC != PF_UNSPEC
michael@0 792 #error "I cannot build on a system where AF_UNSPEC != PF_UNSPEC"
michael@0 793 #endif
michael@0 794
michael@0 795 /** Implements the part of looking up hosts by name that's common to both
michael@0 796 * the blocking and nonblocking resolver:
michael@0 797 * - Adjust 'hints' to have a reasonable socktype and protocol.
michael@0 798 * - Look up the port based on 'servname', and store it in *portnum,
michael@0 799 * - Handle the nodename==NULL case
michael@0 800 * - Handle some invalid arguments cases.
michael@0 801 * - Handle the cases where nodename is an IPv4 or IPv6 address.
michael@0 802 *
michael@0 803 * If we need the resolver to look up the hostname, we return
michael@0 804 * EVUTIL_EAI_NEED_RESOLVE. Otherwise, we can completely implement
michael@0 805 * getaddrinfo: we return 0 or an appropriate EVUTIL_EAI_* error, and
michael@0 806 * set *res as getaddrinfo would.
michael@0 807 */
michael@0 808 int
michael@0 809 evutil_getaddrinfo_common(const char *nodename, const char *servname,
michael@0 810 struct evutil_addrinfo *hints, struct evutil_addrinfo **res, int *portnum)
michael@0 811 {
michael@0 812 int port = 0;
michael@0 813 const char *pname;
michael@0 814
michael@0 815 if (nodename == NULL && servname == NULL)
michael@0 816 return EVUTIL_EAI_NONAME;
michael@0 817
michael@0 818 /* We only understand 3 families */
michael@0 819 if (hints->ai_family != PF_UNSPEC && hints->ai_family != PF_INET &&
michael@0 820 hints->ai_family != PF_INET6)
michael@0 821 return EVUTIL_EAI_FAMILY;
michael@0 822
michael@0 823 evutil_getaddrinfo_infer_protocols(hints);
michael@0 824
michael@0 825 /* Look up the port number and protocol, if possible. */
michael@0 826 pname = evutil_unparse_protoname(hints->ai_protocol);
michael@0 827 if (servname) {
michael@0 828 /* XXXX We could look at the protocol we got back from
michael@0 829 * getservbyname, but it doesn't seem too useful. */
michael@0 830 port = evutil_parse_servname(servname, pname, hints);
michael@0 831 if (port < 0) {
michael@0 832 return EVUTIL_EAI_NONAME;
michael@0 833 }
michael@0 834 }
michael@0 835
michael@0 836 /* If we have no node name, then we're supposed to bind to 'any' and
michael@0 837 * connect to localhost. */
michael@0 838 if (nodename == NULL) {
michael@0 839 struct evutil_addrinfo *res4=NULL, *res6=NULL;
michael@0 840 if (hints->ai_family != PF_INET) { /* INET6 or UNSPEC. */
michael@0 841 struct sockaddr_in6 sin6;
michael@0 842 memset(&sin6, 0, sizeof(sin6));
michael@0 843 sin6.sin6_family = AF_INET6;
michael@0 844 sin6.sin6_port = htons(port);
michael@0 845 if (hints->ai_flags & EVUTIL_AI_PASSIVE) {
michael@0 846 /* Bind to :: */
michael@0 847 } else {
michael@0 848 /* connect to ::1 */
michael@0 849 sin6.sin6_addr.s6_addr[15] = 1;
michael@0 850 }
michael@0 851 res6 = evutil_new_addrinfo((struct sockaddr*)&sin6,
michael@0 852 sizeof(sin6), hints);
michael@0 853 if (!res6)
michael@0 854 return EVUTIL_EAI_MEMORY;
michael@0 855 }
michael@0 856
michael@0 857 if (hints->ai_family != PF_INET6) { /* INET or UNSPEC */
michael@0 858 struct sockaddr_in sin;
michael@0 859 memset(&sin, 0, sizeof(sin));
michael@0 860 sin.sin_family = AF_INET;
michael@0 861 sin.sin_port = htons(port);
michael@0 862 if (hints->ai_flags & EVUTIL_AI_PASSIVE) {
michael@0 863 /* Bind to 0.0.0.0 */
michael@0 864 } else {
michael@0 865 /* connect to 127.0.0.1 */
michael@0 866 sin.sin_addr.s_addr = htonl(0x7f000001);
michael@0 867 }
michael@0 868 res4 = evutil_new_addrinfo((struct sockaddr*)&sin,
michael@0 869 sizeof(sin), hints);
michael@0 870 if (!res4) {
michael@0 871 if (res6)
michael@0 872 evutil_freeaddrinfo(res6);
michael@0 873 return EVUTIL_EAI_MEMORY;
michael@0 874 }
michael@0 875 }
michael@0 876 *res = evutil_addrinfo_append(res4, res6);
michael@0 877 return 0;
michael@0 878 }
michael@0 879
michael@0 880 /* If we can, we should try to parse the hostname without resolving
michael@0 881 * it. */
michael@0 882 /* Try ipv6. */
michael@0 883 if (hints->ai_family == PF_INET6 || hints->ai_family == PF_UNSPEC) {
michael@0 884 struct sockaddr_in6 sin6;
michael@0 885 memset(&sin6, 0, sizeof(sin6));
michael@0 886 if (1==evutil_inet_pton(AF_INET6, nodename, &sin6.sin6_addr)) {
michael@0 887 /* Got an ipv6 address. */
michael@0 888 sin6.sin6_family = AF_INET6;
michael@0 889 sin6.sin6_port = htons(port);
michael@0 890 *res = evutil_new_addrinfo((struct sockaddr*)&sin6,
michael@0 891 sizeof(sin6), hints);
michael@0 892 if (!*res)
michael@0 893 return EVUTIL_EAI_MEMORY;
michael@0 894 return 0;
michael@0 895 }
michael@0 896 }
michael@0 897
michael@0 898 /* Try ipv4. */
michael@0 899 if (hints->ai_family == PF_INET || hints->ai_family == PF_UNSPEC) {
michael@0 900 struct sockaddr_in sin;
michael@0 901 memset(&sin, 0, sizeof(sin));
michael@0 902 if (1==evutil_inet_pton(AF_INET, nodename, &sin.sin_addr)) {
michael@0 903 /* Got an ipv6 address. */
michael@0 904 sin.sin_family = AF_INET;
michael@0 905 sin.sin_port = htons(port);
michael@0 906 *res = evutil_new_addrinfo((struct sockaddr*)&sin,
michael@0 907 sizeof(sin), hints);
michael@0 908 if (!*res)
michael@0 909 return EVUTIL_EAI_MEMORY;
michael@0 910 return 0;
michael@0 911 }
michael@0 912 }
michael@0 913
michael@0 914
michael@0 915 /* If we have reached this point, we definitely need to do a DNS
michael@0 916 * lookup. */
michael@0 917 if ((hints->ai_flags & EVUTIL_AI_NUMERICHOST)) {
michael@0 918 /* If we're not allowed to do one, then say so. */
michael@0 919 return EVUTIL_EAI_NONAME;
michael@0 920 }
michael@0 921 *portnum = port;
michael@0 922 return EVUTIL_EAI_NEED_RESOLVE;
michael@0 923 }
michael@0 924
michael@0 925 #ifdef _EVENT_HAVE_GETADDRINFO
michael@0 926 #define USE_NATIVE_GETADDRINFO
michael@0 927 #endif
michael@0 928
michael@0 929 #ifdef USE_NATIVE_GETADDRINFO
michael@0 930 /* A mask of all the flags that we declare, so we can clear them before calling
michael@0 931 * the native getaddrinfo */
michael@0 932 static const unsigned int ALL_NONNATIVE_AI_FLAGS =
michael@0 933 #ifndef AI_PASSIVE
michael@0 934 EVUTIL_AI_PASSIVE |
michael@0 935 #endif
michael@0 936 #ifndef AI_CANONNAME
michael@0 937 EVUTIL_AI_CANONNAME |
michael@0 938 #endif
michael@0 939 #ifndef AI_NUMERICHOST
michael@0 940 EVUTIL_AI_NUMERICHOST |
michael@0 941 #endif
michael@0 942 #ifndef AI_NUMERICSERV
michael@0 943 EVUTIL_AI_NUMERICSERV |
michael@0 944 #endif
michael@0 945 #ifndef AI_ADDRCONFIG
michael@0 946 EVUTIL_AI_ADDRCONFIG |
michael@0 947 #endif
michael@0 948 #ifndef AI_ALL
michael@0 949 EVUTIL_AI_ALL |
michael@0 950 #endif
michael@0 951 #ifndef AI_V4MAPPED
michael@0 952 EVUTIL_AI_V4MAPPED |
michael@0 953 #endif
michael@0 954 EVUTIL_AI_LIBEVENT_ALLOCATED;
michael@0 955
michael@0 956 static const unsigned int ALL_NATIVE_AI_FLAGS =
michael@0 957 #ifdef AI_PASSIVE
michael@0 958 AI_PASSIVE |
michael@0 959 #endif
michael@0 960 #ifdef AI_CANONNAME
michael@0 961 AI_CANONNAME |
michael@0 962 #endif
michael@0 963 #ifdef AI_NUMERICHOST
michael@0 964 AI_NUMERICHOST |
michael@0 965 #endif
michael@0 966 #ifdef AI_NUMERICSERV
michael@0 967 AI_NUMERICSERV |
michael@0 968 #endif
michael@0 969 #ifdef AI_ADDRCONFIG
michael@0 970 AI_ADDRCONFIG |
michael@0 971 #endif
michael@0 972 #ifdef AI_ALL
michael@0 973 AI_ALL |
michael@0 974 #endif
michael@0 975 #ifdef AI_V4MAPPED
michael@0 976 AI_V4MAPPED |
michael@0 977 #endif
michael@0 978 0;
michael@0 979 #endif
michael@0 980
michael@0 981 #ifndef USE_NATIVE_GETADDRINFO
michael@0 982 /* Helper for systems with no getaddrinfo(): make one or more addrinfos out of
michael@0 983 * a struct hostent.
michael@0 984 */
michael@0 985 static struct evutil_addrinfo *
michael@0 986 addrinfo_from_hostent(const struct hostent *ent,
michael@0 987 int port, const struct evutil_addrinfo *hints)
michael@0 988 {
michael@0 989 int i;
michael@0 990 struct sockaddr_in sin;
michael@0 991 struct sockaddr_in6 sin6;
michael@0 992 struct sockaddr *sa;
michael@0 993 int socklen;
michael@0 994 struct evutil_addrinfo *res=NULL, *ai;
michael@0 995 void *addrp;
michael@0 996
michael@0 997 if (ent->h_addrtype == PF_INET) {
michael@0 998 memset(&sin, 0, sizeof(sin));
michael@0 999 sin.sin_family = AF_INET;
michael@0 1000 sin.sin_port = htons(port);
michael@0 1001 sa = (struct sockaddr *)&sin;
michael@0 1002 socklen = sizeof(struct sockaddr_in);
michael@0 1003 addrp = &sin.sin_addr;
michael@0 1004 if (ent->h_length != sizeof(sin.sin_addr)) {
michael@0 1005 event_warnx("Weird h_length from gethostbyname");
michael@0 1006 return NULL;
michael@0 1007 }
michael@0 1008 } else if (ent->h_addrtype == PF_INET6) {
michael@0 1009 memset(&sin6, 0, sizeof(sin6));
michael@0 1010 sin6.sin6_family = AF_INET6;
michael@0 1011 sin6.sin6_port = htons(port);
michael@0 1012 sa = (struct sockaddr *)&sin6;
michael@0 1013 socklen = sizeof(struct sockaddr_in);
michael@0 1014 addrp = &sin6.sin6_addr;
michael@0 1015 if (ent->h_length != sizeof(sin6.sin6_addr)) {
michael@0 1016 event_warnx("Weird h_length from gethostbyname");
michael@0 1017 return NULL;
michael@0 1018 }
michael@0 1019 } else
michael@0 1020 return NULL;
michael@0 1021
michael@0 1022 for (i = 0; ent->h_addr_list[i]; ++i) {
michael@0 1023 memcpy(addrp, ent->h_addr_list[i], ent->h_length);
michael@0 1024 ai = evutil_new_addrinfo(sa, socklen, hints);
michael@0 1025 if (!ai) {
michael@0 1026 evutil_freeaddrinfo(res);
michael@0 1027 return NULL;
michael@0 1028 }
michael@0 1029 res = evutil_addrinfo_append(res, ai);
michael@0 1030 }
michael@0 1031
michael@0 1032 if (res && ((hints->ai_flags & EVUTIL_AI_CANONNAME) && ent->h_name)) {
michael@0 1033 res->ai_canonname = mm_strdup(ent->h_name);
michael@0 1034 if (res->ai_canonname == NULL) {
michael@0 1035 evutil_freeaddrinfo(res);
michael@0 1036 return NULL;
michael@0 1037 }
michael@0 1038 }
michael@0 1039
michael@0 1040 return res;
michael@0 1041 }
michael@0 1042 #endif
michael@0 1043
michael@0 1044 /* If the EVUTIL_AI_ADDRCONFIG flag is set on hints->ai_flags, and
michael@0 1045 * hints->ai_family is PF_UNSPEC, then revise the value of hints->ai_family so
michael@0 1046 * that we'll only get addresses we could maybe connect to.
michael@0 1047 */
michael@0 1048 void
michael@0 1049 evutil_adjust_hints_for_addrconfig(struct evutil_addrinfo *hints)
michael@0 1050 {
michael@0 1051 if (!(hints->ai_flags & EVUTIL_AI_ADDRCONFIG))
michael@0 1052 return;
michael@0 1053 if (hints->ai_family != PF_UNSPEC)
michael@0 1054 return;
michael@0 1055 if (!have_checked_interfaces)
michael@0 1056 evutil_check_interfaces(0);
michael@0 1057 if (had_ipv4_address && !had_ipv6_address) {
michael@0 1058 hints->ai_family = PF_INET;
michael@0 1059 } else if (!had_ipv4_address && had_ipv6_address) {
michael@0 1060 hints->ai_family = PF_INET6;
michael@0 1061 }
michael@0 1062 }
michael@0 1063
michael@0 1064 #ifdef USE_NATIVE_GETADDRINFO
michael@0 1065 static int need_numeric_port_hack_=0;
michael@0 1066 static int need_socktype_protocol_hack_=0;
michael@0 1067 static int tested_for_getaddrinfo_hacks=0;
michael@0 1068
michael@0 1069 /* Some older BSDs (like OpenBSD up to 4.6) used to believe that
michael@0 1070 giving a numeric port without giving an ai_socktype was verboten.
michael@0 1071 We test for this so we can apply an appropriate workaround. If it
michael@0 1072 turns out that the bug is present, then:
michael@0 1073
michael@0 1074 - If nodename==NULL and servname is numeric, we build an answer
michael@0 1075 ourselves using evutil_getaddrinfo_common().
michael@0 1076
michael@0 1077 - If nodename!=NULL and servname is numeric, then we set
michael@0 1078 servname=NULL when calling getaddrinfo, and post-process the
michael@0 1079 result to set the ports on it.
michael@0 1080
michael@0 1081 We test for this bug at runtime, since otherwise we can't have the
michael@0 1082 same binary run on multiple BSD versions.
michael@0 1083
michael@0 1084 - Some versions of Solaris believe that it's nice to leave to protocol
michael@0 1085 field set to 0. We test for this so we can apply an appropriate
michael@0 1086 workaround.
michael@0 1087 */
michael@0 1088 static void
michael@0 1089 test_for_getaddrinfo_hacks(void)
michael@0 1090 {
michael@0 1091 int r, r2;
michael@0 1092 struct evutil_addrinfo *ai=NULL, *ai2=NULL;
michael@0 1093 struct evutil_addrinfo hints;
michael@0 1094
michael@0 1095 memset(&hints,0,sizeof(hints));
michael@0 1096 hints.ai_family = PF_UNSPEC;
michael@0 1097 hints.ai_flags =
michael@0 1098 #ifdef AI_NUMERICHOST
michael@0 1099 AI_NUMERICHOST |
michael@0 1100 #endif
michael@0 1101 #ifdef AI_NUMERICSERV
michael@0 1102 AI_NUMERICSERV |
michael@0 1103 #endif
michael@0 1104 0;
michael@0 1105 r = getaddrinfo("1.2.3.4", "80", &hints, &ai);
michael@0 1106 hints.ai_socktype = SOCK_STREAM;
michael@0 1107 r2 = getaddrinfo("1.2.3.4", "80", &hints, &ai2);
michael@0 1108 if (r2 == 0 && r != 0) {
michael@0 1109 need_numeric_port_hack_=1;
michael@0 1110 }
michael@0 1111 if (ai2 && ai2->ai_protocol == 0) {
michael@0 1112 need_socktype_protocol_hack_=1;
michael@0 1113 }
michael@0 1114
michael@0 1115 if (ai)
michael@0 1116 freeaddrinfo(ai);
michael@0 1117 if (ai2)
michael@0 1118 freeaddrinfo(ai2);
michael@0 1119 tested_for_getaddrinfo_hacks=1;
michael@0 1120 }
michael@0 1121
michael@0 1122 static inline int
michael@0 1123 need_numeric_port_hack(void)
michael@0 1124 {
michael@0 1125 if (!tested_for_getaddrinfo_hacks)
michael@0 1126 test_for_getaddrinfo_hacks();
michael@0 1127 return need_numeric_port_hack_;
michael@0 1128 }
michael@0 1129
michael@0 1130 static inline int
michael@0 1131 need_socktype_protocol_hack(void)
michael@0 1132 {
michael@0 1133 if (!tested_for_getaddrinfo_hacks)
michael@0 1134 test_for_getaddrinfo_hacks();
michael@0 1135 return need_socktype_protocol_hack_;
michael@0 1136 }
michael@0 1137
michael@0 1138 static void
michael@0 1139 apply_numeric_port_hack(int port, struct evutil_addrinfo **ai)
michael@0 1140 {
michael@0 1141 /* Now we run through the list and set the ports on all of the
michael@0 1142 * results where ports would make sense. */
michael@0 1143 for ( ; *ai; ai = &(*ai)->ai_next) {
michael@0 1144 struct sockaddr *sa = (*ai)->ai_addr;
michael@0 1145 if (sa && sa->sa_family == AF_INET) {
michael@0 1146 struct sockaddr_in *sin = (struct sockaddr_in*)sa;
michael@0 1147 sin->sin_port = htons(port);
michael@0 1148 } else if (sa && sa->sa_family == AF_INET6) {
michael@0 1149 struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)sa;
michael@0 1150 sin6->sin6_port = htons(port);
michael@0 1151 } else {
michael@0 1152 /* A numeric port makes no sense here; remove this one
michael@0 1153 * from the list. */
michael@0 1154 struct evutil_addrinfo *victim = *ai;
michael@0 1155 *ai = victim->ai_next;
michael@0 1156 victim->ai_next = NULL;
michael@0 1157 freeaddrinfo(victim);
michael@0 1158 }
michael@0 1159 }
michael@0 1160 }
michael@0 1161
michael@0 1162 static int
michael@0 1163 apply_socktype_protocol_hack(struct evutil_addrinfo *ai)
michael@0 1164 {
michael@0 1165 struct evutil_addrinfo *ai_new;
michael@0 1166 for (; ai; ai = ai->ai_next) {
michael@0 1167 evutil_getaddrinfo_infer_protocols(ai);
michael@0 1168 if (ai->ai_socktype || ai->ai_protocol)
michael@0 1169 continue;
michael@0 1170 ai_new = mm_malloc(sizeof(*ai_new));
michael@0 1171 if (!ai_new)
michael@0 1172 return -1;
michael@0 1173 memcpy(ai_new, ai, sizeof(*ai_new));
michael@0 1174 ai->ai_socktype = SOCK_STREAM;
michael@0 1175 ai->ai_protocol = IPPROTO_TCP;
michael@0 1176 ai_new->ai_socktype = SOCK_DGRAM;
michael@0 1177 ai_new->ai_protocol = IPPROTO_UDP;
michael@0 1178
michael@0 1179 ai_new->ai_next = ai->ai_next;
michael@0 1180 ai->ai_next = ai_new;
michael@0 1181 }
michael@0 1182 return 0;
michael@0 1183 }
michael@0 1184 #endif
michael@0 1185
michael@0 1186 int
michael@0 1187 evutil_getaddrinfo(const char *nodename, const char *servname,
michael@0 1188 const struct evutil_addrinfo *hints_in, struct evutil_addrinfo **res)
michael@0 1189 {
michael@0 1190 #ifdef USE_NATIVE_GETADDRINFO
michael@0 1191 struct evutil_addrinfo hints;
michael@0 1192 int portnum=-1, need_np_hack, err;
michael@0 1193
michael@0 1194 if (hints_in) {
michael@0 1195 memcpy(&hints, hints_in, sizeof(hints));
michael@0 1196 } else {
michael@0 1197 memset(&hints, 0, sizeof(hints));
michael@0 1198 hints.ai_family = PF_UNSPEC;
michael@0 1199 }
michael@0 1200
michael@0 1201 #ifndef AI_ADDRCONFIG
michael@0 1202 /* Not every system has AI_ADDRCONFIG, so fake it. */
michael@0 1203 if (hints.ai_family == PF_UNSPEC &&
michael@0 1204 (hints.ai_flags & EVUTIL_AI_ADDRCONFIG)) {
michael@0 1205 evutil_adjust_hints_for_addrconfig(&hints);
michael@0 1206 }
michael@0 1207 #endif
michael@0 1208
michael@0 1209 #ifndef AI_NUMERICSERV
michael@0 1210 /* Not every system has AI_NUMERICSERV, so fake it. */
michael@0 1211 if (hints.ai_flags & EVUTIL_AI_NUMERICSERV) {
michael@0 1212 if (servname && parse_numeric_servname(servname)<0)
michael@0 1213 return EVUTIL_EAI_NONAME;
michael@0 1214 }
michael@0 1215 #endif
michael@0 1216
michael@0 1217 /* Enough operating systems handle enough common non-resolve
michael@0 1218 * cases here weirdly enough that we are better off just
michael@0 1219 * overriding them. For example:
michael@0 1220 *
michael@0 1221 * - Windows doesn't like to infer the protocol from the
michael@0 1222 * socket type, or fill in socket or protocol types much at
michael@0 1223 * all. It also seems to do its own broken implicit
michael@0 1224 * always-on version of AI_ADDRCONFIG that keeps it from
michael@0 1225 * ever resolving even a literal IPv6 address when
michael@0 1226 * ai_addrtype is PF_UNSPEC.
michael@0 1227 */
michael@0 1228 #ifdef WIN32
michael@0 1229 {
michael@0 1230 int tmp_port;
michael@0 1231 err = evutil_getaddrinfo_common(nodename,servname,&hints,
michael@0 1232 res, &tmp_port);
michael@0 1233 if (err == 0 ||
michael@0 1234 err == EVUTIL_EAI_MEMORY ||
michael@0 1235 err == EVUTIL_EAI_NONAME)
michael@0 1236 return err;
michael@0 1237 /* If we make it here, the system getaddrinfo can
michael@0 1238 * have a crack at it. */
michael@0 1239 }
michael@0 1240 #endif
michael@0 1241
michael@0 1242 /* See documentation for need_numeric_port_hack above.*/
michael@0 1243 need_np_hack = need_numeric_port_hack() && servname && !hints.ai_socktype
michael@0 1244 && ((portnum=parse_numeric_servname(servname)) >= 0);
michael@0 1245 if (need_np_hack) {
michael@0 1246 if (!nodename)
michael@0 1247 return evutil_getaddrinfo_common(
michael@0 1248 NULL,servname,&hints, res, &portnum);
michael@0 1249 servname = NULL;
michael@0 1250 }
michael@0 1251
michael@0 1252 if (need_socktype_protocol_hack()) {
michael@0 1253 evutil_getaddrinfo_infer_protocols(&hints);
michael@0 1254 }
michael@0 1255
michael@0 1256 /* Make sure that we didn't actually steal any AI_FLAGS values that
michael@0 1257 * the system is using. (This is a constant expression, and should ge
michael@0 1258 * optimized out.)
michael@0 1259 *
michael@0 1260 * XXXX Turn this into a compile-time failure rather than a run-time
michael@0 1261 * failure.
michael@0 1262 */
michael@0 1263 EVUTIL_ASSERT((ALL_NONNATIVE_AI_FLAGS & ALL_NATIVE_AI_FLAGS) == 0);
michael@0 1264
michael@0 1265 /* Clear any flags that only libevent understands. */
michael@0 1266 hints.ai_flags &= ~ALL_NONNATIVE_AI_FLAGS;
michael@0 1267
michael@0 1268 err = getaddrinfo(nodename, servname, &hints, res);
michael@0 1269 if (need_np_hack)
michael@0 1270 apply_numeric_port_hack(portnum, res);
michael@0 1271
michael@0 1272 if (need_socktype_protocol_hack()) {
michael@0 1273 if (apply_socktype_protocol_hack(*res) < 0) {
michael@0 1274 evutil_freeaddrinfo(*res);
michael@0 1275 *res = NULL;
michael@0 1276 return EVUTIL_EAI_MEMORY;
michael@0 1277 }
michael@0 1278 }
michael@0 1279 return err;
michael@0 1280 #else
michael@0 1281 int port=0, err;
michael@0 1282 struct hostent *ent = NULL;
michael@0 1283 struct evutil_addrinfo hints;
michael@0 1284
michael@0 1285 if (hints_in) {
michael@0 1286 memcpy(&hints, hints_in, sizeof(hints));
michael@0 1287 } else {
michael@0 1288 memset(&hints, 0, sizeof(hints));
michael@0 1289 hints.ai_family = PF_UNSPEC;
michael@0 1290 }
michael@0 1291
michael@0 1292 evutil_adjust_hints_for_addrconfig(&hints);
michael@0 1293
michael@0 1294 err = evutil_getaddrinfo_common(nodename, servname, &hints, res, &port);
michael@0 1295 if (err != EVUTIL_EAI_NEED_RESOLVE) {
michael@0 1296 /* We either succeeded or failed. No need to continue */
michael@0 1297 return err;
michael@0 1298 }
michael@0 1299
michael@0 1300 err = 0;
michael@0 1301 /* Use any of the various gethostbyname_r variants as available. */
michael@0 1302 {
michael@0 1303 #ifdef _EVENT_HAVE_GETHOSTBYNAME_R_6_ARG
michael@0 1304 /* This one is what glibc provides. */
michael@0 1305 char buf[2048];
michael@0 1306 struct hostent hostent;
michael@0 1307 int r;
michael@0 1308 r = gethostbyname_r(nodename, &hostent, buf, sizeof(buf), &ent,
michael@0 1309 &err);
michael@0 1310 #elif defined(_EVENT_HAVE_GETHOSTBYNAME_R_5_ARG)
michael@0 1311 char buf[2048];
michael@0 1312 struct hostent hostent;
michael@0 1313 ent = gethostbyname_r(nodename, &hostent, buf, sizeof(buf),
michael@0 1314 &err);
michael@0 1315 #elif defined(_EVENT_HAVE_GETHOSTBYNAME_R_3_ARG)
michael@0 1316 struct hostent_data data;
michael@0 1317 struct hostent hostent;
michael@0 1318 memset(&data, 0, sizeof(data));
michael@0 1319 err = gethostbyname_r(nodename, &hostent, &data);
michael@0 1320 ent = err ? NULL : &hostent;
michael@0 1321 #else
michael@0 1322 /* fall back to gethostbyname. */
michael@0 1323 /* XXXX This needs a lock everywhere but Windows. */
michael@0 1324 ent = gethostbyname(nodename);
michael@0 1325 #ifdef WIN32
michael@0 1326 err = WSAGetLastError();
michael@0 1327 #else
michael@0 1328 err = h_errno;
michael@0 1329 #endif
michael@0 1330 #endif
michael@0 1331
michael@0 1332 /* Now we have either ent or err set. */
michael@0 1333 if (!ent) {
michael@0 1334 /* XXX is this right for windows ? */
michael@0 1335 switch (err) {
michael@0 1336 case TRY_AGAIN:
michael@0 1337 return EVUTIL_EAI_AGAIN;
michael@0 1338 case NO_RECOVERY:
michael@0 1339 default:
michael@0 1340 return EVUTIL_EAI_FAIL;
michael@0 1341 case HOST_NOT_FOUND:
michael@0 1342 return EVUTIL_EAI_NONAME;
michael@0 1343 case NO_ADDRESS:
michael@0 1344 #if NO_DATA != NO_ADDRESS
michael@0 1345 case NO_DATA:
michael@0 1346 #endif
michael@0 1347 return EVUTIL_EAI_NODATA;
michael@0 1348 }
michael@0 1349 }
michael@0 1350
michael@0 1351 if (ent->h_addrtype != hints.ai_family &&
michael@0 1352 hints.ai_family != PF_UNSPEC) {
michael@0 1353 /* This wasn't the type we were hoping for. Too bad
michael@0 1354 * we never had a chance to ask gethostbyname for what
michael@0 1355 * we wanted. */
michael@0 1356 return EVUTIL_EAI_NONAME;
michael@0 1357 }
michael@0 1358
michael@0 1359 /* Make sure we got _some_ answers. */
michael@0 1360 if (ent->h_length == 0)
michael@0 1361 return EVUTIL_EAI_NODATA;
michael@0 1362
michael@0 1363 /* If we got an address type we don't know how to make a
michael@0 1364 sockaddr for, give up. */
michael@0 1365 if (ent->h_addrtype != PF_INET && ent->h_addrtype != PF_INET6)
michael@0 1366 return EVUTIL_EAI_FAMILY;
michael@0 1367
michael@0 1368 *res = addrinfo_from_hostent(ent, port, &hints);
michael@0 1369 if (! *res)
michael@0 1370 return EVUTIL_EAI_MEMORY;
michael@0 1371 }
michael@0 1372
michael@0 1373 return 0;
michael@0 1374 #endif
michael@0 1375 }
michael@0 1376
michael@0 1377 void
michael@0 1378 evutil_freeaddrinfo(struct evutil_addrinfo *ai)
michael@0 1379 {
michael@0 1380 #ifdef _EVENT_HAVE_GETADDRINFO
michael@0 1381 if (!(ai->ai_flags & EVUTIL_AI_LIBEVENT_ALLOCATED)) {
michael@0 1382 freeaddrinfo(ai);
michael@0 1383 return;
michael@0 1384 }
michael@0 1385 #endif
michael@0 1386 while (ai) {
michael@0 1387 struct evutil_addrinfo *next = ai->ai_next;
michael@0 1388 if (ai->ai_canonname)
michael@0 1389 mm_free(ai->ai_canonname);
michael@0 1390 mm_free(ai);
michael@0 1391 ai = next;
michael@0 1392 }
michael@0 1393 }
michael@0 1394
michael@0 1395 static evdns_getaddrinfo_fn evdns_getaddrinfo_impl = NULL;
michael@0 1396
michael@0 1397 void
michael@0 1398 evutil_set_evdns_getaddrinfo_fn(evdns_getaddrinfo_fn fn)
michael@0 1399 {
michael@0 1400 if (!evdns_getaddrinfo_impl)
michael@0 1401 evdns_getaddrinfo_impl = fn;
michael@0 1402 }
michael@0 1403
michael@0 1404 /* Internal helper function: act like evdns_getaddrinfo if dns_base is set;
michael@0 1405 * otherwise do a blocking resolve and pass the result to the callback in the
michael@0 1406 * way that evdns_getaddrinfo would.
michael@0 1407 */
michael@0 1408 int
michael@0 1409 evutil_getaddrinfo_async(struct evdns_base *dns_base,
michael@0 1410 const char *nodename, const char *servname,
michael@0 1411 const struct evutil_addrinfo *hints_in,
michael@0 1412 void (*cb)(int, struct evutil_addrinfo *, void *), void *arg)
michael@0 1413 {
michael@0 1414 if (dns_base && evdns_getaddrinfo_impl) {
michael@0 1415 evdns_getaddrinfo_impl(
michael@0 1416 dns_base, nodename, servname, hints_in, cb, arg);
michael@0 1417 } else {
michael@0 1418 struct evutil_addrinfo *ai=NULL;
michael@0 1419 int err;
michael@0 1420 err = evutil_getaddrinfo(nodename, servname, hints_in, &ai);
michael@0 1421 cb(err, ai, arg);
michael@0 1422 }
michael@0 1423 return 0;
michael@0 1424 }
michael@0 1425
michael@0 1426 const char *
michael@0 1427 evutil_gai_strerror(int err)
michael@0 1428 {
michael@0 1429 /* As a sneaky side-benefit, this case statement will get most
michael@0 1430 * compilers to tell us if any of the error codes we defined
michael@0 1431 * conflict with the platform's native error codes. */
michael@0 1432 switch (err) {
michael@0 1433 case EVUTIL_EAI_CANCEL:
michael@0 1434 return "Request canceled";
michael@0 1435 case 0:
michael@0 1436 return "No error";
michael@0 1437
michael@0 1438 case EVUTIL_EAI_ADDRFAMILY:
michael@0 1439 return "address family for nodename not supported";
michael@0 1440 case EVUTIL_EAI_AGAIN:
michael@0 1441 return "temporary failure in name resolution";
michael@0 1442 case EVUTIL_EAI_BADFLAGS:
michael@0 1443 return "invalid value for ai_flags";
michael@0 1444 case EVUTIL_EAI_FAIL:
michael@0 1445 return "non-recoverable failure in name resolution";
michael@0 1446 case EVUTIL_EAI_FAMILY:
michael@0 1447 return "ai_family not supported";
michael@0 1448 case EVUTIL_EAI_MEMORY:
michael@0 1449 return "memory allocation failure";
michael@0 1450 case EVUTIL_EAI_NODATA:
michael@0 1451 return "no address associated with nodename";
michael@0 1452 case EVUTIL_EAI_NONAME:
michael@0 1453 return "nodename nor servname provided, or not known";
michael@0 1454 case EVUTIL_EAI_SERVICE:
michael@0 1455 return "servname not supported for ai_socktype";
michael@0 1456 case EVUTIL_EAI_SOCKTYPE:
michael@0 1457 return "ai_socktype not supported";
michael@0 1458 case EVUTIL_EAI_SYSTEM:
michael@0 1459 return "system error";
michael@0 1460 default:
michael@0 1461 #if defined(USE_NATIVE_GETADDRINFO) && defined(WIN32)
michael@0 1462 return gai_strerrorA(err);
michael@0 1463 #elif defined(USE_NATIVE_GETADDRINFO)
michael@0 1464 return gai_strerror(err);
michael@0 1465 #else
michael@0 1466 return "Unknown error code";
michael@0 1467 #endif
michael@0 1468 }
michael@0 1469 }
michael@0 1470
michael@0 1471 #ifdef WIN32
michael@0 1472 #define E(code, s) { code, (s " [" #code " ]") }
michael@0 1473 static struct { int code; const char *msg; } windows_socket_errors[] = {
michael@0 1474 E(WSAEINTR, "Interrupted function call"),
michael@0 1475 E(WSAEACCES, "Permission denied"),
michael@0 1476 E(WSAEFAULT, "Bad address"),
michael@0 1477 E(WSAEINVAL, "Invalid argument"),
michael@0 1478 E(WSAEMFILE, "Too many open files"),
michael@0 1479 E(WSAEWOULDBLOCK, "Resource temporarily unavailable"),
michael@0 1480 E(WSAEINPROGRESS, "Operation now in progress"),
michael@0 1481 E(WSAEALREADY, "Operation already in progress"),
michael@0 1482 E(WSAENOTSOCK, "Socket operation on nonsocket"),
michael@0 1483 E(WSAEDESTADDRREQ, "Destination address required"),
michael@0 1484 E(WSAEMSGSIZE, "Message too long"),
michael@0 1485 E(WSAEPROTOTYPE, "Protocol wrong for socket"),
michael@0 1486 E(WSAENOPROTOOPT, "Bad protocol option"),
michael@0 1487 E(WSAEPROTONOSUPPORT, "Protocol not supported"),
michael@0 1488 E(WSAESOCKTNOSUPPORT, "Socket type not supported"),
michael@0 1489 /* What's the difference between NOTSUPP and NOSUPPORT? :) */
michael@0 1490 E(WSAEOPNOTSUPP, "Operation not supported"),
michael@0 1491 E(WSAEPFNOSUPPORT, "Protocol family not supported"),
michael@0 1492 E(WSAEAFNOSUPPORT, "Address family not supported by protocol family"),
michael@0 1493 E(WSAEADDRINUSE, "Address already in use"),
michael@0 1494 E(WSAEADDRNOTAVAIL, "Cannot assign requested address"),
michael@0 1495 E(WSAENETDOWN, "Network is down"),
michael@0 1496 E(WSAENETUNREACH, "Network is unreachable"),
michael@0 1497 E(WSAENETRESET, "Network dropped connection on reset"),
michael@0 1498 E(WSAECONNABORTED, "Software caused connection abort"),
michael@0 1499 E(WSAECONNRESET, "Connection reset by peer"),
michael@0 1500 E(WSAENOBUFS, "No buffer space available"),
michael@0 1501 E(WSAEISCONN, "Socket is already connected"),
michael@0 1502 E(WSAENOTCONN, "Socket is not connected"),
michael@0 1503 E(WSAESHUTDOWN, "Cannot send after socket shutdown"),
michael@0 1504 E(WSAETIMEDOUT, "Connection timed out"),
michael@0 1505 E(WSAECONNREFUSED, "Connection refused"),
michael@0 1506 E(WSAEHOSTDOWN, "Host is down"),
michael@0 1507 E(WSAEHOSTUNREACH, "No route to host"),
michael@0 1508 E(WSAEPROCLIM, "Too many processes"),
michael@0 1509
michael@0 1510 /* Yes, some of these start with WSA, not WSAE. No, I don't know why. */
michael@0 1511 E(WSASYSNOTREADY, "Network subsystem is unavailable"),
michael@0 1512 E(WSAVERNOTSUPPORTED, "Winsock.dll out of range"),
michael@0 1513 E(WSANOTINITIALISED, "Successful WSAStartup not yet performed"),
michael@0 1514 E(WSAEDISCON, "Graceful shutdown now in progress"),
michael@0 1515 #ifdef WSATYPE_NOT_FOUND
michael@0 1516 E(WSATYPE_NOT_FOUND, "Class type not found"),
michael@0 1517 #endif
michael@0 1518 E(WSAHOST_NOT_FOUND, "Host not found"),
michael@0 1519 E(WSATRY_AGAIN, "Nonauthoritative host not found"),
michael@0 1520 E(WSANO_RECOVERY, "This is a nonrecoverable error"),
michael@0 1521 E(WSANO_DATA, "Valid name, no data record of requested type)"),
michael@0 1522
michael@0 1523 /* There are some more error codes whose numeric values are marked
michael@0 1524 * <b>OS dependent</b>. They start with WSA_, apparently for the same
michael@0 1525 * reason that practitioners of some craft traditions deliberately
michael@0 1526 * introduce imperfections into their baskets and rugs "to allow the
michael@0 1527 * evil spirits to escape." If we catch them, then our binaries
michael@0 1528 * might not report consistent results across versions of Windows.
michael@0 1529 * Thus, I'm going to let them all fall through.
michael@0 1530 */
michael@0 1531 { -1, NULL },
michael@0 1532 };
michael@0 1533 #undef E
michael@0 1534 /** Equivalent to strerror, but for windows socket errors. */
michael@0 1535 const char *
michael@0 1536 evutil_socket_error_to_string(int errcode)
michael@0 1537 {
michael@0 1538 /* XXXX Is there really no built-in function to do this? */
michael@0 1539 int i;
michael@0 1540 for (i=0; windows_socket_errors[i].code >= 0; ++i) {
michael@0 1541 if (errcode == windows_socket_errors[i].code)
michael@0 1542 return windows_socket_errors[i].msg;
michael@0 1543 }
michael@0 1544 return strerror(errcode);
michael@0 1545 }
michael@0 1546 #endif
michael@0 1547
michael@0 1548 int
michael@0 1549 evutil_snprintf(char *buf, size_t buflen, const char *format, ...)
michael@0 1550 {
michael@0 1551 int r;
michael@0 1552 va_list ap;
michael@0 1553 va_start(ap, format);
michael@0 1554 r = evutil_vsnprintf(buf, buflen, format, ap);
michael@0 1555 va_end(ap);
michael@0 1556 return r;
michael@0 1557 }
michael@0 1558
michael@0 1559 int
michael@0 1560 evutil_vsnprintf(char *buf, size_t buflen, const char *format, va_list ap)
michael@0 1561 {
michael@0 1562 int r;
michael@0 1563 if (!buflen)
michael@0 1564 return 0;
michael@0 1565 #ifdef _MSC_VER
michael@0 1566 r = _vsnprintf(buf, buflen, format, ap);
michael@0 1567 if (r < 0)
michael@0 1568 r = _vscprintf(format, ap);
michael@0 1569 #elif defined(sgi)
michael@0 1570 /* Make sure we always use the correct vsnprintf on IRIX */
michael@0 1571 extern int _xpg5_vsnprintf(char * __restrict,
michael@0 1572 __SGI_LIBC_NAMESPACE_QUALIFIER size_t,
michael@0 1573 const char * __restrict, /* va_list */ char *);
michael@0 1574
michael@0 1575 r = _xpg5_vsnprintf(buf, buflen, format, ap);
michael@0 1576 #else
michael@0 1577 r = vsnprintf(buf, buflen, format, ap);
michael@0 1578 #endif
michael@0 1579 buf[buflen-1] = '\0';
michael@0 1580 return r;
michael@0 1581 }
michael@0 1582
michael@0 1583 #define USE_INTERNAL_NTOP
michael@0 1584 #define USE_INTERNAL_PTON
michael@0 1585
michael@0 1586 const char *
michael@0 1587 evutil_inet_ntop(int af, const void *src, char *dst, size_t len)
michael@0 1588 {
michael@0 1589 #if defined(_EVENT_HAVE_INET_NTOP) && !defined(USE_INTERNAL_NTOP)
michael@0 1590 return inet_ntop(af, src, dst, len);
michael@0 1591 #else
michael@0 1592 if (af == AF_INET) {
michael@0 1593 const struct in_addr *in = src;
michael@0 1594 const ev_uint32_t a = ntohl(in->s_addr);
michael@0 1595 int r;
michael@0 1596 r = evutil_snprintf(dst, len, "%d.%d.%d.%d",
michael@0 1597 (int)(ev_uint8_t)((a>>24)&0xff),
michael@0 1598 (int)(ev_uint8_t)((a>>16)&0xff),
michael@0 1599 (int)(ev_uint8_t)((a>>8 )&0xff),
michael@0 1600 (int)(ev_uint8_t)((a )&0xff));
michael@0 1601 if (r<0||(size_t)r>=len)
michael@0 1602 return NULL;
michael@0 1603 else
michael@0 1604 return dst;
michael@0 1605 #ifdef AF_INET6
michael@0 1606 } else if (af == AF_INET6) {
michael@0 1607 const struct in6_addr *addr = src;
michael@0 1608 char buf[64], *cp;
michael@0 1609 int longestGapLen = 0, longestGapPos = -1, i,
michael@0 1610 curGapPos = -1, curGapLen = 0;
michael@0 1611 ev_uint16_t words[8];
michael@0 1612 for (i = 0; i < 8; ++i) {
michael@0 1613 words[i] =
michael@0 1614 (((ev_uint16_t)addr->s6_addr[2*i])<<8) + addr->s6_addr[2*i+1];
michael@0 1615 }
michael@0 1616 if (words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 &&
michael@0 1617 words[4] == 0 && ((words[5] == 0 && words[6] && words[7]) ||
michael@0 1618 (words[5] == 0xffff))) {
michael@0 1619 /* This is an IPv4 address. */
michael@0 1620 if (words[5] == 0) {
michael@0 1621 evutil_snprintf(buf, sizeof(buf), "::%d.%d.%d.%d",
michael@0 1622 addr->s6_addr[12], addr->s6_addr[13],
michael@0 1623 addr->s6_addr[14], addr->s6_addr[15]);
michael@0 1624 } else {
michael@0 1625 evutil_snprintf(buf, sizeof(buf), "::%x:%d.%d.%d.%d", words[5],
michael@0 1626 addr->s6_addr[12], addr->s6_addr[13],
michael@0 1627 addr->s6_addr[14], addr->s6_addr[15]);
michael@0 1628 }
michael@0 1629 if (strlen(buf) > len)
michael@0 1630 return NULL;
michael@0 1631 strlcpy(dst, buf, len);
michael@0 1632 return dst;
michael@0 1633 }
michael@0 1634 i = 0;
michael@0 1635 while (i < 8) {
michael@0 1636 if (words[i] == 0) {
michael@0 1637 curGapPos = i++;
michael@0 1638 curGapLen = 1;
michael@0 1639 while (i<8 && words[i] == 0) {
michael@0 1640 ++i; ++curGapLen;
michael@0 1641 }
michael@0 1642 if (curGapLen > longestGapLen) {
michael@0 1643 longestGapPos = curGapPos;
michael@0 1644 longestGapLen = curGapLen;
michael@0 1645 }
michael@0 1646 } else {
michael@0 1647 ++i;
michael@0 1648 }
michael@0 1649 }
michael@0 1650 if (longestGapLen<=1)
michael@0 1651 longestGapPos = -1;
michael@0 1652
michael@0 1653 cp = buf;
michael@0 1654 for (i = 0; i < 8; ++i) {
michael@0 1655 if (words[i] == 0 && longestGapPos == i) {
michael@0 1656 if (i == 0)
michael@0 1657 *cp++ = ':';
michael@0 1658 *cp++ = ':';
michael@0 1659 while (i < 8 && words[i] == 0)
michael@0 1660 ++i;
michael@0 1661 --i; /* to compensate for loop increment. */
michael@0 1662 } else {
michael@0 1663 evutil_snprintf(cp,
michael@0 1664 sizeof(buf)-(cp-buf), "%x", (unsigned)words[i]);
michael@0 1665 cp += strlen(cp);
michael@0 1666 if (i != 7)
michael@0 1667 *cp++ = ':';
michael@0 1668 }
michael@0 1669 }
michael@0 1670 *cp = '\0';
michael@0 1671 if (strlen(buf) > len)
michael@0 1672 return NULL;
michael@0 1673 strlcpy(dst, buf, len);
michael@0 1674 return dst;
michael@0 1675 #endif
michael@0 1676 } else {
michael@0 1677 return NULL;
michael@0 1678 }
michael@0 1679 #endif
michael@0 1680 }
michael@0 1681
michael@0 1682 int
michael@0 1683 evutil_inet_pton(int af, const char *src, void *dst)
michael@0 1684 {
michael@0 1685 #if defined(_EVENT_HAVE_INET_PTON) && !defined(USE_INTERNAL_PTON)
michael@0 1686 return inet_pton(af, src, dst);
michael@0 1687 #else
michael@0 1688 if (af == AF_INET) {
michael@0 1689 int a,b,c,d;
michael@0 1690 char more;
michael@0 1691 struct in_addr *addr = dst;
michael@0 1692 if (sscanf(src, "%d.%d.%d.%d%c", &a,&b,&c,&d,&more) != 4)
michael@0 1693 return 0;
michael@0 1694 if (a < 0 || a > 255) return 0;
michael@0 1695 if (b < 0 || b > 255) return 0;
michael@0 1696 if (c < 0 || c > 255) return 0;
michael@0 1697 if (d < 0 || d > 255) return 0;
michael@0 1698 addr->s_addr = htonl((a<<24) | (b<<16) | (c<<8) | d);
michael@0 1699 return 1;
michael@0 1700 #ifdef AF_INET6
michael@0 1701 } else if (af == AF_INET6) {
michael@0 1702 struct in6_addr *out = dst;
michael@0 1703 ev_uint16_t words[8];
michael@0 1704 int gapPos = -1, i, setWords=0;
michael@0 1705 const char *dot = strchr(src, '.');
michael@0 1706 const char *eow; /* end of words. */
michael@0 1707 if (dot == src)
michael@0 1708 return 0;
michael@0 1709 else if (!dot)
michael@0 1710 eow = src+strlen(src);
michael@0 1711 else {
michael@0 1712 int byte1,byte2,byte3,byte4;
michael@0 1713 char more;
michael@0 1714 for (eow = dot-1; eow >= src && EVUTIL_ISDIGIT(*eow); --eow)
michael@0 1715 ;
michael@0 1716 ++eow;
michael@0 1717
michael@0 1718 /* We use "scanf" because some platform inet_aton()s are too lax
michael@0 1719 * about IPv4 addresses of the form "1.2.3" */
michael@0 1720 if (sscanf(eow, "%d.%d.%d.%d%c",
michael@0 1721 &byte1,&byte2,&byte3,&byte4,&more) != 4)
michael@0 1722 return 0;
michael@0 1723
michael@0 1724 if (byte1 > 255 || byte1 < 0 ||
michael@0 1725 byte2 > 255 || byte2 < 0 ||
michael@0 1726 byte3 > 255 || byte3 < 0 ||
michael@0 1727 byte4 > 255 || byte4 < 0)
michael@0 1728 return 0;
michael@0 1729
michael@0 1730 words[6] = (byte1<<8) | byte2;
michael@0 1731 words[7] = (byte3<<8) | byte4;
michael@0 1732 setWords += 2;
michael@0 1733 }
michael@0 1734
michael@0 1735 i = 0;
michael@0 1736 while (src < eow) {
michael@0 1737 if (i > 7)
michael@0 1738 return 0;
michael@0 1739 if (EVUTIL_ISXDIGIT(*src)) {
michael@0 1740 char *next;
michael@0 1741 long r = strtol(src, &next, 16);
michael@0 1742 if (next > 4+src)
michael@0 1743 return 0;
michael@0 1744 if (next == src)
michael@0 1745 return 0;
michael@0 1746 if (r<0 || r>65536)
michael@0 1747 return 0;
michael@0 1748
michael@0 1749 words[i++] = (ev_uint16_t)r;
michael@0 1750 setWords++;
michael@0 1751 src = next;
michael@0 1752 if (*src != ':' && src != eow)
michael@0 1753 return 0;
michael@0 1754 ++src;
michael@0 1755 } else if (*src == ':' && i > 0 && gapPos==-1) {
michael@0 1756 gapPos = i;
michael@0 1757 ++src;
michael@0 1758 } else if (*src == ':' && i == 0 && src[1] == ':' && gapPos==-1) {
michael@0 1759 gapPos = i;
michael@0 1760 src += 2;
michael@0 1761 } else {
michael@0 1762 return 0;
michael@0 1763 }
michael@0 1764 }
michael@0 1765
michael@0 1766 if (setWords > 8 ||
michael@0 1767 (setWords == 8 && gapPos != -1) ||
michael@0 1768 (setWords < 8 && gapPos == -1))
michael@0 1769 return 0;
michael@0 1770
michael@0 1771 if (gapPos >= 0) {
michael@0 1772 int nToMove = setWords - (dot ? 2 : 0) - gapPos;
michael@0 1773 int gapLen = 8 - setWords;
michael@0 1774 /* assert(nToMove >= 0); */
michael@0 1775 if (nToMove < 0)
michael@0 1776 return -1; /* should be impossible */
michael@0 1777 memmove(&words[gapPos+gapLen], &words[gapPos],
michael@0 1778 sizeof(ev_uint16_t)*nToMove);
michael@0 1779 memset(&words[gapPos], 0, sizeof(ev_uint16_t)*gapLen);
michael@0 1780 }
michael@0 1781 for (i = 0; i < 8; ++i) {
michael@0 1782 out->s6_addr[2*i ] = words[i] >> 8;
michael@0 1783 out->s6_addr[2*i+1] = words[i] & 0xff;
michael@0 1784 }
michael@0 1785
michael@0 1786 return 1;
michael@0 1787 #endif
michael@0 1788 } else {
michael@0 1789 return -1;
michael@0 1790 }
michael@0 1791 #endif
michael@0 1792 }
michael@0 1793
michael@0 1794 int
michael@0 1795 evutil_parse_sockaddr_port(const char *ip_as_string, struct sockaddr *out, int *outlen)
michael@0 1796 {
michael@0 1797 int port;
michael@0 1798 char buf[128];
michael@0 1799 const char *cp, *addr_part, *port_part;
michael@0 1800 int is_ipv6;
michael@0 1801 /* recognized formats are:
michael@0 1802 * [ipv6]:port
michael@0 1803 * ipv6
michael@0 1804 * [ipv6]
michael@0 1805 * ipv4:port
michael@0 1806 * ipv4
michael@0 1807 */
michael@0 1808
michael@0 1809 cp = strchr(ip_as_string, ':');
michael@0 1810 if (*ip_as_string == '[') {
michael@0 1811 int len;
michael@0 1812 if (!(cp = strchr(ip_as_string, ']'))) {
michael@0 1813 return -1;
michael@0 1814 }
michael@0 1815 len = (int) ( cp-(ip_as_string + 1) );
michael@0 1816 if (len > (int)sizeof(buf)-1) {
michael@0 1817 return -1;
michael@0 1818 }
michael@0 1819 memcpy(buf, ip_as_string+1, len);
michael@0 1820 buf[len] = '\0';
michael@0 1821 addr_part = buf;
michael@0 1822 if (cp[1] == ':')
michael@0 1823 port_part = cp+2;
michael@0 1824 else
michael@0 1825 port_part = NULL;
michael@0 1826 is_ipv6 = 1;
michael@0 1827 } else if (cp && strchr(cp+1, ':')) {
michael@0 1828 is_ipv6 = 1;
michael@0 1829 addr_part = ip_as_string;
michael@0 1830 port_part = NULL;
michael@0 1831 } else if (cp) {
michael@0 1832 is_ipv6 = 0;
michael@0 1833 if (cp - ip_as_string > (int)sizeof(buf)-1) {
michael@0 1834 return -1;
michael@0 1835 }
michael@0 1836 memcpy(buf, ip_as_string, cp-ip_as_string);
michael@0 1837 buf[cp-ip_as_string] = '\0';
michael@0 1838 addr_part = buf;
michael@0 1839 port_part = cp+1;
michael@0 1840 } else {
michael@0 1841 addr_part = ip_as_string;
michael@0 1842 port_part = NULL;
michael@0 1843 is_ipv6 = 0;
michael@0 1844 }
michael@0 1845
michael@0 1846 if (port_part == NULL) {
michael@0 1847 port = 0;
michael@0 1848 } else {
michael@0 1849 port = atoi(port_part);
michael@0 1850 if (port <= 0 || port > 65535) {
michael@0 1851 return -1;
michael@0 1852 }
michael@0 1853 }
michael@0 1854
michael@0 1855 if (!addr_part)
michael@0 1856 return -1; /* Should be impossible. */
michael@0 1857 #ifdef AF_INET6
michael@0 1858 if (is_ipv6)
michael@0 1859 {
michael@0 1860 struct sockaddr_in6 sin6;
michael@0 1861 memset(&sin6, 0, sizeof(sin6));
michael@0 1862 #ifdef _EVENT_HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
michael@0 1863 sin6.sin6_len = sizeof(sin6);
michael@0 1864 #endif
michael@0 1865 sin6.sin6_family = AF_INET6;
michael@0 1866 sin6.sin6_port = htons(port);
michael@0 1867 if (1 != evutil_inet_pton(AF_INET6, addr_part, &sin6.sin6_addr))
michael@0 1868 return -1;
michael@0 1869 if ((int)sizeof(sin6) > *outlen)
michael@0 1870 return -1;
michael@0 1871 memset(out, 0, *outlen);
michael@0 1872 memcpy(out, &sin6, sizeof(sin6));
michael@0 1873 *outlen = sizeof(sin6);
michael@0 1874 return 0;
michael@0 1875 }
michael@0 1876 else
michael@0 1877 #endif
michael@0 1878 {
michael@0 1879 struct sockaddr_in sin;
michael@0 1880 memset(&sin, 0, sizeof(sin));
michael@0 1881 #ifdef _EVENT_HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
michael@0 1882 sin.sin_len = sizeof(sin);
michael@0 1883 #endif
michael@0 1884 sin.sin_family = AF_INET;
michael@0 1885 sin.sin_port = htons(port);
michael@0 1886 if (1 != evutil_inet_pton(AF_INET, addr_part, &sin.sin_addr))
michael@0 1887 return -1;
michael@0 1888 if ((int)sizeof(sin) > *outlen)
michael@0 1889 return -1;
michael@0 1890 memset(out, 0, *outlen);
michael@0 1891 memcpy(out, &sin, sizeof(sin));
michael@0 1892 *outlen = sizeof(sin);
michael@0 1893 return 0;
michael@0 1894 }
michael@0 1895 }
michael@0 1896
michael@0 1897 const char *
michael@0 1898 evutil_format_sockaddr_port(const struct sockaddr *sa, char *out, size_t outlen)
michael@0 1899 {
michael@0 1900 char b[128];
michael@0 1901 const char *res=NULL;
michael@0 1902 int port;
michael@0 1903 if (sa->sa_family == AF_INET) {
michael@0 1904 const struct sockaddr_in *sin = (const struct sockaddr_in*)sa;
michael@0 1905 res = evutil_inet_ntop(AF_INET, &sin->sin_addr,b,sizeof(b));
michael@0 1906 port = ntohs(sin->sin_port);
michael@0 1907 if (res) {
michael@0 1908 evutil_snprintf(out, outlen, "%s:%d", b, port);
michael@0 1909 return out;
michael@0 1910 }
michael@0 1911 } else if (sa->sa_family == AF_INET6) {
michael@0 1912 const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6*)sa;
michael@0 1913 res = evutil_inet_ntop(AF_INET6, &sin6->sin6_addr,b,sizeof(b));
michael@0 1914 port = ntohs(sin6->sin6_port);
michael@0 1915 if (res) {
michael@0 1916 evutil_snprintf(out, outlen, "[%s]:%d", b, port);
michael@0 1917 return out;
michael@0 1918 }
michael@0 1919 }
michael@0 1920
michael@0 1921 evutil_snprintf(out, outlen, "<addr with socktype %d>",
michael@0 1922 (int)sa->sa_family);
michael@0 1923 return out;
michael@0 1924 }
michael@0 1925
michael@0 1926 int
michael@0 1927 evutil_sockaddr_cmp(const struct sockaddr *sa1, const struct sockaddr *sa2,
michael@0 1928 int include_port)
michael@0 1929 {
michael@0 1930 int r;
michael@0 1931 if (0 != (r = (sa1->sa_family - sa2->sa_family)))
michael@0 1932 return r;
michael@0 1933
michael@0 1934 if (sa1->sa_family == AF_INET) {
michael@0 1935 const struct sockaddr_in *sin1, *sin2;
michael@0 1936 sin1 = (const struct sockaddr_in *)sa1;
michael@0 1937 sin2 = (const struct sockaddr_in *)sa2;
michael@0 1938 if (sin1->sin_addr.s_addr < sin2->sin_addr.s_addr)
michael@0 1939 return -1;
michael@0 1940 else if (sin1->sin_addr.s_addr > sin2->sin_addr.s_addr)
michael@0 1941 return 1;
michael@0 1942 else if (include_port &&
michael@0 1943 (r = ((int)sin1->sin_port - (int)sin2->sin_port)))
michael@0 1944 return r;
michael@0 1945 else
michael@0 1946 return 0;
michael@0 1947 }
michael@0 1948 #ifdef AF_INET6
michael@0 1949 else if (sa1->sa_family == AF_INET6) {
michael@0 1950 const struct sockaddr_in6 *sin1, *sin2;
michael@0 1951 sin1 = (const struct sockaddr_in6 *)sa1;
michael@0 1952 sin2 = (const struct sockaddr_in6 *)sa2;
michael@0 1953 if ((r = memcmp(sin1->sin6_addr.s6_addr, sin2->sin6_addr.s6_addr, 16)))
michael@0 1954 return r;
michael@0 1955 else if (include_port &&
michael@0 1956 (r = ((int)sin1->sin6_port - (int)sin2->sin6_port)))
michael@0 1957 return r;
michael@0 1958 else
michael@0 1959 return 0;
michael@0 1960 }
michael@0 1961 #endif
michael@0 1962 return 1;
michael@0 1963 }
michael@0 1964
michael@0 1965 /* Tables to implement ctypes-replacement EVUTIL_IS*() functions. Each table
michael@0 1966 * has 256 bits to look up whether a character is in some set or not. This
michael@0 1967 * fails on non-ASCII platforms, but so does every other place where we
michael@0 1968 * take a char and write it onto the network.
michael@0 1969 **/
michael@0 1970 static const ev_uint32_t EVUTIL_ISALPHA_TABLE[8] =
michael@0 1971 { 0, 0, 0x7fffffe, 0x7fffffe, 0, 0, 0, 0 };
michael@0 1972 static const ev_uint32_t EVUTIL_ISALNUM_TABLE[8] =
michael@0 1973 { 0, 0x3ff0000, 0x7fffffe, 0x7fffffe, 0, 0, 0, 0 };
michael@0 1974 static const ev_uint32_t EVUTIL_ISSPACE_TABLE[8] = { 0x3e00, 0x1, 0, 0, 0, 0, 0, 0 };
michael@0 1975 static const ev_uint32_t EVUTIL_ISXDIGIT_TABLE[8] =
michael@0 1976 { 0, 0x3ff0000, 0x7e, 0x7e, 0, 0, 0, 0 };
michael@0 1977 static const ev_uint32_t EVUTIL_ISDIGIT_TABLE[8] = { 0, 0x3ff0000, 0, 0, 0, 0, 0, 0 };
michael@0 1978 static const ev_uint32_t EVUTIL_ISPRINT_TABLE[8] =
michael@0 1979 { 0, 0xffffffff, 0xffffffff, 0x7fffffff, 0, 0, 0, 0x0 };
michael@0 1980 static const ev_uint32_t EVUTIL_ISUPPER_TABLE[8] = { 0, 0, 0x7fffffe, 0, 0, 0, 0, 0 };
michael@0 1981 static const ev_uint32_t EVUTIL_ISLOWER_TABLE[8] = { 0, 0, 0, 0x7fffffe, 0, 0, 0, 0 };
michael@0 1982 /* Upper-casing and lowercasing tables to map characters to upper/lowercase
michael@0 1983 * equivalents. */
michael@0 1984 static const unsigned char EVUTIL_TOUPPER_TABLE[256] = {
michael@0 1985 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
michael@0 1986 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
michael@0 1987 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,
michael@0 1988 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,
michael@0 1989 64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,
michael@0 1990 80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,
michael@0 1991 96,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,
michael@0 1992 80,81,82,83,84,85,86,87,88,89,90,123,124,125,126,127,
michael@0 1993 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
michael@0 1994 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
michael@0 1995 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
michael@0 1996 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
michael@0 1997 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
michael@0 1998 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
michael@0 1999 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
michael@0 2000 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,
michael@0 2001 };
michael@0 2002 static const unsigned char EVUTIL_TOLOWER_TABLE[256] = {
michael@0 2003 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
michael@0 2004 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
michael@0 2005 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,
michael@0 2006 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,
michael@0 2007 64,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,
michael@0 2008 112,113,114,115,116,117,118,119,120,121,122,91,92,93,94,95,
michael@0 2009 96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,
michael@0 2010 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
michael@0 2011 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
michael@0 2012 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
michael@0 2013 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
michael@0 2014 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
michael@0 2015 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
michael@0 2016 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
michael@0 2017 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
michael@0 2018 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,
michael@0 2019 };
michael@0 2020
michael@0 2021 #define IMPL_CTYPE_FN(name) \
michael@0 2022 int EVUTIL_##name(char c) { \
michael@0 2023 ev_uint8_t u = c; \
michael@0 2024 return !!(EVUTIL_##name##_TABLE[(u >> 5) & 7] & (1 << (u & 31))); \
michael@0 2025 }
michael@0 2026 IMPL_CTYPE_FN(ISALPHA)
michael@0 2027 IMPL_CTYPE_FN(ISALNUM)
michael@0 2028 IMPL_CTYPE_FN(ISSPACE)
michael@0 2029 IMPL_CTYPE_FN(ISDIGIT)
michael@0 2030 IMPL_CTYPE_FN(ISXDIGIT)
michael@0 2031 IMPL_CTYPE_FN(ISPRINT)
michael@0 2032 IMPL_CTYPE_FN(ISLOWER)
michael@0 2033 IMPL_CTYPE_FN(ISUPPER)
michael@0 2034
michael@0 2035 char EVUTIL_TOLOWER(char c)
michael@0 2036 {
michael@0 2037 return ((char)EVUTIL_TOLOWER_TABLE[(ev_uint8_t)c]);
michael@0 2038 }
michael@0 2039 char EVUTIL_TOUPPER(char c)
michael@0 2040 {
michael@0 2041 return ((char)EVUTIL_TOUPPER_TABLE[(ev_uint8_t)c]);
michael@0 2042 }
michael@0 2043 int
michael@0 2044 evutil_ascii_strcasecmp(const char *s1, const char *s2)
michael@0 2045 {
michael@0 2046 char c1, c2;
michael@0 2047 while (1) {
michael@0 2048 c1 = EVUTIL_TOLOWER(*s1++);
michael@0 2049 c2 = EVUTIL_TOLOWER(*s2++);
michael@0 2050 if (c1 < c2)
michael@0 2051 return -1;
michael@0 2052 else if (c1 > c2)
michael@0 2053 return 1;
michael@0 2054 else if (c1 == 0)
michael@0 2055 return 0;
michael@0 2056 }
michael@0 2057 }
michael@0 2058 int evutil_ascii_strncasecmp(const char *s1, const char *s2, size_t n)
michael@0 2059 {
michael@0 2060 char c1, c2;
michael@0 2061 while (n--) {
michael@0 2062 c1 = EVUTIL_TOLOWER(*s1++);
michael@0 2063 c2 = EVUTIL_TOLOWER(*s2++);
michael@0 2064 if (c1 < c2)
michael@0 2065 return -1;
michael@0 2066 else if (c1 > c2)
michael@0 2067 return 1;
michael@0 2068 else if (c1 == 0)
michael@0 2069 return 0;
michael@0 2070 }
michael@0 2071 return 0;
michael@0 2072 }
michael@0 2073
michael@0 2074 static int
michael@0 2075 evutil_issetugid(void)
michael@0 2076 {
michael@0 2077 #ifdef _EVENT_HAVE_ISSETUGID
michael@0 2078 return issetugid();
michael@0 2079 #else
michael@0 2080
michael@0 2081 #ifdef _EVENT_HAVE_GETEUID
michael@0 2082 if (getuid() != geteuid())
michael@0 2083 return 1;
michael@0 2084 #endif
michael@0 2085 #ifdef _EVENT_HAVE_GETEGID
michael@0 2086 if (getgid() != getegid())
michael@0 2087 return 1;
michael@0 2088 #endif
michael@0 2089 return 0;
michael@0 2090 #endif
michael@0 2091 }
michael@0 2092
michael@0 2093 const char *
michael@0 2094 evutil_getenv(const char *varname)
michael@0 2095 {
michael@0 2096 if (evutil_issetugid())
michael@0 2097 return NULL;
michael@0 2098
michael@0 2099 return getenv(varname);
michael@0 2100 }
michael@0 2101
michael@0 2102 long
michael@0 2103 _evutil_weakrand(void)
michael@0 2104 {
michael@0 2105 #ifdef WIN32
michael@0 2106 return rand();
michael@0 2107 #else
michael@0 2108 return random();
michael@0 2109 #endif
michael@0 2110 }
michael@0 2111
michael@0 2112 int
michael@0 2113 evutil_sockaddr_is_loopback(const struct sockaddr *addr)
michael@0 2114 {
michael@0 2115 static const char LOOPBACK_S6[16] =
michael@0 2116 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1";
michael@0 2117 if (addr->sa_family == AF_INET) {
michael@0 2118 struct sockaddr_in *sin = (struct sockaddr_in *)addr;
michael@0 2119 return (ntohl(sin->sin_addr.s_addr) & 0xff000000) == 0x7f000000;
michael@0 2120 } else if (addr->sa_family == AF_INET6) {
michael@0 2121 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr;
michael@0 2122 return !memcmp(sin6->sin6_addr.s6_addr, LOOPBACK_S6, 16);
michael@0 2123 }
michael@0 2124 return 0;
michael@0 2125 }
michael@0 2126
michael@0 2127 #define MAX_SECONDS_IN_MSEC_LONG \
michael@0 2128 (((LONG_MAX) - 999) / 1000)
michael@0 2129
michael@0 2130 long
michael@0 2131 evutil_tv_to_msec(const struct timeval *tv)
michael@0 2132 {
michael@0 2133 if (tv->tv_usec > 1000000 || tv->tv_sec > MAX_SECONDS_IN_MSEC_LONG)
michael@0 2134 return -1;
michael@0 2135
michael@0 2136 return (tv->tv_sec * 1000) + ((tv->tv_usec + 999) / 1000);
michael@0 2137 }
michael@0 2138
michael@0 2139 int
michael@0 2140 evutil_hex_char_to_int(char c)
michael@0 2141 {
michael@0 2142 switch(c)
michael@0 2143 {
michael@0 2144 case '0': return 0;
michael@0 2145 case '1': return 1;
michael@0 2146 case '2': return 2;
michael@0 2147 case '3': return 3;
michael@0 2148 case '4': return 4;
michael@0 2149 case '5': return 5;
michael@0 2150 case '6': return 6;
michael@0 2151 case '7': return 7;
michael@0 2152 case '8': return 8;
michael@0 2153 case '9': return 9;
michael@0 2154 case 'A': case 'a': return 10;
michael@0 2155 case 'B': case 'b': return 11;
michael@0 2156 case 'C': case 'c': return 12;
michael@0 2157 case 'D': case 'd': return 13;
michael@0 2158 case 'E': case 'e': return 14;
michael@0 2159 case 'F': case 'f': return 15;
michael@0 2160 }
michael@0 2161 return -1;
michael@0 2162 }
michael@0 2163
michael@0 2164 #ifdef WIN32
michael@0 2165 HANDLE
michael@0 2166 evutil_load_windows_system_library(const TCHAR *library_name)
michael@0 2167 {
michael@0 2168 TCHAR path[MAX_PATH];
michael@0 2169 unsigned n;
michael@0 2170 n = GetSystemDirectory(path, MAX_PATH);
michael@0 2171 if (n == 0 || n + _tcslen(library_name) + 2 >= MAX_PATH)
michael@0 2172 return 0;
michael@0 2173 _tcscat(path, TEXT("\\"));
michael@0 2174 _tcscat(path, library_name);
michael@0 2175 return LoadLibrary(path);
michael@0 2176 }
michael@0 2177 #endif
michael@0 2178

mercurial