在先前有关IPv6本地链接地址的讨论中,我看到一条评论:
有人会争辩说,对于任何类型的地址,都不应使用地址代替主机名。使用mDNS映射到本地链接地址可以正常工作。
讨论的上下文是在使用本地链接地址时需要指定接口。
我发现上述评论令人惊讶,因为我没想到mDNS提供链接信息,因此我没想到它会“正常工作”。我构造了一个简单的测试(如下),以查看getaddrinfo
提供的信息是否包含链接,并且发现了以下内容:
将地址和链接(例如:fe80::a:a:a:a%wlp3s0
)传递到getaddrinfo会导致sockaddr_in6,其中sin6_scope_id
设置为3
(我的wlan卡的索引) )。这表明getaddrinfo可以提供链接信息。
传递仅mDNS可解析的主机名(解析为相同的链接本地地址)会导致sockaddr_in6,其中sin6_scope_id
设置为0
,即未指定链接
此外,我已经确认,当mDNS解析链接本地地址时,依赖于getaddrinfo
来指定链接的包括SSH在内的程序将失败。但是,如果明确指定了IP地址和链接,它们将成功。
以上评论是否有误,或者我在测试此方法时是否犯了错误? mDNS可以解析为链接本地地址并指定链接吗?
作为参考,我正在Debian Buster Linux 4.19.0-5-amd647版本上进行测试
我的nsswitch.conf
包含
hosts: files mdns4_minimal [NOTFOUND=return] dns myhostname
Testcode.c:
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
int main(int arg_count, char ** args)
{
struct addrinfo hints, *servinfo, *p;
for (int i=1; i<arg_count; i++)
{
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET6; // to force IPv6
hints.ai_socktype = SOCK_STREAM;
printf("Checking %s\n", args[i]);
if (getaddrinfo(args[i], "https", &hints, &servinfo)) {
perror("getaddrinfo");
continue;
}
for(p = servinfo; p != NULL; p = p->ai_next) {
struct sockaddr_in6 * address = ((struct sockaddr_in6 *)p->ai_addr);
printf("family %d scope %d\n", address->sin6_family, address->sin6_scope_id);
}
freeaddrinfo(servinfo);
}
return 0;
}