| 1 | #!/usr/bin/php |
| 2 | <?php |
| 3 | |
| 4 | /** |
| 5 | * (c) 2020 - Tomas Mudrunka <harvie@github> |
| 6 | * |
| 7 | * Given IPv6 address and prefix creates array of * wildcard suffixed |
| 8 | * addresses to be used for as reverse DNS records |
| 9 | */ |
| 10 | function ipv6_prefix2wildcards($address, $prefix) { |
| 11 | //Special case of /0 prefix |
| 12 | if($prefix == 0) return ['*']; |
| 13 | |
| 14 | //Parse ip and prefix |
| 15 | echo("IPv6 prefix: ".$address."/".$prefix."\n"); |
| 16 | $addr = inet_pton ($address); |
| 17 | $pref = $prefix; |
| 18 | $a = gmp_import($addr); |
| 19 | |
| 20 | //Separate maskable octets |
| 21 | $pref_hex = ceil($pref / 4); //Number of prefix octets |
| 22 | $pref_bin = $pref_hex*4; //Number of prefix octets in bits |
| 23 | $pref_rem = $pref_bin - $pref; //Remainder of prefix |
| 24 | echo("Rounding prefix: ".$pref_bin."-".$pref_rem."\n"); |
| 25 | |
| 26 | $a = gmp_div_q($a, gmp_pow(2,128-$prefix)); //Truncate to just prefix |
| 27 | $a = gmp_mul($a, gmp_pow(2,$pref_rem)); //Fill remaining bits in last wildcard octet with zeros |
| 28 | |
| 29 | //Generate wildcards |
| 30 | $wildcards = []; |
| 31 | for($i = 0; $i < (2**$pref_rem) ; $i++) { |
| 32 | //echo("ADDED: ".$i." = ".decbin($i)."\n"); |
| 33 | $ap = gmp_or($a, gmp_init($i)); |
| 34 | $w = gmp_strval($ap, 16); |
| 35 | $w = str_repeat('0', $pref_hex-strlen($w)).$w; |
| 36 | if(strlen($w) < 32) $w.='*'; |
| 37 | $wildcards[] = $w; |
| 38 | } |
| 39 | |
| 40 | return $wildcards; |
| 41 | } |
| 42 | |
| 43 | function ipv6_string2rev($str) { |
| 44 | return implode('.',str_split(strrev($str))); |
| 45 | } |
| 46 | |
| 47 | if(isset($argv[2])) { |
| 48 | $wcs = ipv6_prefix2wildcards($argv[1],$argv[2]); |
| 49 | } else { |
| 50 | $wcs = ipv6_prefix2wildcards('2001:1:3::10', 67); |
| 51 | } |
| 52 | |
| 53 | echo("\n"); |
| 54 | foreach($wcs as $w) { |
| 55 | echo($w."\n"); |
| 56 | } |
| 57 | |
| 58 | echo("\n"); |
| 59 | foreach($wcs as $w) { |
| 60 | echo(ipv6_string2rev($w)."\n"); |
| 61 | } |