-
It could be 2001:0000:85a3:0042:1000::7334. It could also be 2001:0:85a3:42:1000::7334.
-
Well it’d be simpler just to realize that every character is 4 bits (0000 through 1111, or 0 through F), and so 80 bits = 20 characters, and 48 would be 12 characters. But that’s helpful only when the network bits are a multiple of 4.
You’ll find it a lot easier to do the maths on smaller groups than the whole thing at once.
So if i were trying to do it programmatically? (off the top of my head)
Start: 2c0f:ffd8:1::/48
Slice off the / and find the value after it. (48). This is NetworkBits.
48/4 = 12, /4 (because there are 4 characters per ‘set’) = 3. I need 3 sets of values in the first half of my string to determine the range
My string is 2c0f:ffd8:1:: I dont see 39 (32 meaningful and 7 colons) characters here, so something’s been shortcutted.
Unshorthand function:
If :: exists in the string:
How many components are missing? Count the number of colons, and subtract 1. There are 3. That means the :: is representing a range of 5 sets of 0’s. Replace the :: with :0000:0000:0000:0000:0000:.
If the beginning or ending of my string are colons, remove them.
EndIf.
My string is now 2c0f:ffd8:1:0000:0000:0000:0000:0000 . I still dont see 39 characters, something’s still missing.
Explode the string on :. Foreach section, if the character count is less than 4, zero-pad the string.
My string is now 2c0f:ffd8:0001:0000:0000:0000:0000:0000. Hey, that looks like a properly formed IPv6 address I can work with.
End Function
(At this point i stopped doing pseudocode because i tried to code it myself and it took… exceedingly longer than it should have to wrap my head around the functions involved. The following is the result of my scratchings. There is PROBABLY a better way to do this.
//This Code assumes the existance of $NetworkBits and $string.
$StartResult = array();
$EndResult = array();
foreach(explode(':',$string) AS $char) {
$InversionMask = bindec(strrev(str_pad(decbin(pow(2,min($NetworkBits,16))-1),16,"0",STR_PAD_LEFT)));
$EndMask = bindec(substr(decbin(~$InversionMask),-16));
$StartResult[] = "".str_pad(dechex(hexdec($char) & $InversionMask),4,"0",STR_PAD_LEFT);
$EndResult[] = "".str_pad(dechex(hexdec($char) | $EndMask),4,"0",STR_PAD_LEFT);
$NetworkBits = max(0,$NetworkBits - 16);
}
echo implode(":",$StartResult)."<br />".implode(":",$EndResult);
For $NetworkBits = 48;
$string = “2c0f:ffd8:0001:0000:0000:0000:0000:0000”;
2c0f:ffd8:0001:0000:0000:0000:0000:0000
2c0f:ffd8:0001:ffff:ffff:ffff:ffff:ffff
For
$NetworkBits = 33;
$string = “2c0f:ffd8:8000:0000:0000:0000:0000:0000”;
2c0f:ffd8:8000:0000:0000:0000:0000:0000
2c0f:ffd8:ffff:ffff:ffff:ffff:ffff:ffff
Of more interesting (maths wise, so you can see it’s not just ‘0 or f’) note would be
For
$NetworkBits = 33;
$string = “2c0f:ffd8:1000:0000:0000:0000:0000:0000”;
2c0f:ffd8:0000:0000:0000:0000:0000:0000
2c0f:ffd8:7fff:ffff:ffff:ffff:ffff:ffff
(Though note should be made here that this string does not comply with CIDR, as the range would be represented as 2c0f:ffd8::\33, and not 2c04:ffd8:1::\33. The CIDR entry, if valid, should equal the Start of range.)