r15517@catbus: nickm | 2007-10-03 13:14:05 -0400

Correct the pointer manipulation in fake_getaddrinfo(), and do the right thing for fake_getaddrinfo(NULL,&ai).  Based on a patch by Lubmir Marinov, hacked until the unit tests passed on Linux with #undef HAVE_GETADDRINFO.


svn:r459
This commit is contained in:
Nick Mathewson 2007-10-03 17:19:22 +00:00
parent bc7b7c249c
commit 49ede3be00
2 changed files with 35 additions and 20 deletions

View File

@ -27,3 +27,4 @@ Changes in current version:
o Make the test.sh script run unit tests for the evpoll method. o Make the test.sh script run unit tests for the evpoll method.
o Make the entire evdns.h header enclosed in "extern C" as appropriate. o Make the entire evdns.h header enclosed in "extern C" as appropriate.
o Fix implementation of strsep on platforms that lack it o Fix implementation of strsep on platforms that lack it
o Fix implementation of getaddrinfo on platforms that lack it; mainly, this will make Windows http.c work better. Original patch by Lubomir Marinov.

34
http.c
View File

@ -90,17 +90,28 @@ struct addrinfo {
static int static int
fake_getaddrinfo(const char *hostname, struct addrinfo *ai) fake_getaddrinfo(const char *hostname, struct addrinfo *ai)
{ {
struct hostent *he; struct hostent *he = NULL;
struct sockaddr_in *sa;
if (hostname) {
he = gethostbyname(hostname); he = gethostbyname(hostname);
if (!he) if (!he)
return (-1); return (-1);
ai->ai_family = he->h_addrtype; }
ai->ai_family = he ? he->h_addrtype : AF_INET;
ai->ai_socktype = SOCK_STREAM; ai->ai_socktype = SOCK_STREAM;
ai->ai_protocol = 0; ai->ai_protocol = 0;
ai->ai_addrlen = he->h_length; ai->ai_addrlen = sizeof(struct sockaddr_in);
if (NULL == (ai->ai_addr = malloc(ai->ai_addrlen))) if (NULL == (ai->ai_addr = malloc(ai->ai_addrlen)))
return (-1); return (-1);
memcpy(ai->ai_addr, &he->h_addr_list[0], ai->ai_addrlen); sa = (struct sockaddr_in*)ai->ai_addr;
memset(sa, 0, ai->ai_addrlen);
if (he) {
sa->sin_family = he->h_addrtype;
memcpy(&sa->sin_addr, he->h_addr_list[0], he->h_length);
} else {
sa->sin_family = AF_INET;
sa->sin_addr.s_addr = INADDR_ANY;
}
ai->ai_next = NULL; ai->ai_next = NULL;
return (0); return (0);
} }
@ -2369,18 +2380,19 @@ bind_socket_ai(struct addrinfo *ai)
static struct addrinfo * static struct addrinfo *
make_addrinfo(const char *address, u_short port) make_addrinfo(const char *address, u_short port)
{ {
struct addrinfo ai[2], *aitop = NULL; struct addrinfo *aitop = NULL;
#ifdef HAVE_GETADDRINFO #ifdef HAVE_GETADDRINFO
struct addrinfo ai;
char strport[NI_MAXSERV]; char strport[NI_MAXSERV];
int ai_result; int ai_result;
memset(&ai[0], 0, sizeof (ai[0])); memset(&ai, 0, sizeof(ai));
ai[0].ai_family = AF_INET; ai.ai_family = AF_INET;
ai[0].ai_socktype = SOCK_STREAM; ai.ai_socktype = SOCK_STREAM;
ai[0].ai_flags = AI_PASSIVE; /* turn NULL host name into INADDR_ANY */ ai.ai_flags = AI_PASSIVE; /* turn NULL host name into INADDR_ANY */
snprintf(strport, sizeof(strport), "%d", port); snprintf(strport, sizeof(strport), "%d", port);
if ((ai_result = getaddrinfo(address, strport, &ai[0], &aitop)) != 0) { if ((ai_result = getaddrinfo(address, strport, &ai, &aitop)) != 0) {
if ( ai_result == EAI_SYSTEM ) if ( ai_result == EAI_SYSTEM )
event_warn("getaddrinfo"); event_warn("getaddrinfo");
else else
@ -2389,6 +2401,7 @@ make_addrinfo(const char *address, u_short port)
} }
#else #else
static int cur; static int cur;
static struct addrinfo ai[2]; /* We will be returning the address of some of this memory so it has to last even after this call. */
if (++cur == 2) cur = 0; /* allow calling this function twice */ if (++cur == 2) cur = 0; /* allow calling this function twice */
if (fake_getaddrinfo(address, &ai[cur]) < 0) { if (fake_getaddrinfo(address, &ai[cur]) < 0) {
@ -2396,6 +2409,7 @@ make_addrinfo(const char *address, u_short port)
return (NULL); return (NULL);
} }
aitop = &ai[cur]; aitop = &ai[cur];
((struct sockaddr_in *) aitop->ai_addr)->sin_port = htons(port);
#endif #endif
return (aitop); return (aitop);