ipv6gen is tool which generates list of IPv6 prefixes of given length from certain prefix according to RFC 3531. (A Flexible Method for Managing the Assignment of Bits of an IPv6 Address Block)
This is intended as a helper script for either constructing IPv6 addressing scheme or allocating prefixes automatically. ipv6gen is structured into functions, which can be used in proprietary scripts.
ipv6gen is written in Perl.
ipv6gen and other related scripts are GPL licensed. If you take some code out of ipv6gen and use it in your project, it would be nice if you mention that it comes from ipv6gen.
ipv6gen is now part of FreeBSD ports collection.
1.0 - fixed bug in the algorithm allocating bits from the middle when
the delta was only 1 bit
0.9 - fixed bug centermost algorithm :
at the very first round the bit following the center for the even
number of bits was not picked
- from Muggle L
0.8 - added checking of semantical correctness of input prefix
(if there are non-zero bits after prefix length boundary,
prefix is considered bad and ipv6gen exits with error.)
0.7 - added stepping between generated prefixes as input parameter
0.6 - fixed
RFC3513 terms)
non-compliancy bug (ipv6gen appended
:: after prefixes longer than 112 bits)
0.5 - fixed zero padding bug - ipv6gen incorrectly generated prefixes
not aligned to byte boundary. e.g. /64 prefixes were incorrectly
generated from /49 prefixes)
0.4 - fixed bug when generating bits for middle allocation and
delta with even number of bits
0.3 - check for format of IPv6 prefixes
0.2 - implemented allocation from the middle (centermost in
RFC3531 terms)
0.1 - only allocation from the left/right is implemented
Say we want to generate /64 prefixes for application servers from 2001:1508:1003::/48, each /64 prefix for servers of given type. If method specifier is omited, allocation from the right will be used:
worm[~/IPv6/ipv6gen]> ./ipv6gen.pl 2001:1508:1003::/48 64 2001:1508:1003:0000::/64 2001:1508:1003:0001::/64 2001:1508:1003:0002::/64 2001:1508:1003:0003::/64 ... 2001:1508:1003:FFFA::/64 2001:1508:1003:FFFB::/64 2001:1508:1003:FFFC::/64 2001:1508:1003:FFFD::/64 2001:1508:1003:FFFE::/64 2001:1508:1003:FFFF::/64
Or we just need to split /48 prefix into two prefixes:
worm[~/IPv6/ipv6gen]> ./ipv6gen.pl 2001:1508:1003::/48 49 2001:1508:1003:0000::/49 2001:1508:1003:8000::/49
This is actually example of allocation which is prone to errors. First byte after /48 boundary is 10000000 in binary which is 128 in decimal, which is 80 in hexa.
Or we need to flexibly allocate prefixes which will be used for further allocations by starting allocating bits in the middle. In this example, debugging option -d will be used to see that the bits are really allocated this way:
worm[~/IPv6/ipv6gen]> ./ipv6gen.pl -d -m 2001:1508:1003::/48 53 binary addr : 001000000000000100010101000010000001000000000011 binary addr : 001000000000000100010101000010000001000000000011(48) delta 5 zero filled : 00000 converting 001000000000000100010101000010000001000000000011 00000 2001:1508:1003:0000::/53 ----- round # 0 left: 0 central_bit: 3 middle: 00100 converting 001000000000000100010101000010000001000000000011 00100 2001:1508:1003:2000::/53 ----- round # 1 left: 1 central_bit: 2 middle: 01000 converting 001000000000000100010101000010000001000000000011 01000 2001:1508:1003:4000::/53 middle: 01100 converting 001000000000000100010101000010000001000000000011 01100 2001:1508:1003:6000::/53 ----- round # 2 left: 0 central_bit: 4 middle: 00010 converting 001000000000000100010101000010000001000000000011 00010 2001:1508:1003:1000::/53 middle: 00110 converting 001000000000000100010101000010000001000000000011 00110 2001:1508:1003:3000::/53 middle: 01010 converting 001000000000000100010101000010000001000000000011 01010 2001:1508:1003:5000::/53 middle: 01110 converting 001000000000000100010101000010000001000000000011 01110 2001:1508:1003:7000::/53 ...
ipv6gen can also leave out gaps between each two generated prefixes. This is usefull when designing allocation schemes which should be extendable. Such scheme is for example using RIPE. Currently it gives out /32 prefixes to LIRs. For each LIR, it leaves out 7 subsequent prefixes, which will be used in case LIR will need more address space. These subsequent prefixes can be aggregated up to to /29 prefix.
For example, one of the prefixes allocated by IANA to RIPE NCC is 2001:1400::/23 prefix. From this prefix, RIPE NCC further allocates /32 prefixes (in general) to LIRs. These prefixes are allocated using rightmost allocation. For each prefix, 7 subsequent prefixes are left out. So, RIPE could use ipv6gen for this task:
simstim:ipv6gen $ ./ipv6gen.pl -s 8 -r 2001:1400::/23 32 2001:1400::/32 2001:1408::/32 2001:1410::/32 2001:1418::/32 2001:1420::/32 2001:1428::/32 2001:1430::/32 2001:1438::/32 ...
Compare this output with list of prefixes allocated by RIPE to LIRs to see that this is really the scheme RIPE uses.
This script checks if one prefix is allocated from second prefix.
But check-overlap script does more than that. It does 3 kinds of checks:
If one of the checks fails, following checks are not made:
worm[~/IPv6/ipv6gen]> ./check-overlap.pl 2001:1508:1000:FFFF::/45 2001:1508:1000:FF00:/56
---- doing prefix checks first
--- checking 2001:1508:1000:FFFF::/45
error in prefix : bit 1 found beyond prefixlen boundary
binary representation of the prefix:
0010000000000001000101010000100000010000000000001111111111111111
001000000000000100010101000010000001000000000 0001111111111111111
/45 ^
--- checking 2001:1508:1000:FF00:/56 ... OK
For some prefixes it is not visible on the first sight, if they are overlapping:
worm[~/IPv6/ipv6gen]> ./check-overlap.pl 2001:1508:FFD0:40::/50 2001:1508:FFB0:C0::/51
---- doing prefix checks first
--- checking 2001:1508:FFD0:40::/50 ... OK
--- checking 2001:1508:FFB0:C0::/51 ... OK
--- checking overlap ... prefixes do NOT overlap
00100000000000010001010100001000111111111101000001 000000
00100000000000010001010100001000111111111011000011 000000
/50
... but these are not.
These are clear:
worm[~/IPv6/ipv6gen]> ./check-overlap.pl 2001:1508::/32 2001:1508:FFB0:C0::/52 ---- doing prefix checks first --- checking 2001:1508::/32 ... OK --- checking 2001:1508:FFB0:C0::/52 ... OK --- checking overlap ... OK (overlapping)