gpt4 book ai didi

iOS:如何指定用于将主机名解析为 IP 地址的 DNS?

转载 作者:搜寻专家 更新时间:2023-10-31 08:21:52 28 4
gpt4 key购买 nike

正如标题所说,我有主机名(例如 www.example.com),我想使用指定的 DNS 服务器解析它。例如,在一种情况下我想使用谷歌的 IPv4 DNS,在另一种情况下我想使用谷歌的 IPv6 DNS。

我在 iOS 上浏览过类似这样的东西,并发现了类似这样的问题 ( Swift - Get device's IP Address ),所以我确信它可以完成,但我不清楚如何做?

我该怎么做?

编辑 06/07/2018

@mdeora 建议的解决方案来自 http://www.software7.com/blog/programmatically-query-specific-dns-servers-on-ios/

此解决方案有效,但前提是我使用 IPv4 DNS,例如谷歌的“8.8.8.8”。如果我尝试使用 IPv6 DNS 2001:4860:4860::8888,我什么也得不到。

我已经成功地改变了转换:

void setup_dns_server(res_state res, const char *dns_server)
{
res_ninit(res);
struct in_addr addr;

// int returnValue = inet_aton(dns_server, &addr);
inet_pton(AF_INET6, dns_server, &addr); // for IPv6 conversion

res->nsaddr_list[0].sin_addr = addr;
res->nsaddr_list[0].sin_family = AF_INET;
res->nsaddr_list[0].sin_port = htons(NS_DEFAULTPORT);
res->nscount = 1;

};

但是还是有问题:

void query_ip(res_state res, const char *host, char ip[])
{
u_char answer[NS_PACKETSZ];//NS_IN6ADDRSZ NS_PACKETSZ
int len = res_nquery(res, host, ns_c_in, ns_t_a, answer, sizeof(answer));

ns_msg handle;
ns_initparse(answer, len, &handle);


if(ns_msg_count(handle, ns_s_an) > 0) {
ns_rr rr;
if(ns_parserr(&handle, ns_s_an, 0, &rr) == 0) {
strcpy(ip, inet_ntoa(*(struct in_addr *)ns_rr_rdata(rr)));
}
}
}

我得到 len 的 -1。据我所知,我似乎需要为 IPv6 配置 res_state。

最佳答案

这里是我的博文中的代码,上面已经提到过,只是稍微调整一下以使用 IPv6。

调整 setup_dns_server

首先我们可以从更改 setup_dns_server 开始:

void setup_dns_server(res_state res, const char *dns_server) {
struct in6_addr addr;

inet_pton(AF_INET6, dns_server, &addr);

res->_u._ext.ext->nsaddrs[0].sin6.sin6_addr = addr;
res->_u._ext.ext->nsaddrs[0].sin6.sin6_family = AF_INET6;
res->_u._ext.ext->nsaddrs[0].sin6.sin6_port = htons(NS_DEFAULTPORT);
res->nscount = 1;
}

添加 __res_state_ext

由于缺少 struct __res_state_ext,因此无法编译。不幸的是,这个结构在私有(private)头文件中。

但是那个的定义可以从这里获取: https://opensource.apple.com/source/libresolv/libresolv-65/res_private.h.auto.html :

struct __res_state_ext {
union res_sockaddr_union nsaddrs[MAXNS];
struct sort_list {
int af;
union {
struct in_addr ina;
struct in6_addr in6a;
} addr, mask;
} sort_list[MAXRESOLVSORT];
char nsuffix[64];
char bsuffix[64];
char nsuffix2[64];
};

可以添加结构,例如在文件的顶部。

适配resolveHost

此处的更改包括更长的 ip 缓冲区 (INET6_ADDRSTRLEN)。 res_ninit 从 setup_dns_server 移动到此方法中,现在与 res_ndestroy 匹配。

+ (NSString *)resolveHost:(NSString *)host usingDNSServer:(NSString *)dnsServer {
struct __res_state res;
char ip[INET6_ADDRSTRLEN];
memset(ip, '\0', sizeof(ip));

res_ninit(&res);
setup_dns_server(&res, [dnsServer cStringUsingEncoding:NSASCIIStringEncoding]);
query_ip(&res, [host cStringUsingEncoding:NSUTF8StringEncoding], ip);
res_ndestroy(&res);

return [[NSString alloc] initWithCString:ip encoding:NSASCIIStringEncoding];
}

检索 IPv6 地址

如果您只想为您的 DNS 服务器使用 IPv6 地址,上述更改已经足够了。因此,如果您仍想检索 IPv4 地址,则在 query_ip 中无需进行任何更改。

如果您还想从 DNS 服务器检索 IPv6 地址,您可以这样做:

void query_ip(res_state res, const char *host, char ip[]) {
u_char answer[NS_PACKETSZ];
int len = res_nquery(res, host, ns_c_in, ns_t_aaaa, answer, sizeof(answer));

ns_msg handle;
ns_initparse(answer, len, &handle);


if(ns_msg_count(handle, ns_s_an) > 0) {
ns_rr rr;
if(ns_parserr(&handle, ns_s_an, 0, &rr) == 0) {
inet_ntop(AF_INET6, ns_rr_rdata(rr), ip, INET6_ADDRSTRLEN);
}
}
}

请注意:我们在这里使用 ns_t_aaaa 来获取 AAAA 资源记录(quad-A 记录),因为在 DNS 中这指定了 IPv6 地址和主机名之间的映射。对于许多主机,没有这样的 quad-A 记录,这意味着您可以通过 IPv4 访问它们。

调用

你可以这样调用它,例如像这样:

NSString *resolved = [ResolveUtil resolveHost:@"www.google.com" usingDNSServer:@"2001:4860:4860::8888"];
NSLog(@"%@", resolved);

结果看起来像这样:

test output

免责声明

这些只是简单的示例调用,演示了函数的基本用法。没有错误处理。

关于iOS:如何指定用于将主机名解析为 IP 地址的 DNS?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50703405/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com