Dominick Meglio's fix for supporting multiple names in the Nameserver key
authorDaniel Stenberg <daniel@haxx.se>
Sun, 22 Feb 2004 22:42:20 +0000 (22:42 +0000)
committerDaniel Stenberg <daniel@haxx.se>
Sun, 22 Feb 2004 22:42:20 +0000 (22:42 +0000)
on Windows.

CHANGES
ares_init.c

diff --git a/CHANGES b/CHANGES
index b22bcdb..9857dbc 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,7 @@
+* February 22, 2004
+- Dominick Meglio made ares init support multiple name servers in the
+  NameServer key on Windows.
+
 * February 16, 2004
 - Modified ares_private.h to include libcurl's memory debug header if
   CURLDEBUG is set. This makes all the ares-functions supervised properly by
index 58d510c..5277674 100644 (file)
@@ -44,7 +44,7 @@ static int init_by_defaults(ares_channel channel);
 static int config_domain(ares_channel channel, char *str);
 static int config_lookup(ares_channel channel, const char *str);
 static int config_nameserver(struct server_state **servers, int *nservers,
-                            const char *str);
+                            char *str);
 static int config_sortlist(struct apattern **sortlist, int *nsort,
                           const char *str);
 static int set_search(ares_channel channel, const char *str);
@@ -230,7 +230,7 @@ static int init_by_environment(ares_channel channel)
 #ifdef WIN32
 static int get_res_size_nt(HKEY hKey, char *subkey, int *size)
 {
-       return RegQueryValueEx(hKey, subkey, 0, NULL, NULL, size);
+  return RegQueryValueEx(hKey, subkey, 0, NULL, NULL, size);
 }
 
 /* Warning: returns a dynamically allocated buffer, the user MUST
@@ -238,55 +238,56 @@ static int get_res_size_nt(HKEY hKey, char *subkey, int *size)
  */
 static int get_res_nt(HKEY hKey, char *subkey, char **obuf)
 {
-       /* Test for the size we need */
-       int size = 0;
-       int result;
-       result = RegQueryValueEx(hKey, subkey, 0, NULL, NULL, &size);
-       if ((result != ERROR_SUCCESS && result != ERROR_MORE_DATA) || !size)
-               return 0;
-       *obuf = malloc(size+1);
-
-       if (RegQueryValueEx(hKey, subkey, 0, NULL, *obuf, &size) != ERROR_SUCCESS)
-       {
-               free(*obuf);
-               return 0;
-       }
-       if (size == 1)
-       {
-               free(*obuf);
-               return 0;
-       }
-       return 1;
+  /* Test for the size we need */
+  int size = 0;
+  int result;
+  result = RegQueryValueEx(hKey, subkey, 0, NULL, NULL, &size);
+  if ((result != ERROR_SUCCESS && result != ERROR_MORE_DATA) || !size)
+    return 0;
+  *obuf = malloc(size+1);
+
+  if (RegQueryValueEx(hKey, subkey, 0, NULL, *obuf, &size) != ERROR_SUCCESS)
+  {
+    free(*obuf);
+    return 0;
+  }
+  if (size == 1)
+  {
+    free(*obuf);
+    return 0;
+  }
+  return 1;
 }
 
 static int get_res_interfaces_nt(HKEY hKey, char *subkey, char **obuf)
 {
-       char enumbuf[39]; /* GUIDs are 38 chars + 1 for NULL */
-       int enum_size = 39;
-       int idx = 0;
-       HKEY hVal;
-       while (RegEnumKeyEx(hKey, idx++, enumbuf, &enum_size, 0, NULL, NULL, NULL) != ERROR_NO_MORE_ITEMS)
-       {
-               enum_size = 39;
-               if (RegOpenKeyEx(hKey, enumbuf, 0, KEY_QUERY_VALUE, &hVal) != ERROR_SUCCESS)
-                       continue;
-               if (!get_res_nt(hVal, subkey, obuf))
-                       RegCloseKey(hVal);
-               else
-               {
-                       RegCloseKey(hVal);
-                       return 1;
-               }
-       }
-       return 0;
+  char enumbuf[39]; /* GUIDs are 38 chars + 1 for NULL */
+  int enum_size = 39;
+  int idx = 0;
+  HKEY hVal;
+  while (RegEnumKeyEx(hKey, idx++, enumbuf, &enum_size, 0,
+                      NULL, NULL, NULL) != ERROR_NO_MORE_ITEMS)
+  {
+    enum_size = 39;
+    if (RegOpenKeyEx(hKey, enumbuf, 0, KEY_QUERY_VALUE, &hVal) !=
+        ERROR_SUCCESS)
+      continue;
+    if (!get_res_nt(hVal, subkey, obuf))
+      RegCloseKey(hVal);
+    else
+    {
+      RegCloseKey(hVal);
+      return 1;
+    }
+  }
+  return 0;
 }
 #endif
 
 static int init_by_resolv_conf(ares_channel channel)
 {
-  FILE *fp;
-  char *line = NULL, *p;
-  int linesize, status, nservers = 0, nsort = 0;
+  char *line = NULL;
+  int status, nservers = 0, nsort = 0;
   struct server_state *servers = NULL;
   struct apattern *sortlist = NULL;
 
@@ -315,8 +316,6 @@ DhcpNameServer
   DWORD data_type;
   DWORD bytes;
   DWORD result;
-  DWORD index;
-  char name[MAX_PATH];
   DWORD keysize = MAX_PATH;
 
   status = ARES_EFILE;
@@ -324,70 +323,75 @@ DhcpNameServer
   if (IsNT) 
   {
     if (RegOpenKeyEx(
-            HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0,
-            KEY_READ, &mykey
-        ) == ERROR_SUCCESS)
-    {
-               RegOpenKeyEx(mykey, "Interfaces", 0, KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS, &subkey);
-               if (get_res_nt(mykey, NAMESERVER, &line))
-               {
-                       status = config_nameserver(&servers, &nservers, line);
-                       free(line);
-               }
-               else if (get_res_nt(mykey, DHCPNAMESERVER, &line))
-               {
-                       status = config_nameserver(&servers, &nservers, line);
-                       free(line);
-               }
-               /* Try the interfaces */
-               else if (get_res_interfaces_nt(subkey, NAMESERVER, &line))
-               {
-                       status = config_nameserver(&servers, &nservers, line);
-                       free(line);
-               }
-               else if (get_res_interfaces_nt(subkey, DHCPNAMESERVER, &line))
-               {
-                       status = config_nameserver(&servers, &nservers, line);
-                       free(line);
-               }
-               RegCloseKey(subkey);
-           RegCloseKey(mykey);
-       }
-  } else {
-      if (RegOpenKeyEx(
-            HKEY_LOCAL_MACHINE, WIN_NS_9X, 0,
-            KEY_READ, &mykey
+          HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0,
+          KEY_READ, &mykey
           ) == ERROR_SUCCESS)
+    {
+      RegOpenKeyEx(mykey, "Interfaces", 0,
+                   KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS, &subkey);
+      if (get_res_nt(mykey, NAMESERVER, &line))
+      {
+        status = config_nameserver(&servers, &nservers, line);
+        free(line);
+      }
+      else if (get_res_nt(mykey, DHCPNAMESERVER, &line))
+      {
+        status = config_nameserver(&servers, &nservers, line);
+        free(line);
+      }
+      /* Try the interfaces */
+      else if (get_res_interfaces_nt(subkey, NAMESERVER, &line))
       {
-        if ((result = RegQueryValueEx(
-                        mykey, NAMESERVER, NULL, &data_type,
-                        NULL, &bytes
-                      ) 
+        status = config_nameserver(&servers, &nservers, line);
+        free(line);
+      }
+      else if (get_res_interfaces_nt(subkey, DHCPNAMESERVER, &line))
+      {
+        status = config_nameserver(&servers, &nservers, line);
+        free(line);
+      }
+      RegCloseKey(subkey);
+      RegCloseKey(mykey);
+    }
+  }
+  else
+  {
+    if (RegOpenKeyEx(
+          HKEY_LOCAL_MACHINE, WIN_NS_9X, 0,
+          KEY_READ, &mykey
+          ) == ERROR_SUCCESS)
+    {
+      if ((result = RegQueryValueEx(
+             mykey, NAMESERVER, NULL, &data_type,
+             NULL, &bytes
+             ) 
             ) == ERROR_SUCCESS ||
-            result == ERROR_MORE_DATA)
+          result == ERROR_MORE_DATA)
+      {
+        if (bytes)
         {
-            if (bytes) {
-                line = (char *)malloc(bytes+1);
-                if (RegQueryValueEx(
-                    mykey, NAMESERVER, NULL, &data_type,
-                    (unsigned char *)line, &bytes
-                    ) == ERROR_SUCCESS) {
-                    status = config_nameserver(&servers, &nservers, line);
-                }
-                free(line);
-            }
+          line = (char *)malloc(bytes+1);
+          if (RegQueryValueEx(mykey, NAMESERVER, NULL, &data_type,
+                              (unsigned char *)line, &bytes) ==
+              ERROR_SUCCESS)
+          {
+            status = config_nameserver(&servers, &nservers, line);
+          }
+          free(line);
         }
-      } 
-      RegCloseKey(mykey);
+      }
+    } 
+    RegCloseKey(mykey);
   }
   
-  if (status != ARES_EFILE) {
-      /*
+  if (status != ARES_EFILE)
+  {
+    /*
       if (!channel->lookups) {
-          status = config_lookup(channel, "file bind");
+      status = config_lookup(channel, "file bind");
       }
-      */
-      status = ARES_EOF;
+    */
+    status = ARES_EOF;
   }
 
 #elif defined(riscos)
@@ -416,36 +420,41 @@ DhcpNameServer
 
     if (status == ARES_SUCCESS)
       status = ARES_EOF;
-
+    
     free(resolvers);
   }
 
 #else
