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