Dominick Meglio's fix for supporting multiple names in the Nameserver key

on Windows.
This commit is contained in:
Daniel Stenberg
2004-02-22 22:42:20 +00:00
parent 3e2959f67c
commit bcc693e966
2 changed files with 172 additions and 117 deletions
+4
View File
@@ -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 * February 16, 2004
- Modified ares_private.h to include libcurl's memory debug header if - Modified ares_private.h to include libcurl's memory debug header if
CURLDEBUG is set. This makes all the ares-functions supervised properly by CURLDEBUG is set. This makes all the ares-functions supervised properly by
+168 -117
View 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_domain(ares_channel channel, char *str);
static int config_lookup(ares_channel channel, const char *str); static int config_lookup(ares_channel channel, const char *str);
static int config_nameserver(struct server_state **servers, int *nservers, static int config_nameserver(struct server_state **servers, int *nservers,
const char *str); char *str);
static int config_sortlist(struct apattern **sortlist, int *nsort, static int config_sortlist(struct apattern **sortlist, int *nsort,
const char *str); const char *str);
static int set_search(ares_channel channel, 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 #ifdef WIN32
static int get_res_size_nt(HKEY hKey, char *subkey, int *size) 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 /* 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) static int get_res_nt(HKEY hKey, char *subkey, char **obuf)
{ {
/* Test for the size we need */ /* Test for the size we need */
int size = 0; int size = 0;
int result; int result;
result = RegQueryValueEx(hKey, subkey, 0, NULL, NULL, &size); result = RegQueryValueEx(hKey, subkey, 0, NULL, NULL, &size);
if ((result != ERROR_SUCCESS && result != ERROR_MORE_DATA) || !size) if ((result != ERROR_SUCCESS && result != ERROR_MORE_DATA) || !size)
return 0; return 0;
*obuf = malloc(size+1); *obuf = malloc(size+1);
if (RegQueryValueEx(hKey, subkey, 0, NULL, *obuf, &size) != ERROR_SUCCESS) if (RegQueryValueEx(hKey, subkey, 0, NULL, *obuf, &size) != ERROR_SUCCESS)
{ {
free(*obuf); free(*obuf);
return 0; return 0;
} }
if (size == 1) if (size == 1)
{ {
free(*obuf); free(*obuf);
return 0; return 0;
} }
return 1; return 1;
} }
static int get_res_interfaces_nt(HKEY hKey, char *subkey, char **obuf) static int get_res_interfaces_nt(HKEY hKey, char *subkey, char **obuf)
{ {
char enumbuf[39]; /* GUIDs are 38 chars + 1 for NULL */ char enumbuf[39]; /* GUIDs are 38 chars + 1 for NULL */
int enum_size = 39; int enum_size = 39;
int idx = 0; int idx = 0;
HKEY hVal; HKEY hVal;
while (RegEnumKeyEx(hKey, idx++, enumbuf, &enum_size, 0, NULL, NULL, NULL) != ERROR_NO_MORE_ITEMS) 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) enum_size = 39;
continue; if (RegOpenKeyEx(hKey, enumbuf, 0, KEY_QUERY_VALUE, &hVal) !=
if (!get_res_nt(hVal, subkey, obuf)) ERROR_SUCCESS)
RegCloseKey(hVal); continue;
else if (!get_res_nt(hVal, subkey, obuf))
{ RegCloseKey(hVal);
RegCloseKey(hVal); else
return 1; {
} RegCloseKey(hVal);
} return 1;
return 0; }
}
return 0;
} }
#endif #endif
static int init_by_resolv_conf(ares_channel channel) static int init_by_resolv_conf(ares_channel channel)
{ {
FILE *fp; char *line = NULL;
char *line = NULL, *p; int status, nservers = 0, nsort = 0;
int linesize, status, nservers = 0, nsort = 0;
struct server_state *servers = NULL; struct server_state *servers = NULL;
struct apattern *sortlist = NULL; struct apattern *sortlist = NULL;
@@ -315,8 +316,6 @@ DhcpNameServer
DWORD data_type; DWORD data_type;
DWORD bytes; DWORD bytes;
DWORD result; DWORD result;
DWORD index;
char name[MAX_PATH];
DWORD keysize = MAX_PATH; DWORD keysize = MAX_PATH;
status = ARES_EFILE; status = ARES_EFILE;
@@ -324,70 +323,75 @@ DhcpNameServer
if (IsNT) if (IsNT)
{ {
if (RegOpenKeyEx( if (RegOpenKeyEx(
HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0, HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0,
KEY_READ, &mykey 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
) == ERROR_SUCCESS) ) == ERROR_SUCCESS)
{
RegOpenKeyEx(mykey, "Interfaces", 0,
KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS, &subkey);
if (get_res_nt(mykey, NAMESERVER, &line))
{ {
if ((result = RegQueryValueEx( status = config_nameserver(&servers, &nservers, line);
mykey, NAMESERVER, NULL, &data_type, free(line);
NULL, &bytes }
) else if (get_res_nt(mykey, DHCPNAMESERVER, &line))
) == ERROR_SUCCESS || {
result == ERROR_MORE_DATA) status = config_nameserver(&servers, &nservers, line);
{ free(line);
if (bytes) { }
line = (char *)malloc(bytes+1); /* Try the interfaces */
if (RegQueryValueEx( else if (get_res_interfaces_nt(subkey, NAMESERVER, &line))
mykey, NAMESERVER, NULL, &data_type, {
(unsigned char *)line, &bytes status = config_nameserver(&servers, &nservers, line);
) == ERROR_SUCCESS) { free(line);
status = config_nameserver(&servers, &nservers, line); }
} else if (get_res_interfaces_nt(subkey, DHCPNAMESERVER, &line))
free(line); {
} status = config_nameserver(&servers, &nservers, line);
} free(line);
} }
RegCloseKey(subkey);
RegCloseKey(mykey); 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)
{
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);
}
}
}
RegCloseKey(mykey);
} }
if (status != ARES_EFILE) { if (status != ARES_EFILE)
/* {
/*
if (!channel->lookups) { if (!channel->lookups) {
status = config_lookup(channel, "file bind"); status = config_lookup(channel, "file bind");
} }
*/ */
status = ARES_EOF; status = ARES_EOF;
} }
#elif defined(riscos) #elif defined(riscos)
@@ -416,36 +420,41 @@ DhcpNameServer
if (status == ARES_SUCCESS) if (status == ARES_SUCCESS)
status = ARES_EOF; status = ARES_EOF;
free(resolvers); free(resolvers);
} }
#else #else
{
fp = fopen(PATH_RESOLV_CONF, "r"); char *p;
if (!fp) FILE *fp;
return (errno == ENOENT) ? ARES_SUCCESS : ARES_EFILE; int linesize;
while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS)
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) 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) 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) 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) 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) 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"))) else if ((p = try_config(line, "options")))
status = set_options(channel, p); status = set_options(channel, p);
else else
status = ARES_SUCCESS; status = ARES_SUCCESS;
if (status != ARES_SUCCESS) if (status != ARES_SUCCESS)
break; break;
} }
free(line); free(line);
fclose(fp); fclose(fp);
}
#endif #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, static int config_nameserver(struct server_state **servers, int *nservers,
const char *str) char *str)
{ {
struct in_addr addr; struct in_addr addr;
struct server_state *newserv; 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. */ /* Add a nameserver entry, if this is a valid address. */
addr.s_addr = inet_addr(str); addr.s_addr = inet_addr(str);
if (addr.s_addr == INADDR_NONE) if (addr.s_addr == INADDR_NONE)
@@ -594,6 +644,7 @@ static int config_nameserver(struct server_state **servers, int *nservers,
newserv[*nservers].addr = addr; newserv[*nservers].addr = addr;
*servers = newserv; *servers = newserv;
(*nservers)++; (*nservers)++;
#endif
return ARES_SUCCESS; return ARES_SUCCESS;
} }