迭代两个 IPV6 地址之间的地址范围

发布于 2024-11-17 23:18:49 字数 650 浏览 3 评论 0原文

我需要某种方法来迭代两个 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 */
}

I need some way to iterate over the range of addresses between two IPv6 addresses. i.e. if the first IP is 2a03:6300:1:103:219:5bff:fe31:13e1 and the second one is 2a03:6300:1:103:219:5bff:fe31:13f4, I would like to visit the 19 addresses in that range.

With IPv4 I just do inet_aton for string representation and get htonl of s_addr in the resulting struct, but how can I do that for IPv6?

For simplify:

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 */
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

流年里的时光 2024-11-24 23:18:49

根据您的评论删除旧答案,更新以迭代一系列地址:

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 */
}

Old answer stricken per your comments, updated to iterate a range of addresses:

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 */
}
手长情犹 2024-11-24 23:18:49

这确实很棘手(我喜欢这个问题)。基本上,您需要递增并比较像这样存储的整数: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;
        }
}

比较功能要容易得多。

It's tricky indeed (I like this question). Basically you need to increment and compare integers that are stored like this: uint8_t s6_addr[16].

  • Find a cool way to convert those arrays to 128b integers and work from that
  • Define two functions inc_s6 and cmp_s6 that increment / compare such arrays

Here is an attempt at inc_s6:

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

The compare function is a lot easier.

烟柳画桥 2024-11-24 23:18:49

澄清一下:

我将其用于一些具有大量绑定 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 解决方案工作得足够好。

For clarification:

I'm using that for some proxy-server that have a lot of binded IPv6 and to delegate new IP for each request.

My increment function with some additional explanation:

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;
}

I don't show compare function because @sixlettervariables solution works good enough.

神妖 2024-11-24 23:18:49

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

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))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文