2012-05-09 29 views
8

gethostbyname()をうまく使っているcygwin(GCCを使用)の下で書いているコードがあります。しかし、DNSサーバーのIPアドレスを取得するためにリゾルバを直接使用しようとすると失敗します(nsaddr_list []のすべてのエントリはnullで、nscountは-1です)。 gethostbyname()が動作している場合、明らかにDNSサーバーに接続できます。
このコードは... UNIX/Linux上でgcc/cygwinはどのように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の上で。 cygwin/gccを使用しているときにDNSサーバを取得するためのトリックはありますか?

+0

脇に、あなたは '{char buf [INET_ADDRSTRLEN]; fprintf(stderr、 "dnssrvr:%s \ n"、inet_ntop(AF_INET、&_res.nsaddr_list [i] .sin_addr、buf、sizeof buf)); IPアドレスをフォーマットする} ' – caf

+0

良い点、もっとクリーナー。ありがとう。 –

答えて

2

n.m. saysとして、Windowsリゾルバを使用している場合、_res.nsaddr_listがCygwin res_init()に入力されません。 /etc/resolv.confが存在しない場合、または/etc/resolv.confoptions osqueryが含まれている場合は、Windowsリゾルバを使用します。

私の意見では、これはCygwinのバグです。否定的な結果を返すのはnscountですが、私たちはそれに取り組んでいます。

#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とリンクする必要があります。ここで私がフォールバックとしてやっているものだ -

ソリューションは、Cygwinは、それ自体を同じようGetNetworkParams()を呼び出すことです。

これは最初のWindows DNSアドレスのみを使用しますが、残りの部分が必要な場合は、GetNetworkParams()が返すリンクリストに従うことができます。 GetNetworkParams()はIPv4アドレスだけを返すので、マシンにIPv6 DNSサーバアドレスが設定されている場合は、どうしたらいいのか分かりません。

+1

これは私に必要なものを与える!ありがとう。 –

3

res_initは必ずしも入力する必要はありません_res.nsaddr_list。 Windowsでは、DnsQuery_A,に設定しないと、resolv.confファイルを使用するようにリゾルバに指示します。この場合、そのファイルのDNSサーバーが使用されます。

ソースhere、ファイルminires.cおよびminires-os-if.cを参照してください。

DNSサーバーを知る必要がある場合は、おそらくDnsQueryConfigまたはGetNetworkParamsを使用する必要があります。

NB:_resは文書化されていないので、使用しないでください。

UPDATEどうやら "新しい"(カリフォルニア州2010年以降)のCygwinのバージョンはget_dns_info、その後get_registry_dnsに呼び出しを介して、_res.nsaddr_listを移入します。最新のCygwinがインストールされていることを確認し、問題が解決しない場合は、デバッグバージョンを使用して、上記の関数の呼び出しをトレースしてみてください。

UPDATE 2いいえ、_resは、私の間違いです。

+0

最近のcygwinでも 'use_os'が0でない場合、' nsaddr_list'に値を設定しません。これは '/ etc/resolv.conf'がない場合や'/etc/resolv.conf'に 'オプションosquery'。したがって、ネームサーバのOSリストからcygwinに 'nsaddr_list'を書き込ませる唯一の方法は、空の'/etc/resolv.conf'を持つことです。 – caf

+0

@caf:はい。私は通常、Windowsには '/ etc/resolv.conf'はありません。 –

+0

確かに* no *'/etc/resolv.conf'は 'nsaddr_list'を記入しません。ですから、 'GetNetworkParams()'を呼び出すCygwin固有のコードを唯一の解決策のように見ていると思います。 – caf

関連する問題