gcc/cygwin如何获取DNS服务器?
Posted
技术标签:
【中文标题】gcc/cygwin如何获取DNS服务器?【英文标题】:How does gcc/cygwin get the DNS server? 【发布时间】:2012-05-18 10:12:11 【问题描述】:我在 cygwin(使用 GCC)下编写了一些成功使用 gethostbyname() 的代码;但是,当我尝试直接使用解析器来检索 DNS 服务器的 IP 地址时,它会失败(nsaddr_list[] 中的所有条目都为空且 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, "dns-s-rvr: %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服务器有什么技巧吗?
【问题讨论】:
顺便说一句,您可以使用 char buf[INET_ADDRSTRLEN]; fprintf(stderr, "dns-s-rvr: %s\n", inet_ntop(AF_INET, &_res.nsaddr_list[i].sin_addr, buf, sizeof buf));
来格式化IP地址。
好点,干净多了。谢谢。
【参考方案1】:
res_init
不一定填充_res.nsaddr_list
。相反,在 Windows 上,它指示解析器使用 DnsQuery_A
,除非您有 resolv.conf
文件,在这种情况下,将使用该文件中的 DNS 服务器。
查看源代码here、文件minires.c
和minires-os-if.c
。
如果您需要了解您的 DNS 服务器,您可能必须使用 DnsQueryConfig
或 GetNetworkParams
。
注意:_res
未记录,不应使用。
更新 显然,cygwin 的“较新”(ca 2010 及更高版本)版本确实填充_res.nsaddr_list
,通过调用get_dns_info
然后get_registry_dns
。您可能需要确保您拥有最新的 cygwin,如果问题仍然存在,请尝试使用调试版本并跟踪对上述函数的调用。
更新 2 不,_res
未填充,我的错误。
【讨论】:
仔细观察,如果use_os
不为零,即使是最新的cygwin 也不会填充nsaddr_list
- 如果没有/etc/resolv.conf
或/etc/resolv.conf
包含options osquery
,这是真的。因此,让 cygwin 从操作系统名称服务器列表中填写 nsaddr_list
的唯一方法是使用空的 /etc/resolv.conf
。
@caf:是的。但我认为 Windows 上通常没有 /etc/resolv.conf
当然 - 并且有 no /etc/resolv.conf
会导致 nsaddr_list
不被填写。所以我认为让 Cygwin 特定的代码调用 GetNetworkParams()
看起来是唯一的解决方案。
@caf:我认为这是不正确的。 res_init
→ res_ninit
→ get_dns_info
(use_os==1
和 nscount==0
)→ nscount=-1
→ goto use_registry
和 nsaddr_list
从那里的注册表中填充。
@caf:我现在没有要检查的 Windows 机器。 This thread 似乎表明我之前评论中概述的顺序不起作用,但我不确定为什么。【参考方案2】:
作为n.m. says,在Cygwin 上res_init()
不会填充_res.nsaddr_list
,如果它使用的是Windows 解析器。如果/etc/resolv.conf
不存在,或者/etc/resolv.conf
包含options osquery
,它将使用Windows 解析器。
在我看来,这是一个 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()
函数。
这仅获取第一个 Windows DNS 地址,但如果您想要其余的地址,您可以按照GetNetworkParams()
返回的链接列表进行操作。 GetNetworkParams()
只返回 IPv4 地址,如果机器配置了 IPv6 DNS 服务器地址,我不确定你应该做什么。
【讨论】:
这给了我我需要的东西!谢谢。以上是关于gcc/cygwin如何获取DNS服务器?的主要内容,如果未能解决你的问题,请参考以下文章
ANSI C 如何在 Linux 中获取名称服务器(DNS)地址? [复制]