linux 如何解析包含作用域ID的IPv6端点地址

8yparm6h  于 2023-06-29  发布在  Linux
关注(0)|答案(1)|浏览(145)

Linux中是否有API将IPv6端点地址(如ff02::d5%eth0)解析为sockaddr_in6结构,或者我必须手动解析它并在作用域ID上调用if_nametoindex
我试了getaddrinfoinet_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会失败。

svmlkihl

svmlkihl1#

作用域ID(正确的名称是Zone ID)目前仅用于链路本地地址(fe80::/64)。参见 * RFC 6874, Representing IPv6 Zone Identifiers in Address Literals and Uniform Resource Identifiers
为了限制这种风险,实现必须不允许使用这种格式,除非是明确定义的用法,例如发送到前缀为fe 80::/10的链路本地地址。
在撰写本文时,这是已知的唯一定义明确的用法。

相关问题