Итерация диапазона адресов между двумя адресами IPV6 - PullRequest
3 голосов
/ 28 июня 2011

Мне нужен какой-то способ перебора диапазона адресов между двумя адресами IPv6.т. е. если первый IP-адрес 2a03:6300:1:103:219:5bff:fe31:13e1, а второй * 2a03:6300:1:103:219:5bff:fe31:13f4, я хотел бы посетить 19 адресов в этом диапазоне.

С IPv4 я просто делаю inet_aton для представления строки и получаю htonl из s_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 */
}

Ответы [ 3 ]

4 голосов
/ 29 июня 2011

Старый ответ поражен вашими комментариями, обновлен для повторения диапазона адресов:

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 */
}
2 голосов
/ 28 июня 2011

Это действительно сложно (мне нравится этот вопрос).В основном вам нужно увеличивать и сравнивать целые числа, которые хранятся следующим образом: uint8_t s6_addr[16].

  • Найдите классный способ конвертировать эти массивы в 128b целых чисел и работать от этогофункции inc_s6 и cmp_s6, которые увеличивают / сравнивают такие массивы

Вот попытка inc_s6:

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

Функция сравнения намного проще.

0 голосов
/ 10 мая 2013

Для пояснения:

Я использую это для некоторых прокси-серверов с большим количеством привязанного 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 работает достаточно хорошо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...