/*
- * 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
#include <limits.h>
#include <stdio.h>
#include <string.h>
-#ifdef _EVENT_HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
#ifdef _EVENT_HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef _EVENT_HAVE_NETINET_IN6_H
#include <netinet/in6.h>
#endif
+#ifdef _EVENT_HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
#ifndef _EVENT_HAVE_GETTIMEOFDAY
#include <sys/timeb.h>
#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
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 ||
r = (ev_int64_t) _atoi64(s);
while (isspace(*s))
++s;
+ if (*s == '-')
+ ++s;
while (isdigit(*s))
++s;
if (endptr)
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
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;
}
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
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,
}
}
+#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.
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 */
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 */
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;
}
}
}
-static void
+static int
apply_socktype_protocol_hack(struct evutil_addrinfo *ai)
{
struct evutil_addrinfo *ai_new;
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;
ai_new->ai_next = ai->ai_next;
ai->ai_next = ai_new;
}
+ return 0;
}
#endif
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