X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=netatalk.git;a=blobdiff_plain;f=libevent%2Fevutil.c;h=b6634591a9bccbc0bfdfdad516d13550bee28c2f;hp=b769acc2b323fa7f90a42074d5bc81af8b395e06;hb=33c70ce1349f3e7fcbc5776785f34f3bd89f1d92;hpb=b0bcb8f6b0571592a50ce039882c9319e012a270 diff --git a/libevent/evutil.c b/libevent/evutil.c index b769acc2..b6634591 100644 --- a/libevent/evutil.c +++ b/libevent/evutil.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2010 Niels Provos and Nick Mathewson + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -55,15 +55,15 @@ #include #include #include -#ifdef _EVENT_HAVE_ARPA_INET_H -#include -#endif #ifdef _EVENT_HAVE_NETINET_IN_H #include #endif #ifdef _EVENT_HAVE_NETINET_IN6_H #include #endif +#ifdef _EVENT_HAVE_ARPA_INET_H +#include +#endif #ifndef _EVENT_HAVE_GETTIMEOFDAY #include @@ -87,6 +87,30 @@ #define stat _stati64 #endif +int +evutil_open_closeonexec(const char *pathname, int flags, unsigned mode) +{ + int fd; + +#ifdef O_CLOEXEC + flags |= O_CLOEXEC; +#endif + + if (flags & O_CREAT) + fd = open(pathname, flags, (mode_t)mode); + else + fd = open(pathname, flags); + if (fd < 0) + return -1; + +#if !defined(O_CLOEXEC) && defined(FD_CLOEXEC) + if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) + return -1; +#endif + + return fd; +} + /** Read the contents of 'filename' into a newly allocated NUL-terminated string. Set *content_out to hold this string, and *len_out to hold its @@ -117,7 +141,7 @@ evutil_read_file(const char *filename, char **content_out, size_t *len_out, mode |= O_BINARY; #endif - fd = open(filename, mode); + fd = evutil_open_closeonexec(filename, mode, 0); if (fd < 0) return -1; if (fstat(fd, &st) || st.st_size < 0 || @@ -351,6 +375,8 @@ evutil_strtoll(const char *s, char **endptr, int base) r = (ev_int64_t) _atoi64(s); while (isspace(*s)) ++s; + if (*s == '-') + ++s; while (isdigit(*s)) ++s; if (endptr) @@ -358,6 +384,36 @@ evutil_strtoll(const char *s, char **endptr, int base) return r; #elif defined(WIN32) return (ev_int64_t) _strtoi64(s, endptr, base); +#elif defined(_EVENT_SIZEOF_LONG_LONG) && _EVENT_SIZEOF_LONG_LONG == 8 + long long r; + int n; + if (base != 10 && base != 16) + return 0; + if (base == 10) { + n = sscanf(s, "%lld", &r); + } else { + unsigned long long ru=0; + n = sscanf(s, "%llx", &ru); + if (ru > EV_INT64_MAX) + return 0; + r = (long long) ru; + } + if (n != 1) + return 0; + while (EVUTIL_ISSPACE(*s)) + ++s; + if (*s == '-') + ++s; + if (base == 10) { + while (EVUTIL_ISDIGIT(*s)) + ++s; + } else { + while (EVUTIL_ISXDIGIT(*s)) + ++s; + } + if (endptr) + *endptr = (char*) s; + return r; #else #error "I don't know how to parse 64-bit integers." #endif @@ -413,9 +469,9 @@ evutil_socket_connect(evutil_socket_t *fd_ptr, struct sockaddr *sa, int socklen) int made_fd = 0; if (*fd_ptr < 0) { - made_fd = 1; if ((*fd_ptr = socket(sa->sa_family, SOCK_STREAM, 0)) < 0) goto err; + made_fd = 1; if (evutil_make_socket_nonblocking(*fd_ptr) < 0) { goto err; } @@ -479,6 +535,15 @@ evutil_socket_finished_connecting(evutil_socket_t fd) set by evutil_check_interfaces. */ static int have_checked_interfaces, had_ipv4_address, had_ipv6_address; +/* Macro: True iff the IPv4 address 'addr', in host order, is in 127.0.0.0/8 + */ +#define EVUTIL_V4ADDR_IS_LOCALHOST(addr) (((addr)>>24) == 127) + +/* Macro: True iff the IPv4 address 'addr', in host order, is a class D + * (multiclass) address. + */ +#define EVUTIL_V4ADDR_IS_CLASSD(addr) ((((addr)>>24) & 0xf0) == 0xe0) + /* Test whether we have an ipv4 interface and an ipv6 interface. Return 0 if * the test seemed successful. */ static int @@ -522,8 +587,9 @@ evutil_check_interfaces(int force_recheck) getsockname(fd, (struct sockaddr*)&sin_out, &sin_out_len) == 0) { /* We might have an IPv4 interface. */ ev_uint32_t addr = ntohl(sin_out.sin_addr.s_addr); - if (addr == 0 || (addr&0xff000000) == 127 || - (addr & 0xff) == 255 || (addr & 0xf0) == 14) { + if (addr == 0 || + EVUTIL_V4ADDR_IS_LOCALHOST(addr) || + EVUTIL_V4ADDR_IS_CLASSD(addr)) { evutil_inet_ntop(AF_INET, &sin_out.sin_addr, buf, sizeof(buf)); /* This is a reserved, ipv4compat, ipv4map, loopback, @@ -721,6 +787,10 @@ evutil_getaddrinfo_infer_protocols(struct evutil_addrinfo *hints) } } +#if AF_UNSPEC != PF_UNSPEC +#error "I cannot build on a system where AF_UNSPEC != PF_UNSPEC" +#endif + /** Implements the part of looking up hosts by name that's common to both * the blocking and nonblocking resolver: * - Adjust 'hints' to have a reasonable socktype and protocol. @@ -771,7 +841,7 @@ evutil_getaddrinfo_common(const char *nodename, const char *servname, memset(&sin6, 0, sizeof(sin6)); sin6.sin6_family = AF_INET6; sin6.sin6_port = htons(port); - if (hints->ai_flags & AI_PASSIVE) { + if (hints->ai_flags & EVUTIL_AI_PASSIVE) { /* Bind to :: */ } else { /* connect to ::1 */ @@ -788,7 +858,7 @@ evutil_getaddrinfo_common(const char *nodename, const char *servname, memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(port); - if (hints->ai_flags & AI_PASSIVE) { + if (hints->ai_flags & EVUTIL_AI_PASSIVE) { /* Bind to 0.0.0.0 */ } else { /* connect to 127.0.0.1 */ @@ -958,8 +1028,13 @@ addrinfo_from_hostent(const struct hostent *ent, res = evutil_addrinfo_append(res, ai); } - if (res && ((hints->ai_flags & EVUTIL_AI_CANONNAME) && ent->h_name)) + if (res && ((hints->ai_flags & EVUTIL_AI_CANONNAME) && ent->h_name)) { res->ai_canonname = mm_strdup(ent->h_name); + if (res->ai_canonname == NULL) { + evutil_freeaddrinfo(res); + return NULL; + } + } return res; } @@ -1083,7 +1158,7 @@ apply_numeric_port_hack(int port, struct evutil_addrinfo **ai) } } -static void +static int apply_socktype_protocol_hack(struct evutil_addrinfo *ai) { struct evutil_addrinfo *ai_new; @@ -1092,6 +1167,8 @@ apply_socktype_protocol_hack(struct evutil_addrinfo *ai) if (ai->ai_socktype || ai->ai_protocol) continue; ai_new = mm_malloc(sizeof(*ai_new)); + if (!ai_new) + return -1; memcpy(ai_new, ai, sizeof(*ai_new)); ai->ai_socktype = SOCK_STREAM; ai->ai_protocol = IPPROTO_TCP; @@ -1101,6 +1178,7 @@ apply_socktype_protocol_hack(struct evutil_addrinfo *ai) ai_new->ai_next = ai->ai_next; ai->ai_next = ai_new; } + return 0; } #endif @@ -1191,7 +1269,11 @@ evutil_getaddrinfo(const char *nodename, const char *servname, apply_numeric_port_hack(portnum, res); if (need_socktype_protocol_hack()) { - apply_socktype_protocol_hack(*res); + if (apply_socktype_protocol_hack(*res) < 0) { + evutil_freeaddrinfo(*res); + *res = NULL; + return EVUTIL_EAI_MEMORY; + } } return err; #else