В более раннем обсуждении темы локальных адресов 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
, т.е. ссылка не была указана
Далее я подтвердил, что программы, в том числе SSH, использующие getaddrinfo
для указания ссылки, не будут работать, когда mDNS разрешит локальный адрес канала. Но они будут успешными, если IP-адрес и ссылка указаны явно.
Был ли приведенный выше комментарий неправильным или я ошибся, когда я проверял это? Может ли mDNS разрешить локальный адрес и указать ссылку?
Для справки я тестирую на Debian Buster Linux версии 4.19.0-5-amd647
My 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;
}