-
-  fp = fopen(PATH_RESOLV_CONF, "r");
-  if (!fp)
-    return (errno == ENOENT) ? ARES_SUCCESS : ARES_EFILE;
-  while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS)
+  {
+    char *p;
+    FILE *fp;
+    int linesize;
+   
+    fp = fopen(PATH_RESOLV_CONF, "r");
+    if (!fp)
+      return (errno == ENOENT) ? ARES_SUCCESS : ARES_EFILE;
+    while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS)
     {
       if ((p = try_config(line, "domain")) && channel->ndomains == -1)
-       status = config_domain(channel, p);
+        status = config_domain(channel, p);
       else if ((p = try_config(line, "lookup")) && !channel->lookups)
-       status = config_lookup(channel, p);
+        status = config_lookup(channel, p);
       else if ((p = try_config(line, "search")) && channel->ndomains == -1)
-       status = set_search(channel, p);
+        status = set_search(channel, p);
       else if ((p = try_config(line, "nameserver")) && channel->nservers == -1)
-       status = config_nameserver(&servers, &nservers, p);
+        status = config_nameserver(&servers, &nservers, p);
       else if ((p = try_config(line, "sortlist")) && channel->nsort == -1)
-       status = config_sortlist(&sortlist, &nsort, p);
+        status = config_sortlist(&sortlist, &nsort, p);
       else if ((p = try_config(line, "options")))
-       status = set_options(channel, p);
+        status = set_options(channel, p);
       else
-       status = ARES_SUCCESS;
+        status = ARES_SUCCESS;
       if (status != ARES_SUCCESS)
-       break;
+        break;
     }
