2011-06-28 61 views
3

我需要一些方法來迭代兩個IPv6地址之間的地址範圍。即如果第一個IP是2a03:6300:1:103:219:5bff:fe31:13e1而第二個是2a03:6300:1:103:219:5bff:fe31:13f4,我想訪問該範圍內的19個地址。迭代兩個IPV6地址之間的地址範圍

對於IPv4,我只是對字符串表示做inet_aton,並在結果結構中獲取htonls_addr,但是如何才能爲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 */ 
} 
+0

在你的問題中,你有兩個問題,它們顯得無關緊要,我無法準確理解你想要做什麼。 – user7116

+0

只有一個問題:如何爲兩個ipv6地址之間的循環迭代? – AmiGO

+0

正如你想將's'和'e'存儲在你可以循環的東西中?或者你想比較兩個地址? – user7116

回答

4

老答案按你的意見失措,更新迭代一個地址範圍:

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

不,你不明白,我需要在範圍內的所有地址(即從第一個ip到第二個)之間迭代 – AmiGO

+0

@AmiGO:根據你的意見更新。 – user7116

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

比較功能要容易得多。

+0

非常感謝,我會試試這個 – AmiGO

+1

由於'uint8_t'中的算術是以256爲模執行的,所以您可以簡單地執行if (++ addr [i])break;'作爲循環體。 – caf

+0

@caf對。我忘記了無符號整數溢出是定義的行爲。 – cnicutar

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解決方案的工作不夠好。