【问题标题】:How to resolve IPv4 address from IPv4 mapped IPv6 address?如何从 IPv4 映射的 IPv6 地址解析 IPv4 地址?
【发布时间】:2012-12-25 17:02:33
【问题描述】:

如何从 IPv4 映射的 IPv6 地址中获取 IPv4 地址?

例如,我有一个 IP 地址::FFFF:129.144.52.38。从中,我需要提取129.144.52.38。有没有用于此目的的 API?

我可以使用以下函数识别 IPv6 或 IPv4 地址族

int getaddrfamily(const char *addr)
{
    struct addrinfo hint, *info =0;
    memset(&hint, 0, sizeof(hint));
    hint.ai_family = AF_UNSPEC;
    // Uncomment this to disable DNS lookup
    //hint.ai_flags = AI_NUMERICHOST;
    int ret = getaddrinfo(addr, 0, &hint, &info);
    if (ret)
        return -1;
    int result = info->ai_family;
    freeaddrinfo(info);
    return result;
}

如果我提供一个 IPv4 映射的 IPv6 地址,那么如何识别它是否是一个映射地址?是否有任何套接字 API 可以从映射的 IPv6 地址中提取 IPv4?

【问题讨论】:

标签: c++ c sockets networking network-programming


【解决方案1】:

试试这样的:

#ifndef IN6_IS_ADDR_V4MAPPED
#define IN6_IS_ADDR_V4MAPPED(a) \
       ((((a)->s6_words[0]) == 0) && \
        (((a)->s6_words[1]) == 0) && \
        (((a)->s6_words[2]) == 0) && \
        (((a)->s6_words[3]) == 0) && \
        (((a)->s6_words[4]) == 0) && \
        (((a)->s6_words[5]) == 0xFFFF))
#endif

unsigned long getIPv4addr(const char *addr)
{
    struct addrinfo hint, *info = 0;
    unsigned long result = INADDR_NONE;
    memset(&hint, 0, sizeof(hint));
    hint.ai_family = AF_UNSPEC;
    // Uncomment this to disable DNS lookup
    //hint.ai_flags = AI_NUMERICHOST;
    if (getaddrinfo(addr, 0, &hint, &info) == 0)
    {
        switch (info->ai_family)
        {
            case AF_INET:
            {
                struct sockaddr_in *addr = (struct sockaddr_in*)(info->ai_addr);
                result = addr->sin_addr.s_addr;
                break;
            }

            case AF_INET6:
            {
                struct sockaddr_in6 *addr = (struct sockaddr_in6*)(info->ai_addr);
                if (IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr))
                    result = ((in_addr*)(addr->sin6_addr.s6_addr+12))->s_addr;
                break;
            }
        }
        freeaddrinfo(info);
    }
    return result;
}

【讨论】:

  • 在 IN6_IS_ADDR_V4MAPPED 的实现中存在一些拼写错误(s6_words 带有一个额外的“s”)。每个 s6_word 应该是 16 位宽。
  • @kingflight 已修复,谢谢
【解决方案2】:

您只需从 IPv6 地址中提取最后四个字节,将它们组合成一个 32 位数字,您就拥有了您的 IPv4 地址。

当然你需要先检查它是否真的是一个 IPv4 映射的地址。

【讨论】:

  • 我不知道为什么这被否决了,它是 100% 正确且基本的 C。
  • @MahmoudAl-Qudsi:因为它没有提到检查 IPv6 的前 10 个字节是否全部为 0,然后检查以下 2 个字节是否全部为 ff。只有这样,才能假设将 IPv4 映射到 IPv6 空间并将低 4 个字节提取为 IPv4。否则他建议只是简单地截断 IPv6 地址的高 12 个字节,这是没有意义的。
  • @ahmd0 不过,问题不在于如何识别 IPv4 映射的 IPv6 地址。它是“ 给定这样一个地址,你如何从中获取 IPv4。
  • @MahmoudAl-Qudsi:您无法从任意 IPv6 获取 IPv4。我上面描述的是一种特殊情况。
猜你喜欢
  • 1970-01-01
  • 2013-09-18
  • 1970-01-01
  • 2015-01-17
  • 2013-07-02
  • 2015-04-01
  • 2012-04-11
  • 2012-06-29
  • 2011-02-16
相关资源
最近更新 更多