doulao3905 2013-02-08 19:05
浏览 162
已采纳

从IPv6字符串(php)增加单个IP

What is a simple, elegant way to list the first x number of IPv6 IPs from a IPv6 string.

For example,

listIPs("2600:f333:10:c000::0", 4)

echos

  • 2600:f333:10:c000::1
  • 2600:f333:10:c000::2
  • 2600:f333:10:c000::3
  • 2600:f333:10:c000::4

Here's a sample of code that may have worked for IPv4, as it converted to int:

$input = "2600:f333:10:c000::/51";
$max = 4;

list($block, $cidr) = explode("/", $input);

$first = inet_pton( $block );
echo inet_ntop($first) . "
";

for ($i = 1; $i < $max; $i++) {
   //todo: die if it has exceeded block size based on $cidr
   echo inet_ntop($first + $i) . "
"; //doesn't work, packed binary?
}
  • 写回答

2条回答 默认 最新

  • drsb77336 2013-02-08 22:57
    关注

    Here's an example program written in C (since I don't know C++). It's fairly fast, but I'm not really happy with it. Maybe someone can help me improve it.

    Edit: Obviously, I wrote this before it was turned into a PHP-only question. Turning this into PHP is left as an exercise to the reader (ew).

    #include <arpa/inet.h>
    #include <string.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <stdio.h>
    #include <ctype.h>
    
    /*
     * Syntax: ./ipv6_list <ip>/<cidr-prefix>
     */
    int main(int argc, char **argv) {
        uint8_t start[16];
        uint8_t address[16];
        uint8_t mask[16] = { 0 };
    
        uint8_t prefix = 128;
        char *prefix_location;
    
        int i;
    
        /* This is the octet that, when changed, will result in <IP> & <mask> != <start IP> */
        int mask_check_octet = 0;
    
        if(argc != 2)
            return 1;
    
        /* Find prefix */
        if((prefix_location = strstr(argv[1], "/")) != NULL) {
            char *prefix_search = prefix_location + 1;
            char *prefix_remaining;
            long prefix_test;
    
            if(!isdigit(*prefix_search))
                return 2;
    
            errno = 0;
            prefix_test = strtol(prefix_search, &prefix_remaining, 10);
            if(errno == ERANGE || prefix_test < 0 || prefix_test > 128 || strcmp(prefix_remaining, "") != 0)
                return 2;
    
            prefix = (uint8_t)prefix_test;
            *prefix_location = '\0'; /* So we can just pass argv[1] into inet_pton(3) */
        }
    
        /* Convert prefix into mask */
        for(i = 0; i < 16; i++) {
            if(prefix == 0)
                break;
    
            mask_check_octet = i;
            if(prefix < 8) {
                mask[i] = ~((1 << (8 - prefix)) - 1);
                break;
            }
            else
                mask[i] = UINT8_MAX;
    
            prefix -= 8;
        }
    
        /* Find address */
        if(inet_pton(AF_INET6, argv[1], start) != 1)
            return 3;
    
        /* Start at the beginning of the network */
        for(i = 0; i < 16; i++) {
            start[i] &= mask[i];
            address[i] = start[i];
        }
    
        /* Iterate */
        while((address[mask_check_octet] & mask[mask_check_octet]) == start[mask_check_octet]) {
            char address_str[INET6_ADDRSTRLEN];
            inet_ntop(AF_INET6, address, address_str, sizeof(address_str));
            printf("%s
    ", address_str);
    
            /* Add one to the address */
            for(i = 15; i >= 0; i--) {
                if(address[i] != UINT8_MAX)
                    break;
            }
            address[i]++;
            for(i++; i < 16; i++)
                address[i] = 0;
        };
    
        return 0;
    }
    

    You can use standard shell commands to limit its output (or just modify the while loop):

    nfontes@brioche:~$ ./ipv6_list '2607:fc50:0:d00::0/106' | head -n 200
    2607:fc50:0:d00::
    2607:fc50:0:d00::1
    2607:fc50:0:d00::2
    2607:fc50:0:d00::3
    2607:fc50:0:d00::4
    2607:fc50:0:d00::5
    2607:fc50:0:d00::6
    2607:fc50:0:d00::7
    2607:fc50:0:d00::8
    2607:fc50:0:d00::9
    2607:fc50:0:d00::a
    2607:fc50:0:d00::b
    2607:fc50:0:d00::c
    2607:fc50:0:d00::d
    2607:fc50:0:d00::e
    [...]
    2607:fc50:0:d00::c0
    2607:fc50:0:d00::c1
    2607:fc50:0:d00::c2
    2607:fc50:0:d00::c3
    2607:fc50:0:d00::c4
    2607:fc50:0:d00::c5
    2607:fc50:0:d00::c6
    2607:fc50:0:d00::c7
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 outlook无法配置成功
  • ¥30 这是哪个作者做的宝宝起名网站
  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题