【问题标题】:Iterate range of addresses between two IPV6 addresses迭代两个 IPV6 地址之间的地址范围
【发布时间】:2011-06-28 19:36:12
【问题描述】:

我需要一些方法来遍历两个 IPv6 地址之间的地址范围。即如果第一个IP是2a03:6300:1:103:219:5bff:fe31:13e1,第二个IP是2a03:6300:1:103:219:5bff:fe31:13f4,我想访问该范围内的19个地址。

对于 IPv4,我只需使用 inet_aton 来表示字符串,并在结果结构中获得 s_addr 中的 htonl,但是对于 IPv6,我该如何做到这一点?

为了简化:

struct in6_addr sn,en;
long i;

s="2a03:6300:1:103:219:5bff:fe31:13e1";
e="2a03:6300:1:103:219:5bff:fe31:13f4";

inet_pton(AF_INET6,s,&sn);
inet_pton(AF_INET6,e,&en);

[..]

for (i = _first_ipv6_representation; i<=_second_ipv6_representation; i++){
    /* stuck here */
}

【问题讨论】:

  • 您的问题中有两个问题,它们看起来不相关,我无法准确理解您想要做什么。
  • 只有一个问题:如何在 2 个 ipv6 地址之间进行“for”循环迭代?
  • 您想将se 都存储在可以循环的东西中吗?还是要比较两个地址?
  • @sixlettervariables: 是的,我想将se 存储在我可以循环的东西中
  • 只是好奇你用这个做什么。此循环可能会运行 长时间,具体取决于输入。 ;-)

标签: c iteration ipv6


【解决方案1】:

每个 cmets 的旧答案,已更新以迭代一系列地址:

char output[64];
struct in6_addr sn, en;
int octet;

s="2a03:6300:1:103:219:5bff:fe31:13e1";
e="2a03:6300:1:103:219:5bff:fe31:13f4";

inet_pton(AF_INET6,s,&sn);
inet_pton(AF_INET6,e,&en);

for ( ; ; ) {
    /* print the address */
    if (!inet_ntop(AF_INET6, &sn, output, sizeof(output))) {
        perror("inet_ntop");
        break;
    }

    printf("%s\n", output);

    /* break if we hit the last address or (sn > en) */
    if (memcmp(sn.s6_addr, en.s6_addr, 16) >= 0) break;

    /* increment sn, and move towards en */
    for (octet = 15; octet >= 0; --octet) {
        if (sn.s6_addr[octet] < 255) {
            sn.s6_addr[octet]++;
            break;
        } else sn.s6_addr[octet] = 0;
    }

    if (octet < 0) break; /* top of logical address range */
}

【讨论】:

  • 不,你不明白,我需要在范围内的所有地址之间进行迭代(即从第一个 ip 到第二个)
【解决方案2】:

确实很棘手(我喜欢这个问题)。基本上你需要递增和比较这样存储的整数:uint8_t s6_addr[16]

  • 找到一种很酷的方法将这些数组转换为 128b 整数并以此为基础工作
  • 定义两个函数 inc_s6cmp_s6 递增/比较此类数组

这是inc_s6的尝试:

void inc_s6(uint8_t *addr)
{
        int i = 0;
        for (i = 15; i >= 0; i--) {
                if (++addr[i])
                    break;
        }
}

比较功能要容易得多。

【讨论】:

  • 非常感谢,我会试试这个
  • 由于 uint8_t 中的算术是以 256 为模执行的,因此您可以简单地将 if (++addr[i]) break; 作为循环体。
  • @caf 对。我忘记了无符号整数溢出是定义的行为。
【解决方案3】:

澄清:

我将它用于一些具有大量绑定 IPv6 的代理服务器,并为每个请求委派新 IP。

我的增量函数有一些额外的解释:

const char *s="2a03:6300:2:200:0:0:0:1"; // first ip in range

struct in6_addr sn;

inet_pton(AF_INET6,s,&sn);

static struct in6_addr cn = sn; //current ip in6_addr struct

unsigned int skipBits=126;
unsigned __int128 icn,skip; // works only with gcc

if (skipBits!=0){ // now we need to skip netmask bits to get next ip
    skip=pow(2,(128-skipBits))-2;
    u_int32_t swap;
    swap=ntohl(cn.s6_addr32[3]);
    cn.s6_addr32[3]=ntohl(cn.s6_addr32[0]);
    cn.s6_addr32[0]=swap;
    swap=ntohl(cn.s6_addr32[2]);
    cn.s6_addr32[2]=ntohl(cn.s6_addr32[1]);
    cn.s6_addr32[1]=swap;

    memcpy(&icn,&cn,sizeof icn);
    // increment, works very fast because gcc will compile it into sse2 intrinsic (double int64 operations)
    icn+=skip;
    memcpy(&cn,&icn,sizeof icn);

    swap=ntohl(cn.s6_addr32[3]);
    cn.s6_addr32[3]=ntohl(cn.s6_addr32[0]);
    cn.s6_addr32[0]=swap;
    swap=ntohl(cn.s6_addr32[2]);
    cn.s6_addr32[2]=ntohl(cn.s6_addr32[1]);
    cn.s6_addr32[1]=swap;
}

我没有显示比较功能,因为@sixlettervariables 解决方案足够好。

【讨论】:

    【解决方案4】:

    Python3:

    import ipaddress
    st_add=int(ips.ip_address(st_add).packed.hex(),16)
    end_add=int(ips.ip_address(end_add).packed.hex(),16)
    Ips=set(ips.ip_address(ip).compressed for ip in range(st_add,end_add))
    

    【讨论】:

    • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
    猜你喜欢
    • 1970-01-01
    • 2019-07-13
    • 2010-10-20
    • 1970-01-01
    • 2021-12-24
    • 2019-12-06
    • 1970-01-01
    • 1970-01-01
    • 2010-12-19
    相关资源
    最近更新 更多