3

在之前关于 IPv6 链路本地地址主题的讨论中,我看到了一条评论,其中指出:

有些人会争辩说,对于任何类型的地址,都不应该使用地址而不是主机名。使用 mDNS 映射到链接本地地址可以正常工作。

讨论的上下文是在使用链接本地地址时需要指定接口。

我发现上面的评论令人惊讶,因为我没想到 mDNS 会提供链接信息,因此我没想到它会“正常工作”。我构建了一个简单的测试(如下),以查看提供的信息是否getaddrinfo包含链接,我发现以下内容:

  • 将地址和链接(例如:)传递fe80::a:a:a:a%wlp3s0给 getaddrinfo 会导致sockaddr_in6设置sin6_scope_id3(我的 wlan 卡的索引)。这表明 getaddrinfo 可以提供链接信息。

  • 传递一个只能由 mDNS 解析的主机名(它解析到相同的链接本地地址)导致 sockaddr_in6sin6_scope_id设置为0,即没有指定链接

  • 此外,我已经确认,当 mDNS 解析链接本地地址时,包括 SSH 在内的依赖getaddrinfo指定链接的程序将失败。但如果明确指定 IP 地址和链接,它们将成功。


上面的评论是错误的,还是我在测试的方式上犯了错误?mDNS 可以解析为链接本地地址并指定链接吗?

作为参考,我正在 Debian Buster Linux 版本 4.19.0-5-amd647 上进行测试

我的nsswitch.conf包含

hosts:          files mdns4_minimal [NOTFOUND=return] dns myhostname

测试代码.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;
}
4

0 回答 0