initial commit
This commit is contained in:
commit
9d20827c46
2469 changed files with 470994 additions and 0 deletions
822
iris-legacy/iris/irisnet/jdns/jdns_sys.c
Normal file
822
iris-legacy/iris/irisnet/jdns/jdns_sys.c
Normal file
|
|
@ -0,0 +1,822 @@
|
|||
/*
|
||||
* Copyright (C) 2005,2006 Justin Karneges
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
this code probes the system for dns settings. blah.
|
||||
|
||||
q3dns strategies
|
||||
----------------
|
||||
|
||||
windows:
|
||||
|
||||
domain name, name server, "search list" found in windows registry here:
|
||||
|
||||
HKEY_LOCAL_MACHINE
|
||||
System\CurrentControlSet\Services\Tcpip\Parameters <-- win nt+
|
||||
System\CurrentControlSet\Services\VxD\MSTCP <-- win 98
|
||||
|
||||
for domain, try DhcpDomain else Domain
|
||||
for name servers, try DhcpNameServer, else NameServer
|
||||
for search list, try SearchList
|
||||
|
||||
iphlpapi.dll : GetNetworkParams(PFIXED_INFO, PULONG);
|
||||
|
||||
info->DomainName
|
||||
info->DnsServerList (if not null, use it, and loop through ->Next until
|
||||
null)
|
||||
no search list
|
||||
|
||||
first try getnetworkparams. if that fails, try the nt regkey then the 98
|
||||
regkey. it seems that search list can only come from the registry, so
|
||||
maybe we need to grab that entry even if getnetworkparams works.
|
||||
|
||||
in the case of the registry, the nameserver and searchlist entries are
|
||||
delimited by spaces on win nt and commas on win 98. probably a good
|
||||
idea to simplify white space first (chop away space at start and end,
|
||||
reduce all sections of spaces to one char). also, lowercase the search
|
||||
list.
|
||||
|
||||
qt doesn't read the hosts file on windows. this might be a good idea, but
|
||||
probably not worth it.
|
||||
|
||||
unix:
|
||||
|
||||
read /etc/resolv.conf manually:
|
||||
for each line, split at spaces
|
||||
if the first item is "nameserver", then there should be an IP address
|
||||
following it. note: may contain mixed ipv4 and ipv6 addresses
|
||||
if the first item is "search", all other items are added to the domain
|
||||
list
|
||||
if the first item is "domain", then the next item should be added to the
|
||||
domain list.
|
||||
do case-insensitive matching for the item types
|
||||
for search/domain, the items are in the 8-bit system locale
|
||||
|
||||
info can also be fetched using system calls. we use the res_* stuff here.
|
||||
first we should detect for a "modern res api". this is available from
|
||||
glibc 2.3 and onward. use the following scheme to check for it:
|
||||
|
||||
#if defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2)
|
||||
&& (__GLIBC_MINOR__ >= 3)))
|
||||
// modern res api
|
||||
#endif
|
||||
|
||||
on mac we should look up res_init in the system library. see:
|
||||
qt_mac_resolve_sys(RTLD_NEXT, "res_init"); for a hint.
|
||||
otherwise we can just use res_init() straight.
|
||||
|
||||
under a modern res api, we do:
|
||||
struct __res_state res;
|
||||
res_ninit(&res);
|
||||
otherwise, we simply call res_init(). for the modern api, we use the "res"
|
||||
struct that we made. otherwise, we use the global "_res" struct.
|
||||
|
||||
read the res struct to obtain the name servers, search list, and domain.
|
||||
lowercase the search list and domain.
|
||||
|
||||
qt tries the file, and if that fails it tries the syscalls. we may want to
|
||||
do the syscalls first, or even just do both all the time.
|
||||
|
||||
read /etc/hosts manually:
|
||||
for each line
|
||||
if there is a '#' character in the line, remove it and everything to
|
||||
the right
|
||||
simplify white space
|
||||
convert to lowercase
|
||||
split the line at spaces
|
||||
first item is the ip address
|
||||
all remaining items are hostnames
|
||||
|
||||
note: these hosts could also be used for reverse-dns too
|
||||
note2: Windows has a hosts file as well (like C:\WINDOWS\hosts)
|
||||
*/
|
||||
|
||||
#include "jdns_p.h"
|
||||
|
||||
#ifdef JDNS_OS_WIN
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef JDNS_OS_UNIX
|
||||
# include <netinet/in.h>
|
||||
# include <arpa/nameser.h>
|
||||
# include <resolv.h>
|
||||
# include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#define string_indexOf jdns_string_indexOf
|
||||
#define string_split jdns_string_split
|
||||
|
||||
static int char_isspace(unsigned char c)
|
||||
{
|
||||
if(c == ' ' || c == '\t' || c == '\n' || c == '\r')
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned char *string_getnextword(unsigned char *in, int size, int pos, int *newpos)
|
||||
{
|
||||
int n;
|
||||
int at;
|
||||
int len;
|
||||
unsigned char *out;
|
||||
|
||||
at = pos;
|
||||
|
||||
// skip any space at the start
|
||||
while(at < size && char_isspace(in[at]))
|
||||
++at;
|
||||
|
||||
// all space? no word then
|
||||
if(at >= size)
|
||||
return 0;
|
||||
|
||||
// skip until a space or end
|
||||
n = at;
|
||||
while(n < size && !char_isspace(in[n]))
|
||||
++n;
|
||||
len = n - at;
|
||||
|
||||
// allocate length + zero byte
|
||||
out = (unsigned char *)jdns_alloc(len + 1);
|
||||
if(!out)
|
||||
return 0;
|
||||
memcpy(out, in + at, len);
|
||||
out[len] = 0;
|
||||
*newpos = at + len;
|
||||
return out;
|
||||
}
|
||||
|
||||
static jdns_string_t *string_simplify(const jdns_string_t *in)
|
||||
{
|
||||
int n;
|
||||
int pos;
|
||||
int total;
|
||||
unsigned char *out;
|
||||
int outlen;
|
||||
jdns_string_t *outstr;
|
||||
jdns_stringlist_t *wordlist;
|
||||
|
||||
// gather words and total of lengths
|
||||
pos = 0;
|
||||
total = 0;
|
||||
wordlist = jdns_stringlist_new();
|
||||
while(1)
|
||||
{
|
||||
jdns_string_t *word;
|
||||
unsigned char *str = string_getnextword(in->data, in->size, pos, &pos);
|
||||
if(!str)
|
||||
break;
|
||||
word = jdns_string_new();
|
||||
jdns_string_set_cstr(word, (char *)str);
|
||||
jdns_free(str);
|
||||
jdns_stringlist_append(wordlist, word);
|
||||
total += word->size;
|
||||
jdns_string_delete(word);
|
||||
}
|
||||
|
||||
if(total == 0)
|
||||
{
|
||||
jdns_stringlist_delete(wordlist);
|
||||
|
||||
outstr = jdns_string_new();
|
||||
jdns_string_set_cstr(outstr, "");
|
||||
return outstr;
|
||||
}
|
||||
|
||||
// we need to allocate space for total lengths and wordcount-1 spaces
|
||||
outlen = total + (wordlist->count - 1);
|
||||
out = (unsigned char *)jdns_alloc(outlen);
|
||||
|
||||
// lay out the words
|
||||
pos = 0;
|
||||
for(n = 0; n < wordlist->count; ++n)
|
||||
{
|
||||
unsigned char *data = wordlist->item[n]->data;
|
||||
int size = wordlist->item[n]->size;
|
||||
memcpy(out + pos, data, size);
|
||||
pos += size;
|
||||
|
||||
// if this is not the last word, append a space
|
||||
if(n + 1 < wordlist->count)
|
||||
out[pos++] = ' ';
|
||||
}
|
||||
jdns_stringlist_delete(wordlist);
|
||||
|
||||
outstr = jdns_string_new();
|
||||
jdns_string_set(outstr, out, outlen);
|
||||
jdns_free(out);
|
||||
return outstr;
|
||||
}
|
||||
|
||||
static jdns_string_t *string_tolower(const jdns_string_t *in)
|
||||
{
|
||||
int n;
|
||||
jdns_string_t *out = jdns_string_copy(in);
|
||||
for(n = 0; n < out->size; ++n)
|
||||
out->data[n] = tolower(out->data[n]);
|
||||
return out;
|
||||
}
|
||||
|
||||
static jdns_string_t *file_nextline(FILE *f)
|
||||
{
|
||||
int at, size;
|
||||
unsigned char *buf;
|
||||
jdns_string_t *str;
|
||||
|
||||
size = 1023;
|
||||
buf = (unsigned char *)jdns_alloc(size);
|
||||
at = 0;
|
||||
while(1)
|
||||
{
|
||||
unsigned char c = fgetc(f);
|
||||
if(feof(f))
|
||||
{
|
||||
jdns_free(buf);
|
||||
return 0;
|
||||
}
|
||||
if(c == '\n')
|
||||
break;
|
||||
if(c == '\r')
|
||||
continue;
|
||||
if(at < 1023)
|
||||
buf[at++] = c;
|
||||
}
|
||||
|
||||
str = jdns_string_new();
|
||||
jdns_string_set(str, buf, at);
|
||||
jdns_free(buf);
|
||||
return str;
|
||||
}
|
||||
|
||||
static jdns_dnshostlist_t *read_hosts_file(const char *path)
|
||||
{
|
||||
jdns_dnshostlist_t *out;
|
||||
FILE *f;
|
||||
jdns_string_t *line, *simp;
|
||||
jdns_stringlist_t *parts;
|
||||
jdns_address_t *addr;
|
||||
int n;
|
||||
|
||||
out = jdns_dnshostlist_new();
|
||||
|
||||
f = fopen(path, "r");
|
||||
if(!f)
|
||||
return out;
|
||||
while(1)
|
||||
{
|
||||
line = file_nextline(f);
|
||||
if(!line)
|
||||
break;
|
||||
|
||||
// truncate at comment
|
||||
n = string_indexOf(line, '#', 0);
|
||||
if(n != -1)
|
||||
{
|
||||
line->size = n;
|
||||
line->data[n] = 0;
|
||||
}
|
||||
|
||||
simp = string_simplify(line);
|
||||
jdns_string_delete(line);
|
||||
|
||||
parts = string_split(simp, ' ');
|
||||
jdns_string_delete(simp);
|
||||
|
||||
if(parts->count < 2)
|
||||
{
|
||||
jdns_stringlist_delete(parts);
|
||||
continue;
|
||||
}
|
||||
|
||||
addr = jdns_address_new();
|
||||
if(!jdns_address_set_cstr(addr, (const char *)parts->item[0]->data))
|
||||
{
|
||||
jdns_address_delete(addr);
|
||||
jdns_stringlist_delete(parts);
|
||||
continue;
|
||||
}
|
||||
|
||||
for(n = 1; n < parts->count; ++n)
|
||||
{
|
||||
jdns_dnshost_t *h = jdns_dnshost_new();
|
||||
h->name = jdns_string_copy(parts->item[n]);
|
||||
h->address = jdns_address_copy(addr);
|
||||
jdns_dnshostlist_append(out, h);
|
||||
jdns_dnshost_delete(h);
|
||||
}
|
||||
|
||||
jdns_address_delete(addr);
|
||||
jdns_stringlist_delete(parts);
|
||||
}
|
||||
fclose(f);
|
||||
return out;
|
||||
}
|
||||
|
||||
static void apply_hosts_file(jdns_dnsparams_t *a, const char *path)
|
||||
{
|
||||
int n;
|
||||
jdns_dnshostlist_t *list;
|
||||
|
||||
list = read_hosts_file(path);
|
||||
for(n = 0; n < list->count; ++n)
|
||||
jdns_dnshostlist_append(a->hosts, list->item[n]);
|
||||
jdns_dnshostlist_delete(list);
|
||||
}
|
||||
|
||||
static int dnsparams_have_domain(const jdns_dnsparams_t *a, const jdns_string_t *domain)
|
||||
{
|
||||
int n;
|
||||
for(n = 0; n < a->domains->count; ++n)
|
||||
{
|
||||
jdns_string_t *str = a->domains->item[n];
|
||||
if(strcmp((const char *)str->data, (const char *)domain->data) == 0)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef JDNS_OS_WIN
|
||||
|
||||
// from Microsoft IPTypes.h
|
||||
#ifndef IP_TYPES_INCLUDED
|
||||
#define MAX_HOSTNAME_LEN 128
|
||||
#define MAX_DOMAIN_NAME_LEN 128
|
||||
#define MAX_SCOPE_ID_LEN 256
|
||||
typedef struct {
|
||||
char String[4 * 4];
|
||||
} IP_ADDRESS_STRING, *PIP_ADDRESS_STRING, IP_MASK_STRING, *PIP_MASK_STRING;
|
||||
typedef struct _IP_ADDR_STRING {
|
||||
struct _IP_ADDR_STRING* Next;
|
||||
IP_ADDRESS_STRING IpAddress;
|
||||
IP_MASK_STRING IpMask;
|
||||
DWORD Context;
|
||||
} IP_ADDR_STRING, *PIP_ADDR_STRING;
|
||||
typedef struct {
|
||||
char HostName[MAX_HOSTNAME_LEN + 4] ;
|
||||
char DomainName[MAX_DOMAIN_NAME_LEN + 4];
|
||||
PIP_ADDR_STRING CurrentDnsServer;
|
||||
IP_ADDR_STRING DnsServerList;
|
||||
UINT NodeType;
|
||||
char ScopeId[MAX_SCOPE_ID_LEN + 4];
|
||||
UINT EnableRouting;
|
||||
UINT EnableProxy;
|
||||
UINT EnableDns;
|
||||
} FIXED_INFO, *PFIXED_INFO;
|
||||
#endif
|
||||
|
||||
typedef DWORD (WINAPI *GetNetworkParamsFunc)(PFIXED_INFO, PULONG);
|
||||
|
||||
static jdns_string_t *reg_readString(HKEY hk, const char *subkey)
|
||||
{
|
||||
char *buf;
|
||||
DWORD bufsize;
|
||||
int ret;
|
||||
jdns_string_t *str = 0;
|
||||
|
||||
bufsize = 1024;
|
||||
buf = (char *)jdns_alloc((int)bufsize);
|
||||
if(!buf)
|
||||
return 0;
|
||||
ret = RegQueryValueExA(hk, subkey, 0, 0, (LPBYTE)buf, &bufsize);
|
||||
if(ret == ERROR_MORE_DATA)
|
||||
{
|
||||
buf = (char *)jdns_realloc(buf, bufsize);
|
||||
if(!buf)
|
||||
{
|
||||
jdns_free(buf);
|
||||
return 0;
|
||||
}
|
||||
ret = RegQueryValueExA(hk, subkey, 0, 0, (LPBYTE)buf, &bufsize);
|
||||
}
|
||||
if(ret == ERROR_SUCCESS)
|
||||
{
|
||||
str = jdns_string_new();
|
||||
jdns_string_set_cstr(str, (char *)buf);
|
||||
}
|
||||
jdns_free(buf);
|
||||
return str;
|
||||
}
|
||||
|
||||
static jdns_dnsparams_t *dnsparams_get_winreg()
|
||||
{
|
||||
int n;
|
||||
jdns_dnsparams_t *params;
|
||||
HKEY key;
|
||||
int ret;
|
||||
char sep;
|
||||
jdns_string_t *str_domain, *str_nameserver, *str_searchlist;
|
||||
jdns_stringlist_t *list_nameserver, *list_searchlist;
|
||||
|
||||
sep = ' ';
|
||||
ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
|
||||
"System\\CurrentControlSet\\Services\\Tcpip\\Parameters",
|
||||
0, KEY_READ, &key);
|
||||
if(ret != ERROR_SUCCESS)
|
||||
{
|
||||
sep = ',';
|
||||
ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
|
||||
"System\\CurrentControlSet\\Services\\VxD\\MSTCP",
|
||||
0, KEY_READ, &key);
|
||||
if(ret != ERROR_SUCCESS)
|
||||
return 0;
|
||||
}
|
||||
|
||||
str_domain = reg_readString(key, "DhcpDomain");
|
||||
if(!str_domain)
|
||||
str_domain = reg_readString(key, "Domain");
|
||||
str_nameserver = reg_readString(key, "DhcpNameServer");
|
||||
if(!str_nameserver)
|
||||
str_nameserver = reg_readString(key, "NameServer");
|
||||
str_searchlist = reg_readString(key, "SearchList");
|
||||
|
||||
RegCloseKey(key);
|
||||
|
||||
list_nameserver = 0;
|
||||
if(str_nameserver)
|
||||
{
|
||||
list_nameserver = string_split(str_nameserver, sep);
|
||||
jdns_string_delete(str_nameserver);
|
||||
}
|
||||
list_searchlist = 0;
|
||||
if(str_searchlist)
|
||||
{
|
||||
// lowercase the string
|
||||
jdns_string_t *p = string_tolower(str_searchlist);
|
||||
jdns_string_delete(str_searchlist);
|
||||
str_searchlist = p;
|
||||
|
||||
list_searchlist = string_split(str_searchlist, sep);
|
||||
jdns_string_delete(str_searchlist);
|
||||
}
|
||||
|
||||
params = jdns_dnsparams_new();
|
||||
if(list_nameserver)
|
||||
{
|
||||
// qt seems to do a strange thing here by running each name
|
||||
// server address through the q3dns setLabel function, and
|
||||
// then pulls the result as a list of addresses. i have
|
||||
// no idea why they do this, or how one IP address would
|
||||
// turn into anything else, let alone several addresses.
|
||||
// so, uh, we're not going to do that.
|
||||
for(n = 0; n < list_nameserver->count; ++n)
|
||||
{
|
||||
jdns_address_t *addr = jdns_address_new();
|
||||
if(jdns_address_set_cstr(addr, (char *)list_nameserver->item[n]->data))
|
||||
jdns_dnsparams_append_nameserver(params, addr, JDNS_UNICAST_PORT);
|
||||
jdns_address_delete(addr);
|
||||
}
|
||||
jdns_stringlist_delete(list_nameserver);
|
||||
}
|
||||
if(str_domain)
|
||||
{
|
||||
if(str_domain->size > 0)
|
||||
jdns_dnsparams_append_domain(params, str_domain);
|
||||
jdns_string_delete(str_domain);
|
||||
}
|
||||
if(list_searchlist)
|
||||
{
|
||||
for(n = 0; n < list_searchlist->count; ++n)
|
||||
{
|
||||
if(list_searchlist->item[n]->size > 0)
|
||||
jdns_dnsparams_append_domain(params, list_searchlist->item[n]);
|
||||
}
|
||||
jdns_stringlist_delete(list_searchlist);
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
static jdns_dnsparams_t *dnsparams_get_winsys()
|
||||
{
|
||||
jdns_dnsparams_t *params;
|
||||
GetNetworkParamsFunc myGetNetworkParams;
|
||||
DWORD ret;
|
||||
HINSTANCE lib;
|
||||
jdns_address_t *addr;
|
||||
jdns_string_t *str;
|
||||
IP_ADDR_STRING *ipstr;
|
||||
|
||||
lib = LoadLibraryA("iphlpapi");
|
||||
if(!lib)
|
||||
return 0;
|
||||
|
||||
params = 0;
|
||||
myGetNetworkParams = (GetNetworkParamsFunc)GetProcAddress(lib, "GetNetworkParams");
|
||||
if(myGetNetworkParams)
|
||||
{
|
||||
ULONG bufsize = 0;
|
||||
ret = myGetNetworkParams(0, &bufsize);
|
||||
if(ret == ERROR_BUFFER_OVERFLOW)
|
||||
{
|
||||
FIXED_INFO *info = (FIXED_INFO *)jdns_alloc((int)bufsize);
|
||||
ret = myGetNetworkParams(info, &bufsize);
|
||||
if(ret == ERROR_SUCCESS)
|
||||
{
|
||||
params = jdns_dnsparams_new();
|
||||
ipstr = &info->DnsServerList;
|
||||
while(ipstr)
|
||||
{
|
||||
addr = jdns_address_new();
|
||||
if(jdns_address_set_cstr(addr, (char *)ipstr->IpAddress.String))
|
||||
jdns_dnsparams_append_nameserver(params, addr, JDNS_UNICAST_PORT);
|
||||
jdns_address_delete(addr);
|
||||
ipstr = ipstr->Next;
|
||||
}
|
||||
str = jdns_string_new();
|
||||
jdns_string_set_cstr(str, info->DomainName);
|
||||
if(str->size > 0)
|
||||
jdns_dnsparams_append_domain(params, str);
|
||||
jdns_string_delete(str);
|
||||
}
|
||||
jdns_free(info);
|
||||
}
|
||||
}
|
||||
FreeLibrary(lib);
|
||||
return params;
|
||||
}
|
||||
|
||||
static void apply_win_hosts_file(jdns_dnsparams_t *a)
|
||||
{
|
||||
char *p, *str;
|
||||
int len;
|
||||
|
||||
p = getenv("WINDIR");
|
||||
if(!p)
|
||||
return;
|
||||
len = strlen(p);
|
||||
str = (char *)jdns_alloc(len + 100); // should be enough
|
||||
memcpy(str, p, len);
|
||||
strcpy(str + len, "\\system32\\drivers\\etc\\hosts"); // winnt+
|
||||
apply_hosts_file(a, str);
|
||||
strcpy(str + len, "\\hosts"); // win9x
|
||||
apply_hosts_file(a, str);
|
||||
jdns_free(str);
|
||||
}
|
||||
|
||||
static jdns_dnsparams_t *dnsparams_get_win()
|
||||
{
|
||||
int n;
|
||||
jdns_dnsparams_t *sys_params, *reg_params;
|
||||
|
||||
reg_params = dnsparams_get_winreg();
|
||||
sys_params = dnsparams_get_winsys();
|
||||
|
||||
// no sys params? take the reg params then
|
||||
if(!sys_params)
|
||||
{
|
||||
apply_win_hosts_file(reg_params);
|
||||
return reg_params;
|
||||
}
|
||||
|
||||
// sys params don't have a search list, so merge the domains from
|
||||
// the registry if possible
|
||||
if(reg_params)
|
||||
{
|
||||
for(n = 0; n < reg_params->domains->count; ++n)
|
||||
{
|
||||
jdns_string_t *reg_str = reg_params->domains->item[n];
|
||||
|
||||
// don't add dups
|
||||
if(!dnsparams_have_domain(sys_params, reg_str))
|
||||
jdns_dnsparams_append_domain(sys_params, reg_str);
|
||||
}
|
||||
jdns_dnsparams_delete(reg_params);
|
||||
}
|
||||
apply_win_hosts_file(sys_params);
|
||||
return sys_params;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef JDNS_OS_UNIX
|
||||
|
||||
static jdns_dnsparams_t *dnsparams_get_unixfiles()
|
||||
{
|
||||
FILE *f;
|
||||
int n;
|
||||
jdns_dnsparams_t *params;
|
||||
jdns_string_t *line, *simp;
|
||||
jdns_stringlist_t *parts;
|
||||
|
||||
params = jdns_dnsparams_new();
|
||||
|
||||
f = fopen("/etc/resolv.conf", "r");
|
||||
if(!f)
|
||||
return params;
|
||||
while(1)
|
||||
{
|
||||
line = file_nextline(f);
|
||||
if(!line)
|
||||
break;
|
||||
|
||||
// truncate at comment
|
||||
n = string_indexOf(line, '#', 0);
|
||||
if(n != -1)
|
||||
{
|
||||
line->size = n;
|
||||
line->data[n] = 0;
|
||||
}
|
||||
|
||||
simp = string_simplify(line);
|
||||
jdns_string_delete(line);
|
||||
|
||||
parts = string_split(simp, ' ');
|
||||
jdns_string_delete(simp);
|
||||
|
||||
if(parts->count < 2)
|
||||
{
|
||||
jdns_stringlist_delete(parts);
|
||||
continue;
|
||||
}
|
||||
|
||||
simp = string_tolower(parts->item[0]);
|
||||
if(strcmp((char *)simp->data, "nameserver") == 0)
|
||||
{
|
||||
jdns_address_t *addr = jdns_address_new();
|
||||
jdns_address_set_cstr(addr, (const char *)parts->item[1]->data);
|
||||
jdns_dnsparams_append_nameserver(params, addr, JDNS_UNICAST_PORT);
|
||||
jdns_address_delete(addr);
|
||||
}
|
||||
else if(strcmp((char *)simp->data, "search") == 0)
|
||||
{
|
||||
for(n = 1; n < parts->count; ++n)
|
||||
{
|
||||
jdns_dnsparams_append_domain(params, parts->item[n]);
|
||||
}
|
||||
}
|
||||
else if(strcmp((char *)simp->data, "domain") == 0)
|
||||
{
|
||||
jdns_dnsparams_append_domain(params, parts->item[1]);
|
||||
}
|
||||
jdns_string_delete(simp);
|
||||
|
||||
jdns_stringlist_delete(parts);
|
||||
}
|
||||
fclose(f);
|
||||
return params;
|
||||
}
|
||||
|
||||
#if defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 3)))
|
||||
# define JDNS_MODERN_RES_API
|
||||
#endif
|
||||
|
||||
#ifndef JDNS_MODERN_RES_API
|
||||
typedef int (*res_init_func)();
|
||||
static int my_res_init()
|
||||
{
|
||||
#ifdef JDNS_OS_MAC
|
||||
res_init_func mac_res_init;
|
||||
|
||||
// look up res_init in the system library (qt does this, not sure why)
|
||||
mac_res_init = (res_init_func)dlsym(RTLD_NEXT, "res_init");
|
||||
if(!mac_res_init)
|
||||
return -1;
|
||||
return mac_res_init();
|
||||
#else
|
||||
return res_init();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __res_state_ext
|
||||
# define USE_EXTEXT
|
||||
#endif
|
||||
|
||||
static jdns_dnsparams_t *dnsparams_get_unixsys()
|
||||
{
|
||||
int n;
|
||||
jdns_dnsparams_t *params;
|
||||
|
||||
#ifdef JDNS_MODERN_RES_API
|
||||
struct __res_state res;
|
||||
memset(&res, 0, sizeof(struct __res_state));
|
||||
n = res_ninit(&res);
|
||||
#define RESVAR res
|
||||
#else
|
||||
n = my_res_init();
|
||||
#define RESVAR _res
|
||||
#endif
|
||||
|
||||
params = jdns_dnsparams_new();
|
||||
|
||||
// error initializing?
|
||||
if(n == -1)
|
||||
return params;
|
||||
|
||||
// nameservers - ipv6
|
||||
for(n = 0; n < MAXNS && n < RESVAR._u._ext.nscount; ++n)
|
||||
{
|
||||
jdns_address_t *addr;
|
||||
struct sockaddr_in6 *sa6;
|
||||
|
||||
#ifdef USE_EXTEXT
|
||||
sa6 = ((struct sockaddr_in6 *)RESVAR._u._ext.ext) + n;
|
||||
#else
|
||||
sa6 = RESVAR._u._ext.nsaddrs[n];
|
||||
#endif
|
||||
|
||||
if(sa6 == NULL)
|
||||
continue;
|
||||
addr = jdns_address_new();
|
||||
jdns_address_set_ipv6(addr, sa6->sin6_addr.s6_addr);
|
||||
jdns_dnsparams_append_nameserver(params, addr, JDNS_UNICAST_PORT);
|
||||
jdns_address_delete(addr);
|
||||
}
|
||||
|
||||
// nameservers - ipv4
|
||||
for(n = 0; n < MAXNS && n < RESVAR.nscount; ++n)
|
||||
{
|
||||
jdns_address_t *addr = jdns_address_new();
|
||||
jdns_address_set_ipv4(addr, ntohl(RESVAR.nsaddr_list[n].sin_addr.s_addr));
|
||||
jdns_dnsparams_append_nameserver(params, addr, JDNS_UNICAST_PORT);
|
||||
jdns_address_delete(addr);
|
||||
}
|
||||
|
||||
// domain name
|
||||
if(strlen(RESVAR.defdname) > 0)
|
||||
{
|
||||
jdns_string_t *str;
|
||||
jdns_string_t *p;
|
||||
str = jdns_string_new();
|
||||
jdns_string_set_cstr(str, RESVAR.defdname);
|
||||
p = string_tolower(str);
|
||||
jdns_string_delete(str);
|
||||
str = p;
|
||||
jdns_dnsparams_append_domain(params, str);
|
||||
jdns_string_delete(str);
|
||||
}
|
||||
|
||||
// search list
|
||||
#ifdef MAXDFLSRCH
|
||||
for(n = 0; n < MAXDFLSRCH && RESVAR.dnsrch[n]; ++n)
|
||||
{
|
||||
if(strlen(RESVAR.dnsrch[n]) > 0)
|
||||
{
|
||||
jdns_string_t *str;
|
||||
jdns_string_t *p;
|
||||
str = jdns_string_new();
|
||||
jdns_string_set_cstr(str, RESVAR.dnsrch[n]);
|
||||
p = string_tolower(str);
|
||||
jdns_string_delete(str);
|
||||
str = p;
|
||||
|
||||
// don't add dups
|
||||
if(!dnsparams_have_domain(params, str))
|
||||
jdns_dnsparams_append_domain(params, str);
|
||||
|
||||
jdns_string_delete(str);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
static jdns_dnsparams_t *dnsparams_get_unix()
|
||||
{
|
||||
jdns_dnsparams_t *params;
|
||||
|
||||
// prefer system calls over files
|
||||
params = dnsparams_get_unixsys();
|
||||
if(params->nameservers->count == 0)
|
||||
{
|
||||
jdns_dnsparams_delete(params);
|
||||
params = dnsparams_get_unixfiles();
|
||||
}
|
||||
|
||||
apply_hosts_file(params, "/etc/hosts");
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
jdns_dnsparams_t *jdns_system_dnsparams()
|
||||
{
|
||||
#ifdef JDNS_OS_WIN
|
||||
return dnsparams_get_win();
|
||||
#else
|
||||
return dnsparams_get_unix();
|
||||
#endif
|
||||
}
|
||||
Reference in a new issue