Linux中是否有API将IPv6端点地址(如ff02::d5%eth0
)解析为sockaddr_in6
结构,或者我必须手动解析它并在作用域ID上调用if_nametoindex
?
我试了getaddrinfo
,inet_pton
,都没有用。
这是我的测试程序
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <iostream>
int main(int argc, char** argv)
{
struct addrinfo hints = {
.ai_flags = AI_PASSIVE | AI_ALL,
.ai_family = AF_INET6,
.ai_socktype = SOCK_DGRAM,
};
struct addrinfo *res = nullptr;
if (argc < 2) {
fprintf(stderr, "Usage: %s <addr>\n", argv[0]);
return 1;
}
int rc = getaddrinfo(argv[1], "5683", &hints, &res);
if (rc) {
std::cout << "rc = " << rc << ", res = " << (void*)res << std::endl;
return 1;
}
if (res) {
char buf[128];
sockaddr_in *sin = (sockaddr_in *)res->ai_addr;
switch (sin->sin_family) {
case AF_INET:
std::cout << inet_ntop(sin->sin_family, &sin->sin_addr, buf, sizeof(buf)) << std::endl;
break;
case AF_INET6:
std::cout << inet_ntop(sin->sin_family, &((sockaddr_in6 *)sin)->sin6_addr, buf, sizeof(buf)) << std::endl;
break;
}
freeaddrinfo(res);
}
}
它可以处理1.1.1.1
、::1
等参数,但在提供ff02::d5%eth0
、::1%lo
、[::1%lo]
等作用域ID时,EAI_NONAME
会失败。
1条答案
按热度按时间svmlkihl1#
作用域ID(正确的名称是Zone ID)目前仅用于链路本地地址(
fe80::/64
)。参见 * RFC 6874, Representing IPv6 Zone Identifiers in Address Literals and Uniform Resource Identifiers:为了限制这种风险,实现必须不允许使用这种格式,除非是明确定义的用法,例如发送到前缀为fe 80::/10的链路本地地址。 在撰写本文时,这是已知的唯一定义明确的用法。