Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>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.</p> <p><strong>Edit:</strong> 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).</p> <pre class="lang-c prettyprint-override"><code>#include &lt;arpa/inet.h&gt; #include &lt;string.h&gt; #include &lt;stdlib.h&gt; #include &lt;errno.h&gt; #include &lt;stdio.h&gt; #include &lt;ctype.h&gt; /* * Syntax: ./ipv6_list &lt;ip&gt;/&lt;cidr-prefix&gt; */ 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 &lt;IP&gt; &amp; &lt;mask&gt; != &lt;start IP&gt; */ 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, &amp;prefix_remaining, 10); if(errno == ERANGE || prefix_test &lt; 0 || prefix_test &gt; 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 &lt; 16; i++) { if(prefix == 0) break; mask_check_octet = i; if(prefix &lt; 8) { mask[i] = ~((1 &lt;&lt; (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 &lt; 16; i++) { start[i] &amp;= mask[i]; address[i] = start[i]; } /* Iterate */ while((address[mask_check_octet] &amp; 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\n", address_str); /* Add one to the address */ for(i = 15; i &gt;= 0; i--) { if(address[i] != UINT8_MAX) break; } address[i]++; for(i++; i &lt; 16; i++) address[i] = 0; }; return 0; } </code></pre> <p>You can use standard shell commands to limit its output (or just modify the <code>while</code> loop):</p> <pre class="lang-none prettyprint-override"><code>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 </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload