【问题标题】:expand an IPv6 address so I can print it to stdout扩展 IPv6 地址,以便我可以将其打印到标准输出
【发布时间】:2011-04-13 05:57:35
【问题描述】:

我正在使用 getifaddrs() 和 inet_ntop() 来获取系统上的 IP 地址。当系统设置为 IPv6 时,返回的地址是缩短的版本(使用 :: 表示零)。有没有办法将该地址扩展为完整地址?

这是我正在使用的代码:

struct ifaddrs *myaddrs, *ifa;
void *in_addr;
char buf[64];

if(getifaddrs(&myaddrs) != 0)
{
    perror("getifaddrs");
    exit(1);
}

for (ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
{
    if (ifa->ifa_addr == NULL)
        continue;
    if (!(ifa->ifa_flags & IFF_UP))
        continue;

    switch (ifa->ifa_addr->sa_family)
    {
        case AF_INET:
        {
            struct sockaddr_in *s4 = (struct sockaddr_in *)ifa->ifa_addr;
            in_addr = &s4->sin_addr;
            break;
        }

        case AF_INET6:
        {
            struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)ifa->ifa_addr;
            in_addr = &s6->sin6_addr;
            break;
        }

        default:
            continue;
    }

    if (!inet_ntop(ifa->ifa_addr->sa_family, in_addr, buf, sizeof(buf)))
    {
        printf("%s: inet_ntop failed!\n", ifa->ifa_name);
    }
    else
    {
        printf("IP address: %s\n", buf);
    }
}

freeifaddrs(myaddrs);

非常感谢代码。

编辑:
既然这显然很难理解,我给你举个例子:

如果我得到 abcd:12::3,我需要将其扩展为 abcd:0012:0000:0000:0000:0000:0000:0003
原因?因为这是要求的一部分。就这么简单。

【问题讨论】:

  • 缩短的版本是一个有效的 ipv6 地址 - 那么为什么要扩展它呢?
  • @Jessica:您将其存储为 128 位整数,对吗?因为将其存储为文本表示有点毫无意义 - IPv6 地址可以通过多种方式表示,这正是因为 :: 缩短的语法。
  • 好的,我会让你更容易。我需要将它存储在一个字符串中。 char*、char[] 或其他。我只需要存储地址。仅此而已,有什么难理解的?我问了一个非常具体的问题。我不关心 SQL 数据库。
  • 您的要求有误。请参阅 RFC 5952“IPv6 地址文本表示建议”
  • @bortzmeyer:不。不符合要求的建议是错误的。如果排序顺序(数据库!)很重要,那么 RFC 5952 就是一团糟。

标签: c linux ipv6


【解决方案1】:
void ipv6_to_str_unexpanded(char *str, const struct in6_addr *addr) {
   sprintf(str, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
                 (int)addr->s6_addr[0], (int)addr->s6_addr[1],
                 (int)addr->s6_addr[2], (int)addr->s6_addr[3],
                 (int)addr->s6_addr[4], (int)addr->s6_addr[5],
                 (int)addr->s6_addr[6], (int)addr->s6_addr[7],
                 (int)addr->s6_addr[8], (int)addr->s6_addr[9],
                 (int)addr->s6_addr[10], (int)addr->s6_addr[11],
                 (int)addr->s6_addr[12], (int)addr->s6_addr[13],
                 (int)addr->s6_addr[14], (int)addr->s6_addr[15]);
}

【讨论】:

  • 太棒了。第一个 %02x%02: 应该是 %02x%02x: 顺便说一句
【解决方案2】:
            #include<stdio.h>
            #include <netinet/in.h>
            #include <arpa/inet.h>

            struct in6_addrr
            {
                unsigned char addr[16];
            };

            void ipv6_expander(const struct in6_addr * addr)
            {
                char str[40];
                sprintf(str,"%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
                (int)addr->s6_addr[0], (int)addr->s6_addr[1],
                (int)addr->s6_addr[2], (int)addr->s6_addr[3],
                (int)addr->s6_addr[4], (int)addr->s6_addr[5],
                (int)addr->s6_addr[6], (int)addr->s6_addr[7],
                (int)addr->s6_addr[8], (int)addr->s6_addr[9],
                (int)addr->s6_addr[10], (int)addr->s6_addr[11],
                (int)addr->s6_addr[12], (int)addr->s6_addr[13],
                (int)addr->s6_addr[14], (int)addr->s6_addr[15]);
                 printf("\nExpanded ipv6 Addr %s\n",str);
            }

            int main(int argc,char *argv[])
            {
                struct in6_addrr ipv6;
                printf("\nGiven IPv6 Addr %s\n",argv[1]);
                if(inet_pton(AF_INET6,argv[1],&ipv6.addr))
                {
                    ipv6_expander(&ipv6.addr);
                }
                else
                {
                    printf("\n error\n");
                }
                return;
            }

【讨论】:

  • 这里为什么需要struct。我们不能只传递无符号字符数组吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-07-11
  • 2013-05-01
  • 1970-01-01
  • 2013-09-01
  • 2011-01-12
相关资源
最近更新 更多