diff --git a/src/common/crypto.c b/src/common/crypto.c index 60775e7e7f..8d8c78a1e3 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -41,6 +41,9 @@ #include "util.h" #ifdef MS_WINDOWS +#define WIN32_WINNT 0x400 +#define _WIN32_WINNT 0x400 +#define WIN32_LEAN_AND_MEAN #include #endif diff --git a/src/common/util.c b/src/common/util.c index fb92681e93..64e3a9b5a4 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -39,6 +39,9 @@ #ifdef HAVE_SYS_SOCKET_H #include #endif +#ifdef HAVE_NETDB_H +#include +#endif #ifdef HAVE_UNISTD_H #include #endif @@ -55,6 +58,18 @@ #include #endif +#ifdef HAVE_WINSOCK_H +#define WIN32_WINNT 0x400 +#define _WIN32_WINNT 0x400 +#define WIN32_LEAN_AND_MEAN +#endif +#if _MSC_VER > 1300 +#include +#include +#elif defined(_MSC_VER) +#include +#endif + /* used by inet_addr, not defined on solaris anywhere!? */ #ifndef INADDR_NONE #define INADDR_NONE ((unsigned long) -1) @@ -1368,6 +1383,42 @@ int tor_inet_aton(const char *c, struct in_addr* addr) #endif } +/* Similar behavior to Unix gethostbyname: resolve 'name', and set + * *addr to the proper IP address, in network byte order. Returns 0 + * on success, -1 on failure; 1 on transient failure. + * + * (This function exists because standard windows gethostbyname + * doesn't treat raw IP addresses properly.) + */ +/* Perhaps eventually this should be replaced by a tor_getaddrinfo or + * something. + */ +int tor_lookup_hostname(const char *name, uint32_t *addr) +{ + struct in_addr iaddr; + struct hostent *ent; + tor_assert(addr); + if (tor_inet_aton(name, &iaddr)) { + /* It's an IP. */ + memcpy(addr, &iaddr.s_addr, 4); + return 0; + } else { + ent = gethostbyname(name); + if (ent) { + /* break to remind us if we move away from IPv4 */ + tor_assert(ent->h_length == 4); + memcpy(addr, ent->h_addr, 4); + return 0; + } + memset(addr, 0, 4); +#ifdef MS_WINDOWS + return (WSAGetLastError() == WSATRY_AGAIN) ? 1 : -1; +#else + return (h_errno == TRY_AGAIN) ? 1 : -1; +#endif + } +} + /* Local Variables: mode:c diff --git a/src/common/util.h b/src/common/util.h index b0120e7d37..bd65a0153b 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -212,6 +212,7 @@ int switch_id(char *user, char *group); struct in_addr; int tor_inet_aton(const char *cp, struct in_addr *addr); +int tor_lookup_hostname(const char *name, uint32_t *addr); /* For stupid historical reasons, windows sockets have an independent set of * errnos which they use as the fancy strikes them. diff --git a/src/or/dns.c b/src/or/dns.c index b49e6dafa9..6d7f36fc8a 100644 --- a/src/or/dns.c +++ b/src/or/dns.c @@ -451,7 +451,6 @@ int dnsworker_main(void *data) { char address[MAX_ADDRESSLEN]; unsigned char address_len; char answer[5]; - struct hostent *rent; int *fdarray = data; int fd; @@ -475,21 +474,17 @@ int dnsworker_main(void *data) { } address[address_len] = 0; /* null terminate it */ - rent = gethostbyname(address); - if (!rent) { - if(h_errno == TRY_AGAIN) { /* transient error -- don't cache it */ + switch (tor_lookup_hostname(address, (uint32_t*)answer+1)) { + case 1: log_fn(LOG_INFO,"Could not resolve dest addr %s (transient).",address); answer[0] = DNS_RESOLVE_FAILED_TRANSIENT; - } else { /* permanent error, can be cached */ + break; + case -1: log_fn(LOG_INFO,"Could not resolve dest addr %s (permanent).",address); answer[0] = DNS_RESOLVE_FAILED_PERMANENT; - } - memset(answer+1,0,4); - } else { - tor_assert(rent->h_length == 4); /* break to remind us if we move away from ipv4 */ - answer[0] = DNS_RESOLVE_SUCCEEDED; - memcpy(answer+1, rent->h_addr, 4); - log_fn(LOG_INFO,"Resolved address '%s'.",address); + case 0: + log_fn(LOG_INFO,"Resolved address '%s'.",address); + answer[0] = DNS_RESOLVE_SUCCEEDED; } if(write_all(fd, answer, 5, 1) != 5) { log_fn(LOG_ERR,"writing answer failed. Child exiting."); diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 3c01838dc0..3183820314 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -507,14 +507,11 @@ router_resolve(routerinfo_t *router) { struct hostent *rent; - rent = (struct hostent *)gethostbyname(router->address); - if (!rent) { + if (tor_lookup_hostname(router->address, &router->addr)) { log_fn(LOG_WARN,"Could not get address for router %s (%s).", router->address, router->nickname); return -1; } - tor_assert(rent->h_length == 4); - memcpy(&router->addr, rent->h_addr,rent->h_length); router->addr = ntohl(router->addr); /* get it back into host order */ return 0;