How does PHP implement ip2cidr (generate multiple cidr)? are there any functions that generate multiple cidr, for example, 1.120.0.0 1.159.255.255 to generate 1.120.0.0/13 1.128.0.0/11?
Reply to discussion (solution)
Function ip2cidr ($ ip_start, $ ip_end ){
If (long2ip (ip2long ($ ip_start ))! = $ Ip_start or long2ip (ip2long ($ ip_end ))! = $ Ip_end) return NULL;
$ Ipl_start = (int) ip2long ($ ip_start );
$ Ipl_end = (int) ip2long ($ ip_end );
If ($ ipl_start> 0 & $ ipl_end <0) $ delta = ($ ipl_end + 4294967296)-$ ipl_start;
Else $ delta = $ ipl_end-$ ipl_start;
$ Netmask = str_pad (decbin ($ delta), 32, "0", "STR_PAD_LEFT ");
If (ip2long ($ ip_start) = 0 & substr_count ($ netmask, "1") = 32) return "0.0.0.0/0 ";
If ($ delta <0 or ($ delta> 0 & $ delta % 2 = 0) return NULL;
For ($ mask = 0; $ mask <32; $ mask ++) if ($ netmask [$ mask] = 1) break;
If (substr_count ($ netmask, "0 ")! = $ Mask) return NULL;
Return "$ ip_start/$ mask ";
} This function cannot generate multiple cidr instances.
echo ip2cidr('1.120.0.0', '1.127.255.255'); //1.120.0.0/13function ip2cidr($ip_start,$ip_end) { if(long2ip(ip2long($ip_start))!=$ip_start or long2ip(ip2long($ip_end))!=$ip_end) return NULL; $ipl_start = ip2long($ip_start); $ipl_end = ip2long($ip_end); if($ipl_start>0 && $ipl_end<0) $delta = ($ipl_end + 4294967296) - $ipl_start; else $delta = $ipl_end - $ipl_start; $netmask = str_pad(decbin($delta), 32, "0", STR_PAD_LEFT); if(ip2long($ip_start)==0 && substr_count($netmask,"1")==32) return "0.0.0.0/0"; if($delta<0 or ($delta>0 && $delta%2==0)) return NULL; for($mask=0; $mask<32; $mask++) if($netmask[$mask]==1) break; if(substr_count($netmask,"0")!=$mask) return NULL; return "$ip_start/$mask";}
echo ip2cidr('1.120.0.0', '1.127.255.255'); //1.120.0.0/13function ip2cidr($ip_start,$ip_end) { if(long2ip(ip2long($ip_start))!=$ip_start or long2ip(ip2long($ip_end))!=$ip_end) return NULL; $ipl_start = ip2long($ip_start); $ipl_end = ip2long($ip_end); if($ipl_start>0 && $ipl_end<0) $delta = ($ipl_end + 4294967296) - $ipl_start; else $delta = $ipl_end - $ipl_start; $netmask = str_pad(decbin($delta), 32, "0", STR_PAD_LEFT); if(ip2long($ip_start)==0 && substr_count($netmask,"1")==32) return "0.0.0.0/0"; if($delta<0 or ($delta>0 && $delta%2==0)) return NULL; for($mask=0; $mask<32; $mask++) if($netmask[$mask]==1) break; if(substr_count($netmask,"0")!=$mask) return NULL; return "$ip_start/$mask";}
The moderator, as you wrote on the second floor, cannot solve the problem of CIDR generation in the IP address range 1.120.0.0 1.159.255.255.
Although splitting is not very difficult, how do you determine the splitting point?
For example
Echo ip2cidr ('1. 120.0.0 ', '1. 127.255.255'); // 1.120.0.0/13
Echo ip2cidr ('1. 128.0.0 ', '1. 159.255.255'); // 1.128.0.0/11
Is a split method
Echo ip2cidr ('1. 120.0.0 ', '1. 151.20.255'); // 1.120.0.0/11
Echo ip2cidr ('1. 152.0.0 ', '1. 159.255.255'); // 1.152.0.0/13
Another method of splitting
While
Echo ip2cidr ('1. 120.0.0 ', '1. 159.255.255 ');
The reason for the failure is that the mask is
00000000001001111111111111111111
In fact, there is nothing wrong with it, but it cannot be expressed by cidr.
Notes
Echo long2ip (bindec ('20140901') + ip2long ('1. 120.0.0 '); // 1.151.255.255
Therefore, the second split method can be implemented by machines, while the first method can only be implemented manually.
Although splitting is not very difficult, how do you determine the splitting point?
For example
Echo ip2cidr ('1. 120.0.0 ', '1. 127.255.255'); // 1.120.0.0/13
Echo ip2cidr ('1. 128.0.0 ', '1. 159.255.255'); // 1.128.0.0/11
Is a split method
Echo ip2cidr ('1. 120.0.0 ', '1. 151.20.255'); // 1.120.0.0/11
Echo ip2cidr ('1. 152.0.0 ', '1. 159.255.255'); // 1.152.0.0/13
Another method of splitting
While
Echo ip2cidr ('1. 120.0.0 ', '1. 159.255.255 ');
The reason for the failure is that the mask is
00000000001001111111111111111111
In fact, there is nothing wrong with it, but it cannot be expressed by cidr.
Notes
Echo long2ip (bindec ('20140901') + ip2long ('1. 120.0.0 '); // 1.151.255.255
Therefore, the second split method can be implemented by machines, while the first method can only be implemented manually.
Thank you, moderator.
Ip2cidr ("1.40.0.0", "1.44.255.255 ");
00000000000001001111111111111111
Echo long2ip (bindec ('200') + ip2long ('1. 40.0.0 '); // 1.71.255.255 exceeds the specified IP address range
0000000000000100 1111111111111111
To obtain
Splitting should start from a small area
This is a big part. it is definitely not suitable.
Thank you for your exploration.
Analyze more problems
00000001011101110000000000000000 1.119.0.0
00000001011110000000000000000000 1.120.0.0
00000001011110010000000000000000 1.121.0.0
00000001011110100000000000000000 1.122.0.0
00000001011110110000000000000000 1.123.0.0
00000001011111000000000000000000 1.124.0.0
00000001011111010000000000000000 1.125.0.0
00000001011111100000000000000000 1.126.0.0
00000001011111110000000000000000 1.127.0.0
00000001100000000000000000000000 1.128.0.0
00000001100000010000000000000000 1.129.0.0
00000001100000100000000000000000 1.130.0.0
00000001100000110000000000000000 1.131.0.0
00000001100001000000000000000000 1.132.0.0
00000001100001010000000000000000 1.133.0.0
00000001100001100000000000000000 1.134.0.0
00000001100001110000000000000000 1.135.0.0
00000001100010000000000000000000 1.136.0.0
00000001100010010000000000000000 1.137.0.0
00000001100010100000000000000000 1.138.0.0
00000001100010110000000000000000 1.139.0.0
00000001100011000000000000000000 1.140.0.0
00000001100011010000000000000000 1.141.0.0
00000001100011100000000000000000 1.142.0.0
00000001100011110000000000000000 1.143.0.0
00000001100100000000000000000000 1.144.0.0
00000001100100010000000000000000 1.145.0.0
00000001100100100000000000000000 1.146.0.0
00000001100100110000000000000000 1.147.0.0
00000001100101000000000000000000 1.148.0.0
00000001100101010000000000000000 1.149.0.0
00000001100101100000000000000000 1.150.0.0
00000001100101110000000000000000 1.151.0.0
00000001100110000000000000000000 1.152.0.0
00000001100110010000000000000000 1.153.0.0
00000001100110100000000000000000 1.154.0.0
00000001100110110000000000000000 1.155.0.0
00000001100111000000000000000000 1.156.0.0
00000001100111010000000000000000 1.157.0.0
00000001100111100000000000000000 1.158.0.0
00000001100111110000000000000000 1.159.0.0
00000001101000000000000000000000 1.160.0.0
End
Echo ip2cidr ('1. 120.0.0 ', '1. 159.255.255 '), PHP_EOL; echo ip2cidr ('1. 120.0.0 ', '1. 169.255.255 '), PHP_EOL; echo ip2cidr ('1. 120.0.0 ', '1. 179.255.255 '), PHP_EOL; function ip2cidr ($ ip_start, $ ip_end) {if (long2ip (ip2long ($ ip_start ))! = $ Ip_start or long2ip (ip2long ($ ip_end ))! = $ Ip_end) return! Trigger_error ('IP illegal ', E_USER_NOTICE); $ ipl_start = ip2long ($ ip_start); $ ipl_end = ip2long ($ ip_end ); if ($ ipl_start> 0 & amp; $ ipl_end <0) $ delta = ($ ipl_end + 4294967296)-$ ipl_start; else $ delta = $ ipl_end-$ ipl_start; $ netmask = sprintf ('% 032b', $ delta); if (ip2long ($ ip_start) = 0 & substr_count ($ netmask, "1") = 32) return "0.0.0.0/0"; if ($ delta <0 or ($ delta> 0 & $ delta % 2 = 0) return! Trigger_error ("The number of intervals is invalid $ delta", E_USER_NOTICE); for ($ mask = 0; $ mask <32; $ mask ++) if ($ netmask [$ mask] = 1) break; if (substr_count ($ netmask, "0 ")! = $ Mask) {$ w = strrpos ($ netmask, '0') + 1; $ m = pow (2, 32-$ w)-1; $ ip_start = long2ip ($ ipl_start &~ $ M) + $ m + 1); return long2ip ($ ipl_start &~ $ M). "/$ w,". ip2cidr ($ ip_start, $ ip_end) ;}; return "$ ip_start/$ mask ";}
1.120.0.0/13, 1.128.0.0/11
1.120.0.0/15, 1.112.0.0/12, 1.128.0.0/15, 1.128.0.0/13, 1.136.0.0/15, 1.138.0.0/11
1.120.0.0/14, 1.120.0.0/13, 1.128.0.0/14, 1.128.0.0/12, 1.144.0.0/14, 1.148.0.0/11
Thank you! the moderator is particularly aware of his own shortcomings and has to work hard.