-  free(line);
-  fclose(fp);
+    free(line);
+    fclose(fp);
+  }
 
 #endif
 
@@ -579,11 +588,52 @@ static int config_lookup(ares_channel channel, const char *str)
 }
 
 static int config_nameserver(struct server_state **servers, int *nservers,
-                            const char *str)
+                            char *str)
 {
   struct in_addr addr;
   struct server_state *newserv;
+  /* On Windows, there may be more than one nameserver specified in the same
+   * registry key, so we parse it as a space or comma seperated list.
+   */
+#ifdef WIN32
+  char *p = str;
+  char *begin = str;
+  int more = 1;
+  while (more)
+  {
+    more = 0;
+    while (*p && !isspace(*p) && *str != ',')
+      p++;
+
+    if (*p)
+    {
+      *p = 0;
+      more = 1;
+    }
+
+    /* Skip multiple spaces or trailing spaces */
+    if (!*begin)
+    {
+      begin = ++p;
+      continue;
+    }
+
+    /* This is the part that actually sets the nameserver */
+    addr.s_addr = inet_addr(begin);
+    if (addr.s_addr == INADDR_NONE)
+      continue;
+    newserv = realloc(*servers, (*nservers + 1) * sizeof(struct server_state));
+    if (!newserv)
+      return ARES_ENOMEM;
+    newserv[*nservers].addr = addr;
+    *servers = newserv;
+    (*nservers)++;
 
+    if (!more)
+      break;
+    begin = ++p;
+  }
+#else
   /* Add a nameserver entry, if this is a valid address. */
   addr.s_addr = inet_addr(str);
   if (addr.s_addr == INADDR_NONE)
@@ -594,6 +644,7 @@ static int config_nameserver(struct server_state **servers, int *nservers,
   newserv[*nservers].addr = addr;
   *servers = newserv;
   (*nservers)++;
+#endif
   return ARES_SUCCESS;
 }