2012-05-09 13 views
8

मेरे पास कुछ कोड है जो मैं साइगविन (जीसीसी का उपयोग करके) के तहत लिख रहा हूं जो सफलतापूर्वक gethostbyname() का उपयोग करता है; हालांकि जब मैं DNS सर्वर के आईपी पते को पुनर्प्राप्त करने के लिए सीधे रिज़ॉल्वर का उपयोग करने का प्रयास करता हूं तो यह विफल हो जाता है (nsaddr_list [] में सभी प्रविष्टियां शून्य हैं और nscount -1 है)। अगर gethostbyname() काम कर रहा है, तो जाहिर है कि यह DNS सर्वर से कनेक्ट करने में सक्षम है।
इस कोड को ... यूनिक्स/लिनक्स परजीसीसी/साइगविन को DNS सर्वर कैसे मिलता है?

if (res_init() == -1) { 
     fprintf(stderr,"res_init() failed\n"); 
     exit(1); 
    } 

    if (_res.nscount <= 0) { 
     fprintf(stderr,"nscount = %d\n",_res.nscount); 
    } 
    else { 
     for(i=0;i<_res.nscount;i++) { 
      fprintf(stderr, "dnssrvr: %d.%d.%d.%d\n", 
       (_res.nsaddr_list[i].sin_addr.s_addr & 0xff) >> 0, 
       (_res.nsaddr_list[i].sin_addr.s_addr & 0xff00) >> 8, 
       (_res.nsaddr_list[i].sin_addr.s_addr & 0xff0000) >> 16, 
       (_res.nsaddr_list[i].sin_addr.s_addr & 0xff000000) >> 24); 
     } 
    } 

काम करता है, लेकिन रिटर्न nscount = -1 cygwin पर। क्या साइगविन/जीसीसी का उपयोग करते समय DNS सर्वर प्राप्त करने के लिए कुछ चाल है?

+0

एक तरफ के रूप में, आप '{char buf [INET_ADDRSTRLEN] का उपयोग कर सकते हैं; fprintf (stderr, "dnssrvr:% s \ n", inet_ntop (AF_INET, और _res.nsaddr_list [i] .sin_addr, buf, sizeof buf)); } 'आईपी पते को प्रारूपित करने के लिए। – caf

+0

अच्छा बिंदु, बहुत साफ। धन्यवाद। –

उत्तर

2

n.m. says के रूप में, सिगविन res_init() पर _res.nsaddr_list पॉप्युलेट नहीं करता है यदि यह विंडोज रिज़ॉल्वर का उपयोग कर रहा है। यह विंडोज रिज़ॉल्वर का उपयोग करता है यदि /etc/resolv.conf मौजूद नहीं है, या /etc/resolv.conf में options osquery है।

मेरी राय में यह एक सिगविन बग है - ऋणात्मक nscount लौट रहा है - लेकिन फिर भी हम इसके आसपास काम करने के साथ फंस गए हैं।

समाधान GetNetworkParams() कॉल करने के लिए Cygwin ही है बस के रूप में है - यहाँ है कि मैं क्या एक fallback के रूप में कर रहा हूँ:

#include <windows.h> 
#include <iphlpapi.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 

if (_res.nscount < 0) 
{ 
    ULONG buflen = 0; 
    FIXED_INFO *buf = NULL; 

    if (GetNetworkParams(NULL, &buflen) == ERROR_BUFFER_OVERFLOW) 
     buf = malloc(buflen); 

    if (buf && GetNetworkParams(buf, &buflen) == NO_ERROR) 
    { 
     _res.nscount = 1; 
     _res.nsaddr_list[0].sin_family = AF_INET; 
     _res.nsaddr_list[0].sin_addr.s_addr = inet_addr(buf->DnsServerList.IpAddress.String); 
     _res.nsaddr_list[0].sin_port = htons(53); 
    } 

    free(buf); 
} 

आप GetNetworkParams() समारोह के लिए -liphlpapi के खिलाफ लिंक करना होगा।

यह केवल पहला विंडोज DNS पता लेता है, लेकिन यदि आप उनमें से बाकी चाहते हैं तो आप GetNetworkParams() रिटर्न से जुड़े लिंक का अनुसरण कर सकते हैं। GetNetworkParams() केवल आईपीवी 4 पते लौटाता है, मुझे यकीन नहीं है कि मशीन को आईपीवी 6 DNS सर्वर पता कॉन्फ़िगर किया गया है तो आपको क्या करना है।

+1

यह मुझे जो चाहिए वह देता है! धन्यवाद। –

3

res_init आवश्यक रूप से _res.nsaddr_list पॉप्युलेट नहीं करता है। इसके बजाए, विंडोज़ पर यह DnsQuery_A, का उपयोग करने के लिए रिज़ॉल्यूवर को निर्देशित करता है जब तक आपके पास resolv.conf फ़ाइल है, जिस स्थिति में उस फ़ाइल से DNS सर्वर का उपयोग किया जाता है।

स्रोत here, minires.c और minires-os-if.c फ़ाइलें देखें।

यदि आपको अपने DNS सर्वरों को जानना है, तो आपको शायद DnsQueryConfig या GetNetworkParams का उपयोग करना होगा।

एनबी: _res अनियंत्रित है और इसका उपयोग नहीं किया जाना चाहिए।

अद्यतन जाहिर है "नए" (2010 और बाद में सीए) cygwin के संस्करणों get_dns_info और फिर get_registry_dns को पॉप्युलेट करते _res.nsaddr_list, एक कॉल के माध्यम से। आप यह सुनिश्चित करना चाहते हैं कि आपके पास नवीनतम सिगविन है, और यदि समस्या बनी रहती है, तो डीबग संस्करण का उपयोग करने और उल्लिखित कार्यों पर कॉल का पता लगाने का प्रयास करें।

अद्यतन 2 नहीं, _res मेरी गलती नहीं है।

+0

बारीकी से देख रहे हैं, यहां तक ​​कि नवीनतम cygwin 'nsaddr_list' को पॉप्युलेट नहीं करता है अगर' use_os' nonzero है - यह सच है या तो कोई '/ etc/resolv.conf' नहीं है या यदि'/etc/resolv.conf' में ' विकल्प osquery'। इसलिए नेमसर्वर की ओएस सूची से 'nsaddr_list' में भरने के लिए साइगविन प्राप्त करने का एकमात्र तरीका खाली '/ etc/resolv.conf' होना है। – caf

+0

@caf: हाँ। लेकिन मुझे लगता है कि सामान्य रूप से विंडोज –

+0

पर कोई '/ etc/resolv.conf' नहीं है - और * नहीं *'/etc/resolv.conf' होने के कारण 'nsaddr_list' भरना नहीं है। तो मुझे लगता है कि 'GetNetworkParams()' को कॉल करने के लिए सिगविन-विशिष्ट कोड को एकमात्र समाधान की तरह दिख रहा है। – caf

संबंधित मुद्दे