- As was pointed out to me by Andreas Schuldei, the MAXHOSTNAMELEN define is
authorDaniel Stenberg <daniel@haxx.se>
Mon, 30 Jun 2008 12:48:25 +0000 (12:48 +0000)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 30 Jun 2008 12:48:25 +0000 (12:48 +0000)
  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.

CHANGES
ares_init.c
nameser.h

diff --git a/CHANGES b/CHANGES
index d1f2de8..1266fb8 100644 (file)
--- a/CHANGES
+++ b/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
index 0b96371..e33c397 100644 (file)
@@ -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;
+  }
 
-  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;
-        }
-      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;
-        }
-    }
+#ifdef ENAMETOOLONG
+#define toolong(x) (x == -1) && ((ENAMETOOLONG == errno) || (EINVAL == errno))
+#else
+#define toolong(x) (x == -1) && (EINVAL == errno)
+#endif
 
-  if (channel->nsort == -1)
-    {
-      channel->sortlist = NULL;
-      channel->nsort = 0;
+  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->lookups)
-    {
-      channel->lookups = strdup("fb");
-      if (!channel->lookups)
-        return ARES_ENOMEM;
+    do {
+      res = gethostname(hostname, len);
+
+      if(toolong(res)) {
+        char *p;
+        len *= 2;
+        p = realloc(hostname, len);
+        if(!p) {
+          rc = ARES_ENOMEM;
+          goto error;
+        }
+        hostname = p;
+        continue;
+      }
+      else if(res) {
+        rc = ARES_EBADNAME;
+        goto error;
+      }
+
+    } while(0);
+
+    channel->ndomains = 0; /* default to none */
+    if (strchr(hostname, '.'))  {
+      /* a dot was found */
+
+      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;
     }
+  }
 
-  return ARES_SUCCESS;
+  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
index dc8c86e..b5add93 100644 (file)
--- a/nameser.h
+++ b/nameser.h
@@ -13,8 +13,6 @@
 
 #ifndef NETWARE
 
-#define MAXHOSTNAMELEN 256
-
 /* Structure for scatter/gather I/O.  */
 struct iovec
 {