Как gcc / cygwin получает DNS-сервер?

У меня есть код, который я пишу под cygwin (используя GCC), который успешно использует gethostbyname (); однако, когда я пытаюсь использовать распознаватель напрямую для получения IP-адреса DNS-сервера, он терпит неудачу (все записи в nsaddr_list[] равны нулю, а nscount -1). Если gethostbyname () работает, то, очевидно, он может подключиться к DNS-серверу.
Настоящий кодекс...

    if (res_init() == -1) {
        fprintf(stderr,"res_init() failedn");
        exit(1);
    }

    if (_res.nscount <= 0) {
        fprintf(stderr,"nscount = %dn",_res.nscount);
    }
    else {
        for(i=0;i<_res.nscount;i++) {
            fprintf(stderr, "dnssrvr: %d.%d.%d.%dn",
                (_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, но возвращает nscount=-1 на cygwin. Есть ли какой-то трюк для получения DNS сервер при использовании cygwin / gcc?

2 ответов


As n.м. говорит, на Cygwin res_init() не заполняет _res.nsaddr_list если он использует распознаватель Windows. Он использует распознаватель Windows, Если либо /etc/resolv.conf не существует, или /etc/resolv.conf содержит options 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 на


res_init не обязательно заполнять _res.nsaddr_list. Вместо этого в Windows он направляет распознаватель использовать DnsQuery_A, если у вас resolv.conf file, в этом случае используются DNS-серверы из этого файла.

посмотреть источник здесь, files minires.c и minires-os-if.c.

Если вам нужно знать свои DNS-серверы, вам, вероятно, придется использовать DnsQueryConfig или GetNetworkParams.

NB:_res является недокументированным и не должен использоваться.

обновление по-видимому, "новые" (ca 2010 и более поздние) версии cygwin действительно заполняют _res.nsaddr_list, через вызов get_dns_info а то get_registry_dns. Вы можете убедиться, что у вас есть новейший cygwin, и если проблема не устранена, попробуйте использовать отладочную версию и трассировку вызовов указанных функций.

обновление 2 нет, _res не заселен, моя ошибка.