8

gethostbyname(); を正常に使用する cygwin で (GCC を使用して) 書いているコードがあります。ただし、リゾルバーを直接使用して DNS サーバーの IP アドレスを取得しようとすると失敗します (nsaddr_list[] のすべてのエントリが null で、nscount が -1 です)。gethostbyname() が機能している場合、明らかに 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);
        }
    }

unix/linux で動作しますが、cygwin では nscount=-1 を返します。cygwin/gcc を使用しているときに DNS サーバーを取得するためのトリックはありますか?

4

2 に答える 2

3

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

ここのソース、ファイルminires.cminires-os-if.c.

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

注意:_res文書化されていないため、使用しないでください。

更新 どうやら cygwin の「新しい」(ca 2010 以降) バージョンは_res.nsaddr_list、 への呼び出しを介してget_dns_info、そしてget_registry_dns. 最新の cygwin を使用していることを確認し、問題が解決しない場合は、デバッグ バージョンを使用して、前述の関数の呼び出しをトレースしてみてください。

更新 2いいえ、_res入力されていません、私の間違いです。

于 2012-05-27T10:32:16.577 に答える
2

nmが言うように、Windowsリゾルバーを使用している場合、Cygwinではデータres_init()が入力されません。存在しないか、が含まれている_res.nsaddr_list場合は、Windowsリゾルバーを使用します。/etc/resolv.conf/etc/resolv.confoptions osquery

私の意見では、これはCygwinのバグであり、ネガティブを返すことnscountは偽物ですが、それでも私たちはそれを回避することに固執しています。

GetNetworkParams()解決策は、Cygwin自体と同じように呼び出すことです。これが、フォールバックとして実行していることです。

#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);
}

-liphlpapi関数に対してリンクする必要がありGetNetworkParams()ます。

これは最初のWindowsDNSアドレスのみを取得しますが、残りが必要な場合は、GetNetworkParams()返されるリンクリストをたどることができます。 GetNetworkParams()IPv4アドレスのみを返します。マシンにIPv6DNSサーバーアドレスが構成されている場合、どうすればよいかわかりません。

于 2012-06-01T03:25:37.030 に答える