diff --git a/ares/CHANGES b/ares/CHANGES index d1f2de800..1266fb854 100644 --- a/ares/CHANGES +++ b/ares/CHANGES @@ -1,5 +1,18 @@ Changelog for the c-ares project +* Jun 30 2008 (Daniel Stenberg) + +- As was pointed out to me by Andreas Schuldei, the MAXHOSTNAMELEN define is + not posix or anything and thus c-ares failed to build on hurd (and possibly + elsewhere). The define was also somewhat artificially used in the windows + port. Now, I instead rewrote the use of gethostbyname to enlarge the host + name buffer in case of need and totally avoid the use of the MAXHOSTNAMELEN + define. I thus also removed the defien from the namser.h file where it was + once added for the windows build. + + I also fixed init_by_defaults() function to not leak memory in case if + error. + * Jun 9 2008 (Yang Tse) - Make libcares.pc generated file for pkg-config include information relative diff --git a/ares/ares_init.c b/ares/ares_init.c index 0b9637105..e33c3973a 100644 --- a/ares/ares_init.c +++ b/ares/ares_init.c @@ -912,7 +912,8 @@ okay: static int init_by_defaults(ares_channel channel) { - char hostname[MAXHOSTNAMELEN + 1]; + char *hostname = NULL; + int rc = ARES_SUCCESS; if (channel->flags == -1) channel->flags = 0; @@ -927,53 +928,103 @@ static int init_by_defaults(ares_channel channel) if (channel->tcp_port == -1) channel->tcp_port = htons(NAMESERVER_PORT); - if (channel->nservers == -1) - { - /* If nobody specified servers, try a local named. */ - channel->servers = malloc(sizeof(struct server_state)); - if (!channel->servers) - return ARES_ENOMEM; - channel->servers[0].addr.s_addr = htonl(INADDR_LOOPBACK); - channel->nservers = 1; + if (channel->nservers == -1) { + /* If nobody specified servers, try a local named. */ + channel->servers = malloc(sizeof(struct server_state)); + if (!channel->servers) { + rc = ARES_ENOMEM; + goto error; + } + channel->servers[0].addr.s_addr = htonl(INADDR_LOOPBACK); + channel->nservers = 1; + } + +#ifdef ENAMETOOLONG +#define toolong(x) (x == -1) && ((ENAMETOOLONG == errno) || (EINVAL == errno)) +#else +#define toolong(x) (x == -1) && (EINVAL == errno) +#endif + + if (channel->ndomains == -1) { + /* Derive a default domain search list from the kernel hostname, + * or set it to empty if the hostname isn't helpful. + */ + size_t len = 64; + int res; + + hostname = (char *)malloc(len); + if(!hostname) { + rc = ARES_ENOMEM; + goto error; } - if (channel->ndomains == -1) - { - /* Derive a default domain search list from the kernel hostname, - * or set it to empty if the hostname isn't helpful. - */ - if (gethostname(hostname, sizeof(hostname)) == -1 - || !strchr(hostname, '.')) - { - channel->ndomains = 0; + do { + res = gethostname(hostname, len); + + if(toolong(res)) { + char *p; + len *= 2; + p = realloc(hostname, len); + if(!p) { + rc = ARES_ENOMEM; + goto error; } - else - { - channel->domains = malloc(sizeof(char *)); - if (!channel->domains) - return ARES_ENOMEM; - channel->ndomains = 0; - channel->domains[0] = strdup(strchr(hostname, '.') + 1); - if (!channel->domains[0]) - return ARES_ENOMEM; - channel->ndomains = 1; - } - } + hostname = p; + continue; + } + else if(res) { + rc = ARES_EBADNAME; + goto error; + } - if (channel->nsort == -1) - { - channel->sortlist = NULL; - channel->nsort = 0; - } + } while(0); - if (!channel->lookups) - { - channel->lookups = strdup("fb"); - if (!channel->lookups) - return ARES_ENOMEM; - } + channel->ndomains = 0; /* default to none */ + if (strchr(hostname, '.')) { + /* a dot was found */ - return ARES_SUCCESS; + channel->domains = malloc(sizeof(char *)); + if (!channel->domains) { + rc = ARES_ENOMEM; + goto error; + } + channel->domains[0] = strdup(strchr(hostname, '.') + 1); + if (!channel->domains[0]) { + rc = ARES_ENOMEM; + goto error; + } + channel->ndomains = 1; + } + } + + if (channel->nsort == -1) { + channel->sortlist = NULL; + channel->nsort = 0; + } + + if (!channel->lookups) { + channel->lookups = strdup("fb"); + if (!channel->lookups) + rc = ARES_ENOMEM; + } + + error: + if(rc) { + if(channel->servers) + free(channel->servers); + + if(channel->domains && channel->domains[0]) + free(channel->domains[0]); + if(channel->domains) + free(channel->domains); + if(channel->lookups) + free(channel->lookups); + } + + if(hostname) + free(hostname); + + return rc; } #ifndef WIN32 diff --git a/ares/nameser.h b/ares/nameser.h index dc8c86e34..b5add9334 100644 --- a/ares/nameser.h +++ b/ares/nameser.h @@ -13,8 +13,6 @@ #ifndef NETWARE -#define MAXHOSTNAMELEN 256 - /* Structure for scatter/gather I/O. */ struct iovec {