在两个IPv6地址之间迭代地址范围

3
我需要一种方法来遍历两个IPv6地址之间的地址范围。即,如果第一个IP是2a03:6300:1:103:219:5bff:fe31:13e1,第二个IP是2a03:6300:1:103:219:5bff:fe31:13f4,我想访问该范围内的19个地址。
对于IPv4,我只需使用字符串表示的inet_aton并获取结果结构体中s_addrhtonl即可,但是如何处理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 */
}

你的问题中有两个问题,它们似乎没有关联,我很难理解你想要做什么。 - user7116
只有一个问题:如何在两个IPv6地址之间进行“for”循环迭代? - AmiGO
您想将se存储在可循环的东西中吗?还是您想比较这两个地址? - user7116
@sixlettervariables:是的,我想将se都存储在一个可以循环的东西中。 - AmiGO
只是好奇你用这个做什么。根据输入,这个循环可能会运行很长时间。;-) - mpontillo
@Mike:针对一个具有许多IPv6绑定IP的搜索引擎解析代理服务器。 - AmiGO
4个回答

5

根据您的评论,旧答案已被删除,更新为迭代地址范围:

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到第二个IP)。 - AmiGO

3

这确实有些棘手(我喜欢这个问题)。基本上,您需要增加并比较存储为 uint8_t s6_addr[16] 的整数。

  • 找到一种将这些数组转换为128位整数并从中进行操作的酷方法
  • 定义两个函数 inc_s6cmp_s6,用于增加/比较此类数组

这里是一个关于 inc_s6 的尝试:

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

比较函数要简单得多。

1
由于在 uint8_t 中进行算术运算时会对 256 取模,因此您可以将 if (++addr[i]) break; 作为循环体。 - caf
@caf 对,我忘记了无符号整数上溢是被定义为行为的。 - cnicutar

0

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))

您的回答可以通过提供更多的支持性信息来改进。请[编辑]以添加更多详细信息,例如引用或文档,以便他人可以确认您的回答是正确的。您可以在帮助中心找到有关如何编写良好答案的更多信息。 - Community

0

澄清一下:

我正在使用它作为一些代理服务器的工具,这些服务器有很多绑定的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的解决方案已经足够好了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接