aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2004-02-22 22:42:20 +0000
committerDaniel Stenberg <daniel@haxx.se>2004-02-22 22:42:20 +0000
commit32a678eab3ebe5b3e71b36d330e4f614cfecc37e (patch)
tree00a6bad63a56db2b2c56dbfb5630f83fcaf1ffd5
parentbd7ba3bde62eaf3cbe98de44fde33b76d4f039d7 (diff)
Dominick Meglio's fix for supporting multiple names in the Nameserver key
on Windows.
-rw-r--r--ares/CHANGES4
-rw-r--r--ares/ares_init.c283
2 files changed, 171 insertions, 116 deletions
diff --git a/ares/CHANGES b/ares/CHANGES
index b22bcdbd8..9857dbc8d 100644
--- a/ares/CHANGES
+++ b/ares/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
diff --git a/ares/ares_init.c b/ares/ares_init.c
index 58d510c44..527767467 100644
--- a/ares/ares_init.c
+++ b/ares/ares_init.c
@@ -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;
}