File indexing completed on 2024-05-26 04:08:59
0001 /* 0002 * Copyright (C) 2005-2008 Justin Karneges 0003 * 0004 * Permission is hereby granted, free of charge, to any person obtaining a 0005 * copy of this software and associated documentation files (the 0006 * "Software"), to deal in the Software without restriction, including 0007 * without limitation the rights to use, copy, modify, merge, publish, 0008 * distribute, sublicense, and/or sell copies of the Software, and to 0009 * permit persons to whom the Software is furnished to do so, subject to 0010 * the following conditions: 0011 * 0012 * The above copyright notice and this permission notice shall be included 0013 * in all copies or substantial portions of the Software. 0014 * 0015 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 0016 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 0017 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 0018 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 0019 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 0020 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 0021 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 0022 */ 0023 0024 /* 0025 this code probes the system for dns settings. blah. 0026 0027 q3dns strategies 0028 ---------------- 0029 0030 windows: 0031 0032 domain name, name server, "search list" found in windows registry here: 0033 0034 HKEY_LOCAL_MACHINE 0035 System\CurrentControlSet\Services\Tcpip\Parameters <-- win nt+ 0036 System\CurrentControlSet\Services\VxD\MSTCP <-- win 98 0037 0038 for domain, try DhcpDomain else Domain 0039 for name servers, try DhcpNameServer, else NameServer 0040 for search list, try SearchList 0041 0042 iphlpapi.dll : GetNetworkParams(PFIXED_INFO, PULONG); 0043 0044 info->DomainName 0045 info->DnsServerList (if not null, use it, and loop through ->Next until 0046 null) 0047 no search list 0048 0049 first try getnetworkparams. if that fails, try the nt regkey then the 98 0050 regkey. it seems that search list can only come from the registry, so 0051 maybe we need to grab that entry even if getnetworkparams works. 0052 0053 in the case of the registry, the nameserver and searchlist entries are 0054 delimited by spaces on win nt and commas on win 98. probably a good 0055 idea to simplify white space first (chop away space at start and end, 0056 reduce all sections of spaces to one char). also, lowercase the search 0057 list. 0058 0059 qt doesn't read the hosts file on windows. this might be a good idea, but 0060 probably not worth it. 0061 0062 unix: 0063 0064 read /etc/resolv.conf manually: 0065 for each line, split at spaces 0066 if the first item is "nameserver", then there should be an IP address 0067 following it. note: may contain mixed ipv4 and ipv6 addresses 0068 if the first item is "search", all other items are added to the domain 0069 list 0070 if the first item is "domain", then the next item should be added to the 0071 domain list. 0072 do case-insensitive matching for the item types 0073 for search/domain, the items are in the 8-bit system locale 0074 0075 info can also be fetched using system calls. we use the res_* stuff here. 0076 first we should detect for a "modern res api". this is available from 0077 glibc 2.3 and onward. use the following scheme to check for it: 0078 0079 #if defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) 0080 && (__GLIBC_MINOR__ >= 3))) 0081 // modern res api 0082 #endif 0083 0084 on mac we should look up res_init in the system library. see: 0085 qt_mac_resolve_sys(RTLD_NEXT, "res_init"); for a hint. 0086 otherwise we can just use res_init() straight. 0087 0088 under a modern res api, we do: 0089 struct __res_state res; 0090 res_ninit(&res); 0091 otherwise, we simply call res_init(). for the modern api, we use the "res" 0092 struct that we made. otherwise, we use the global "_res" struct. 0093 0094 read the res struct to obtain the name servers, search list, and domain. 0095 lowercase the search list and domain. 0096 0097 qt tries the file, and if that fails it tries the syscalls. we may want to 0098 do the syscalls first, or even just do both all the time. 0099 0100 read /etc/hosts manually: 0101 for each line 0102 if there is a '#' character in the line, remove it and everything to 0103 the right 0104 simplify white space 0105 convert to lowercase 0106 split the line at spaces 0107 first item is the ip address 0108 all remaining items are hostnames 0109 0110 note: these hosts could also be used for reverse-dns too 0111 note2: Windows has a hosts file as well (like C:\WINDOWS\hosts) 0112 */ 0113 0114 #include "jdns_p.h" 0115 0116 #ifdef JDNS_OS_WIN 0117 # include <windows.h> 0118 #endif 0119 0120 #ifdef JDNS_OS_UNIX 0121 # include <netinet/in.h> 0122 # include <arpa/nameser.h> 0123 # include <resolv.h> 0124 # include <dlfcn.h> 0125 #endif 0126 0127 #define string_indexOf jdns_string_indexOf 0128 #define string_split jdns_string_split 0129 0130 static int char_isspace(unsigned char c) 0131 { 0132 if(c == ' ' || c == '\t' || c == '\n' || c == '\r') 0133 return 1; 0134 return 0; 0135 } 0136 0137 static unsigned char *string_getnextword(unsigned char *in, int size, int pos, int *newpos) 0138 { 0139 int n; 0140 int at; 0141 int len; 0142 unsigned char *out; 0143 0144 at = pos; 0145 0146 /* skip any space at the start */ 0147 while(at < size && char_isspace(in[at])) 0148 ++at; 0149 0150 /* all space? no word then */ 0151 if(at >= size) 0152 return 0; 0153 0154 /* skip until a space or end */ 0155 n = at; 0156 while(n < size && !char_isspace(in[n])) 0157 ++n; 0158 len = n - at; 0159 0160 /* allocate length + zero byte */ 0161 out = (unsigned char *)jdns_alloc(len + 1); 0162 if(!out) 0163 return 0; 0164 memcpy(out, in + at, len); 0165 out[len] = 0; 0166 *newpos = at + len; 0167 return out; 0168 } 0169 0170 static jdns_string_t *string_simplify(const jdns_string_t *in) 0171 { 0172 int n; 0173 int pos; 0174 int total; 0175 unsigned char *out; 0176 int outlen; 0177 jdns_string_t *outstr; 0178 jdns_stringlist_t *wordlist; 0179 0180 /* gather words and total of lengths */ 0181 pos = 0; 0182 total = 0; 0183 wordlist = jdns_stringlist_new(); 0184 while(1) 0185 { 0186 jdns_string_t *word; 0187 unsigned char *str = string_getnextword(in->data, in->size, pos, &pos); 0188 if(!str) 0189 break; 0190 word = jdns_string_new(); 0191 jdns_string_set_cstr(word, (char *)str); 0192 jdns_free(str); 0193 jdns_stringlist_append(wordlist, word); 0194 total += word->size; 0195 jdns_string_delete(word); 0196 } 0197 0198 if(total == 0) 0199 { 0200 jdns_stringlist_delete(wordlist); 0201 0202 outstr = jdns_string_new(); 0203 jdns_string_set_cstr(outstr, ""); 0204 return outstr; 0205 } 0206 0207 /* we need to allocate space for total lengths and wordcount-1 spaces */ 0208 outlen = total + (wordlist->count - 1); 0209 out = (unsigned char *)jdns_alloc(outlen); 0210 0211 /* lay out the words */ 0212 pos = 0; 0213 for(n = 0; n < wordlist->count; ++n) 0214 { 0215 unsigned char *data = wordlist->item[n]->data; 0216 int size = wordlist->item[n]->size; 0217 memcpy(out + pos, data, size); 0218 pos += size; 0219 0220 /* if this is not the last word, append a space */ 0221 if(n + 1 < wordlist->count) 0222 out[pos++] = ' '; 0223 } 0224 jdns_stringlist_delete(wordlist); 0225 0226 outstr = jdns_string_new(); 0227 jdns_string_set(outstr, out, outlen); 0228 jdns_free(out); 0229 return outstr; 0230 } 0231 0232 static jdns_string_t *string_tolower(const jdns_string_t *in) 0233 { 0234 int n; 0235 jdns_string_t *out = jdns_string_copy(in); 0236 for(n = 0; n < out->size; ++n) 0237 out->data[n] = tolower(out->data[n]); 0238 return out; 0239 } 0240 0241 static jdns_string_t *file_nextline(FILE *f) 0242 { 0243 int at, size; 0244 unsigned char *buf; 0245 jdns_string_t *str; 0246 0247 size = 1023; 0248 buf = (unsigned char *)jdns_alloc(size); 0249 at = 0; 0250 while(1) 0251 { 0252 unsigned char c = fgetc(f); 0253 if(feof(f)) 0254 { 0255 jdns_free(buf); 0256 return 0; 0257 } 0258 if(c == '\n') 0259 break; 0260 if(c == '\r') 0261 continue; 0262 if(at < 1023) 0263 buf[at++] = c; 0264 } 0265 0266 str = jdns_string_new(); 0267 jdns_string_set(str, buf, at); 0268 jdns_free(buf); 0269 return str; 0270 } 0271 0272 static jdns_dnshostlist_t *read_hosts_file(const char *path) 0273 { 0274 jdns_dnshostlist_t *out; 0275 FILE *f; 0276 jdns_string_t *line, *simp; 0277 jdns_stringlist_t *parts; 0278 jdns_address_t *addr; 0279 int n; 0280 0281 out = jdns_dnshostlist_new(); 0282 0283 f = jdns_fopen(path, "r"); 0284 if(!f) 0285 return out; 0286 while(1) 0287 { 0288 line = file_nextline(f); 0289 if(!line) 0290 break; 0291 0292 /* truncate at comment */ 0293 n = string_indexOf(line, '#', 0); 0294 if(n != -1) 0295 { 0296 line->size = n; 0297 line->data[n] = 0; 0298 } 0299 0300 simp = string_simplify(line); 0301 jdns_string_delete(line); 0302 0303 parts = string_split(simp, ' '); 0304 jdns_string_delete(simp); 0305 0306 if(parts->count < 2) 0307 { 0308 jdns_stringlist_delete(parts); 0309 continue; 0310 } 0311 0312 addr = jdns_address_new(); 0313 if(!jdns_address_set_cstr(addr, (const char *)parts->item[0]->data)) 0314 { 0315 jdns_address_delete(addr); 0316 jdns_stringlist_delete(parts); 0317 continue; 0318 } 0319 0320 for(n = 1; n < parts->count; ++n) 0321 { 0322 jdns_dnshost_t *h = jdns_dnshost_new(); 0323 h->name = jdns_string_copy(parts->item[n]); 0324 h->address = jdns_address_copy(addr); 0325 jdns_dnshostlist_append(out, h); 0326 jdns_dnshost_delete(h); 0327 } 0328 0329 jdns_address_delete(addr); 0330 jdns_stringlist_delete(parts); 0331 } 0332 fclose(f); 0333 return out; 0334 } 0335 0336 static void apply_hosts_file(jdns_dnsparams_t *a, const char *path) 0337 { 0338 int n; 0339 jdns_dnshostlist_t *list; 0340 0341 list = read_hosts_file(path); 0342 for(n = 0; n < list->count; ++n) 0343 jdns_dnshostlist_append(a->hosts, list->item[n]); 0344 jdns_dnshostlist_delete(list); 0345 } 0346 0347 static int dnsparams_have_domain(const jdns_dnsparams_t *a, const jdns_string_t *domain) 0348 { 0349 int n; 0350 for(n = 0; n < a->domains->count; ++n) 0351 { 0352 jdns_string_t *str = a->domains->item[n]; 0353 if(strcmp((const char *)str->data, (const char *)domain->data) == 0) 0354 return 1; 0355 } 0356 return 0; 0357 } 0358 0359 #ifdef JDNS_OS_WIN 0360 0361 /* from Microsoft IPTypes.h */ 0362 #ifndef IP_TYPES_INCLUDED 0363 #define MAX_HOSTNAME_LEN 128 0364 #define MAX_DOMAIN_NAME_LEN 128 0365 #define MAX_SCOPE_ID_LEN 256 0366 typedef struct { 0367 char String[4 * 4]; 0368 } IP_ADDRESS_STRING, *PIP_ADDRESS_STRING, IP_MASK_STRING, *PIP_MASK_STRING; 0369 typedef struct _IP_ADDR_STRING { 0370 struct _IP_ADDR_STRING* Next; 0371 IP_ADDRESS_STRING IpAddress; 0372 IP_MASK_STRING IpMask; 0373 DWORD Context; 0374 } IP_ADDR_STRING, *PIP_ADDR_STRING; 0375 typedef struct { 0376 char HostName[MAX_HOSTNAME_LEN + 4] ; 0377 char DomainName[MAX_DOMAIN_NAME_LEN + 4]; 0378 PIP_ADDR_STRING CurrentDnsServer; 0379 IP_ADDR_STRING DnsServerList; 0380 UINT NodeType; 0381 char ScopeId[MAX_SCOPE_ID_LEN + 4]; 0382 UINT EnableRouting; 0383 UINT EnableProxy; 0384 UINT EnableDns; 0385 } FIXED_INFO, *PFIXED_INFO; 0386 #endif 0387 0388 typedef DWORD (WINAPI *GetNetworkParamsFunc)(PFIXED_INFO, PULONG); 0389 0390 static jdns_string_t *reg_readString(HKEY hk, const char *subkey) 0391 { 0392 char *buf; 0393 DWORD bufsize; 0394 int ret; 0395 jdns_string_t *str = 0; 0396 0397 bufsize = 1024; 0398 buf = (char *)jdns_alloc((int)bufsize); 0399 if(!buf) 0400 return 0; 0401 ret = RegQueryValueExA(hk, subkey, 0, 0, (LPBYTE)buf, &bufsize); 0402 if(ret == ERROR_MORE_DATA) 0403 { 0404 buf = (char *)jdns_realloc(buf, bufsize); 0405 if(!buf) 0406 { 0407 jdns_free(buf); 0408 return 0; 0409 } 0410 ret = RegQueryValueExA(hk, subkey, 0, 0, (LPBYTE)buf, &bufsize); 0411 } 0412 if(ret == ERROR_SUCCESS) 0413 { 0414 str = jdns_string_new(); 0415 jdns_string_set_cstr(str, (char *)buf); 0416 } 0417 jdns_free(buf); 0418 return str; 0419 } 0420 0421 static jdns_dnsparams_t *dnsparams_get_winreg() 0422 { 0423 int n; 0424 jdns_dnsparams_t *params; 0425 HKEY key; 0426 int ret; 0427 char sep; 0428 jdns_string_t *str_domain, *str_nameserver, *str_searchlist; 0429 jdns_stringlist_t *list_nameserver, *list_searchlist; 0430 0431 sep = ' '; 0432 ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, 0433 "System\\CurrentControlSet\\Services\\Tcpip\\Parameters", 0434 0, KEY_READ, &key); 0435 if(ret != ERROR_SUCCESS) 0436 { 0437 sep = ','; 0438 ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, 0439 "System\\CurrentControlSet\\Services\\VxD\\MSTCP", 0440 0, KEY_READ, &key); 0441 if(ret != ERROR_SUCCESS) 0442 return 0; 0443 } 0444 0445 str_domain = reg_readString(key, "DhcpDomain"); 0446 if(!str_domain) 0447 str_domain = reg_readString(key, "Domain"); 0448 str_nameserver = reg_readString(key, "DhcpNameServer"); 0449 if(!str_nameserver) 0450 str_nameserver = reg_readString(key, "NameServer"); 0451 str_searchlist = reg_readString(key, "SearchList"); 0452 0453 RegCloseKey(key); 0454 0455 list_nameserver = 0; 0456 if(str_nameserver) 0457 { 0458 list_nameserver = string_split(str_nameserver, sep); 0459 jdns_string_delete(str_nameserver); 0460 } 0461 list_searchlist = 0; 0462 if(str_searchlist) 0463 { 0464 /* lowercase the string */ 0465 jdns_string_t *p = string_tolower(str_searchlist); 0466 jdns_string_delete(str_searchlist); 0467 str_searchlist = p; 0468 0469 list_searchlist = string_split(str_searchlist, sep); 0470 jdns_string_delete(str_searchlist); 0471 } 0472 0473 params = jdns_dnsparams_new(); 0474 if(list_nameserver) 0475 { 0476 /* qt seems to do a strange thing here by running each name */ 0477 /* server address through the q3dns setLabel function, and */ 0478 /* then pulls the result as a list of addresses. i have */ 0479 /* no idea why they do this, or how one IP address would */ 0480 /* turn into anything else, let alone several addresses. */ 0481 /* so, uh, we're not going to do that. */ 0482 for(n = 0; n < list_nameserver->count; ++n) 0483 { 0484 jdns_address_t *addr = jdns_address_new(); 0485 if(jdns_address_set_cstr(addr, (char *)list_nameserver->item[n]->data)) 0486 jdns_dnsparams_append_nameserver(params, addr, JDNS_UNICAST_PORT); 0487 jdns_address_delete(addr); 0488 } 0489 jdns_stringlist_delete(list_nameserver); 0490 } 0491 if(str_domain) 0492 { 0493 if(str_domain->size > 0) 0494 jdns_dnsparams_append_domain(params, str_domain); 0495 jdns_string_delete(str_domain); 0496 } 0497 if(list_searchlist) 0498 { 0499 for(n = 0; n < list_searchlist->count; ++n) 0500 { 0501 if(list_searchlist->item[n]->size > 0) 0502 jdns_dnsparams_append_domain(params, list_searchlist->item[n]); 0503 } 0504 jdns_stringlist_delete(list_searchlist); 0505 } 0506 0507 return params; 0508 } 0509 0510 static jdns_dnsparams_t *dnsparams_get_winsys() 0511 { 0512 jdns_dnsparams_t *params; 0513 GetNetworkParamsFunc myGetNetworkParams; 0514 DWORD ret; 0515 HINSTANCE lib; 0516 jdns_address_t *addr; 0517 jdns_string_t *str; 0518 IP_ADDR_STRING *ipstr; 0519 0520 lib = LoadLibraryA("iphlpapi"); 0521 if(!lib) 0522 return 0; 0523 0524 params = 0; 0525 myGetNetworkParams = (GetNetworkParamsFunc)GetProcAddress(lib, "GetNetworkParams"); 0526 if(myGetNetworkParams) 0527 { 0528 ULONG bufsize = 0; 0529 ret = myGetNetworkParams(0, &bufsize); 0530 if(ret == ERROR_BUFFER_OVERFLOW) 0531 { 0532 FIXED_INFO *info = (FIXED_INFO *)jdns_alloc((int)bufsize); 0533 ret = myGetNetworkParams(info, &bufsize); 0534 if(ret == ERROR_SUCCESS) 0535 { 0536 params = jdns_dnsparams_new(); 0537 ipstr = &info->DnsServerList; 0538 while(ipstr) 0539 { 0540 addr = jdns_address_new(); 0541 if(jdns_address_set_cstr(addr, (char *)ipstr->IpAddress.String)) 0542 jdns_dnsparams_append_nameserver(params, addr, JDNS_UNICAST_PORT); 0543 jdns_address_delete(addr); 0544 ipstr = ipstr->Next; 0545 } 0546 str = jdns_string_new(); 0547 jdns_string_set_cstr(str, info->DomainName); 0548 if(str->size > 0) 0549 jdns_dnsparams_append_domain(params, str); 0550 jdns_string_delete(str); 0551 } 0552 jdns_free(info); 0553 } 0554 } 0555 FreeLibrary(lib); 0556 return params; 0557 } 0558 0559 static void apply_win_hosts_file(jdns_dnsparams_t *a) 0560 { 0561 jdns_string_t *p; 0562 char *str; 0563 int len; 0564 0565 p = jdns_getenv("WINDIR"); 0566 if(!p) 0567 return; 0568 len = strlen((char *)p->data); 0569 str = (char *)jdns_alloc(len + 100); /* should be enough */ 0570 memcpy(str, p->data, len); 0571 jdns_string_delete(p); 0572 jdns_strcpy(str + len, "\\system32\\drivers\\etc\\hosts"); /* winnt+ */ 0573 apply_hosts_file(a, str); 0574 jdns_strcpy(str + len, "\\hosts"); /* win9x */ 0575 apply_hosts_file(a, str); 0576 jdns_free(str); 0577 } 0578 0579 static jdns_dnsparams_t *dnsparams_get_win() 0580 { 0581 int n; 0582 jdns_dnsparams_t *sys_params, *reg_params; 0583 0584 reg_params = dnsparams_get_winreg(); 0585 sys_params = dnsparams_get_winsys(); 0586 0587 /* no sys params? take the reg params then */ 0588 if(!sys_params) 0589 { 0590 apply_win_hosts_file(reg_params); 0591 return reg_params; 0592 } 0593 0594 /* sys params don't have a search list, so merge the domains from */ 0595 /* the registry if possible */ 0596 if(reg_params) 0597 { 0598 for(n = 0; n < reg_params->domains->count; ++n) 0599 { 0600 jdns_string_t *reg_str = reg_params->domains->item[n]; 0601 0602 /* don't add dups */ 0603 if(!dnsparams_have_domain(sys_params, reg_str)) 0604 jdns_dnsparams_append_domain(sys_params, reg_str); 0605 } 0606 jdns_dnsparams_delete(reg_params); 0607 } 0608 apply_win_hosts_file(sys_params); 0609 return sys_params; 0610 } 0611 0612 #endif 0613 0614 #ifdef JDNS_OS_UNIX 0615 0616 static jdns_dnsparams_t *dnsparams_get_unixfiles() 0617 { 0618 FILE *f; 0619 int n; 0620 jdns_dnsparams_t *params; 0621 jdns_string_t *line, *simp; 0622 jdns_stringlist_t *parts; 0623 0624 params = jdns_dnsparams_new(); 0625 0626 f = jdns_fopen("/etc/resolv.conf", "r"); 0627 if(!f) 0628 return params; 0629 while(1) 0630 { 0631 line = file_nextline(f); 0632 if(!line) 0633 break; 0634 0635 /* truncate at comment */ 0636 n = string_indexOf(line, '#', 0); 0637 if(n != -1) 0638 { 0639 line->size = n; 0640 line->data[n] = 0; 0641 } 0642 0643 simp = string_simplify(line); 0644 jdns_string_delete(line); 0645 0646 parts = string_split(simp, ' '); 0647 jdns_string_delete(simp); 0648 0649 if(parts->count < 2) 0650 { 0651 jdns_stringlist_delete(parts); 0652 continue; 0653 } 0654 0655 simp = string_tolower(parts->item[0]); 0656 if(strcmp((char *)simp->data, "nameserver") == 0) 0657 { 0658 jdns_address_t *addr = jdns_address_new(); 0659 jdns_address_set_cstr(addr, (const char *)parts->item[1]->data); 0660 jdns_dnsparams_append_nameserver(params, addr, JDNS_UNICAST_PORT); 0661 jdns_address_delete(addr); 0662 } 0663 else if(strcmp((char *)simp->data, "search") == 0) 0664 { 0665 for(n = 1; n < parts->count; ++n) 0666 { 0667 jdns_dnsparams_append_domain(params, parts->item[n]); 0668 } 0669 } 0670 else if(strcmp((char *)simp->data, "domain") == 0) 0671 { 0672 jdns_dnsparams_append_domain(params, parts->item[1]); 0673 } 0674 jdns_string_delete(simp); 0675 0676 jdns_stringlist_delete(parts); 0677 } 0678 fclose(f); 0679 return params; 0680 } 0681 0682 #if defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 3))) 0683 # define JDNS_MODERN_RES_API 0684 #endif 0685 0686 #ifndef JDNS_MODERN_RES_API 0687 typedef int (*res_init_func)(); 0688 static int my_res_init() 0689 { 0690 #ifdef JDNS_OS_MAC 0691 res_init_func mac_res_init; 0692 0693 /* look up res_init in the system library (qt does this, not sure why) */ 0694 mac_res_init = (res_init_func)dlsym(RTLD_NEXT, "res_init"); 0695 if(!mac_res_init) 0696 return -1; 0697 return mac_res_init(); 0698 #else 0699 return res_init(); 0700 #endif 0701 } 0702 #endif 0703 0704 #if defined(JDNS_OS_MAC) || defined(JDNS_OS_FREEBSD) || \ 0705 defined(JDNS_OS_NETBSD) || defined(JDNS_OS_OPENBSD) || defined (JDNS_OS_SOLARIS) 0706 # define USE_EXTEXT 0707 #endif 0708 0709 static jdns_dnsparams_t *dnsparams_get_unixsys() 0710 { 0711 int n; 0712 jdns_dnsparams_t *params; 0713 0714 #ifdef JDNS_MODERN_RES_API 0715 struct __res_state res; 0716 memset(&res, 0, sizeof(struct __res_state)); 0717 n = res_ninit(&res); 0718 #define RESVAR res 0719 #else 0720 n = my_res_init(); 0721 #define RESVAR _res 0722 #endif 0723 0724 #ifdef JDNS_OS_OPENBSD 0725 #define RESVAREXT _res_ext 0726 #else 0727 #define RESVAREXT RESVAR._u._ext 0728 #endif 0729 0730 params = jdns_dnsparams_new(); 0731 0732 /* error initializing? */ 0733 if(n == -1) 0734 return params; 0735 0736 /* nameservers - ipv6 */ 0737 #ifdef JDNS_OS_OPENBSD 0738 for(n = 0; n < MAXNS; ++n) 0739 #else 0740 for(n = 0; n < MAXNS && n < RESVAREXT.nscount; ++n) 0741 #endif 0742 { 0743 jdns_address_t *addr; 0744 struct sockaddr_in6 *sa6; 0745 0746 #if defined(USE_EXTEXT) && !defined(JDNS_OS_OPENBSD) 0747 sa6 = ((struct sockaddr_in6 *)RESVAREXT.ext) + n; 0748 #elif defined(JDNS_OS_OPENBSD) 0749 sa6 = &RESVAREXT.nsaddr_list[n]; 0750 #else 0751 sa6 = RESVAREXT.nsaddrs[n]; 0752 #endif 0753 0754 if(sa6 == NULL) 0755 continue; 0756 addr = jdns_address_new(); 0757 jdns_address_set_ipv6(addr, sa6->sin6_addr.s6_addr); 0758 jdns_dnsparams_append_nameserver(params, addr, JDNS_UNICAST_PORT); 0759 jdns_address_delete(addr); 0760 } 0761 0762 /* nameservers - ipv4 */ 0763 for(n = 0; n < MAXNS && n < RESVAR.nscount; ++n) 0764 { 0765 jdns_address_t *addr = jdns_address_new(); 0766 jdns_address_set_ipv4(addr, ntohl(RESVAR.nsaddr_list[n].sin_addr.s_addr)); 0767 jdns_dnsparams_append_nameserver(params, addr, JDNS_UNICAST_PORT); 0768 jdns_address_delete(addr); 0769 } 0770 0771 /* domain name */ 0772 if(strlen(RESVAR.defdname) > 0) 0773 { 0774 jdns_string_t *str; 0775 jdns_string_t *p; 0776 str = jdns_string_new(); 0777 jdns_string_set_cstr(str, RESVAR.defdname); 0778 p = string_tolower(str); 0779 jdns_string_delete(str); 0780 str = p; 0781 jdns_dnsparams_append_domain(params, str); 0782 jdns_string_delete(str); 0783 } 0784 0785 /* search list */ 0786 #ifdef MAXDFLSRCH 0787 for(n = 0; n < MAXDFLSRCH && RESVAR.dnsrch[n]; ++n) 0788 { 0789 if(strlen(RESVAR.dnsrch[n]) > 0) 0790 { 0791 jdns_string_t *str; 0792 jdns_string_t *p; 0793 str = jdns_string_new(); 0794 jdns_string_set_cstr(str, RESVAR.dnsrch[n]); 0795 p = string_tolower(str); 0796 jdns_string_delete(str); 0797 str = p; 0798 0799 /* don't add dups */ 0800 if(!dnsparams_have_domain(params, str)) 0801 jdns_dnsparams_append_domain(params, str); 0802 0803 jdns_string_delete(str); 0804 } 0805 } 0806 #endif 0807 0808 return params; 0809 } 0810 0811 static jdns_dnsparams_t *dnsparams_get_unix() 0812 { 0813 jdns_dnsparams_t *params; 0814 0815 /* prefer system calls over files */ 0816 params = dnsparams_get_unixsys(); 0817 if(params->nameservers->count == 0) 0818 { 0819 jdns_dnsparams_delete(params); 0820 params = dnsparams_get_unixfiles(); 0821 } 0822 0823 apply_hosts_file(params, "/etc/hosts"); 0824 0825 return params; 0826 } 0827 0828 #endif 0829 0830 jdns_dnsparams_t *jdns_system_dnsparams() 0831 { 0832 #ifdef JDNS_OS_WIN 0833 return dnsparams_get_win(); 0834 #else 0835 return dnsparams_get_unix(); 0836 #endif 0837 }