IpToCidr function-php Tutorial

Source: Internet
Author: User
IpToCidr function
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 ";}


The above is the function that the moderator writes.
Ip2cidr ("36.96.0.0", "36.223.255.255 ")
Execution result 36.96.0.0/9

Reverse lookup
Http://www.itmop.com/tool/ipaddress.php
36.96.0.0/9-> 36.0.0.1-36.127.255.254 is inconsistent with 36.96.0.0-36.223.255.255

There is a website, but you cannot see the conversion code
Http://ip2cidr.com/
36.96.0.0-36.223.255.255
Convert to 36.96.0.0/11
36.128.0.0/10
36.192.0.0/11

The split interval is hard to grasp...


Reply to discussion (solution)

Result: available address: 8388606 mask: 255.128.0.0 network: 36.96.0.0 first available: 36.0.0.1 last available: 36.127.255.254 broadcast: 36.223.255.255

Why not?

???? Yes ?? Ah.


36.96.0.0/9-> 36.0.0.1-36.127.255.254
Inconsistent with 36.96.0.0-36.223.255.255

After my brother on the second floor on the first floor said, I thought I had to test ip2cidr ("36.96.0.0", "36.223.425255") again by mistake. the execution result is 36.96.0.0/9.
The IP generation range of 36.96.0.0/9 is 36. 0.0.1-36. 127.255.254.

His computing is different from your needs.
It calculates which network segment an ip address can belong to under a given mask.

Different requirements and different results

It may have been wrong. my requirement is to use the function to convert the ranges of the first IP address and the last IP address to the CIDR format so that I can query whether an IP address belongs to this CIDR region, the test method is to use CIDR to generate the interval between the first IP address and the last IP address.
Function functions are similar to



This is actually a bug in ip2cidr.
The function prototype is from the php manual, but the segmentation function is added.
We can see that the segmentation is performed when the original function finds that the segment cannot work.
However, due to inherent deficiency, he did not identify your input as a segment.

I don't know how this website http://ip2cidr.com/how it is achieved on the Internet with fewer resources

A foreign article is implemented in JAVA

import java.util.ArrayList;import java.util.List;import java.util.regex.Matcher;import java.util.regex.Pattern;public class RangeToCidr {    private static final String IP_ADDRESS = "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})";    private static final Pattern addressPattern = Pattern.compile(IP_ADDRESS);    public static List
 
   rangeToCidrList(String istart, String iend)  {               int start = toInteger(istart);        int end = toInteger(iend);        List
  
    result = new ArrayList
   
    ();        while (end >= start) {            int maxsize = imaxblock( start, 32);            double x = (Math.log(end - start + 1) / Math.log(2) ) ;            int maxdiff = (int) (Math.floor(32 - Math.floor(x)));            String ip = intToIP(start);            if (maxsize < maxdiff) {                maxsize = maxdiff;            }            result.add( ip + "/" + (int)maxsize );            start += Math.pow(2, (32-maxsize));        }        return result;    }    private static int toInteger(String address) {        Matcher matcher = addressPattern.matcher(address);        if (matcher.matches()) {            return matchAddress(matcher);        }        else            throw new IllegalArgumentException("Could not parse [" + address + "]");    }    private static int matchAddress(Matcher matcher) {        int addr = 0;        for (int i = 1; i <= 4; ++i) {             int n = (rangeCheck(Integer.parseInt(matcher.group(i)), -1, 255));            addr |= ((n & 0xff) << 8*(4-i));        }        return addr;    }    private static int rangeCheck(int value, int begin, int end) {        if (value > begin && value <= end) // (begin,end]            return value;        throw new IllegalArgumentException("Value [" + value + "] not in range ("+begin+","+end+"]");    }    private static String intToIP(int val) {        int octets[] = new int[4];        for (int j = 3; j >= 0; --j)            octets[j] |= ((val >>> 8*(3-j)) & (0xff));        StringBuilder str = new StringBuilder();        for (int i =0; i < octets.length; ++i){            str.append(octets[i]);            if (i != octets.length - 1) {                str.append(".");             }        }        return str.toString();    }    private static long imask(int t)    {        return (long)(Math.pow(2, 32) - Math.pow(2, 32-t) ) ;    }    private static int imaxblock(long ibase, int tbit)  {        while (tbit > 0)    {            long im = imask(tbit-1);            long imand = ibase & im ;            if (imand != ibase) {                break;            }            tbit--;        }        return tbit;    }}
   
  
 

$ R = ip2cidr ("36.96.0.1", "36.223.0000255"); print_r ($ r); function ip2cidr ($ ip_start, $ ip_end) {$ res = array (); 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); if ($ ipl_start <0) $ ipl_start + = 0x100000000; $ ipl_end = ip2long ($ ip_end); if ($ ipl_end <0) $ ipl_end + = 0x100000000; $ ipl = $ ipl_start; do {$ k = strrpos (sprintf ('% 032b', $ ipl), '1'); $ cidr = $ k + 1; $ dk = pow (2, 32-$ K-1); $ mask = $ dk-1; $ res [] = sprintf ("% s/% d", long2ip ($ ipl &~ $ Mask), $ cidr); $ ipl + = $ dk;} while ($ ipl <$ ipl_end); return $ res ;}
Array(    [0] => 36.96.0.1/32    [1] => 36.96.0.2/31    [2] => 36.96.0.4/30    [3] => 36.96.0.8/29    [4] => 36.96.0.16/28    [5] => 36.96.0.32/27    [6] => 36.96.0.64/26    [7] => 36.96.0.128/25    [8] => 36.96.1.0/24    [9] => 36.96.2.0/23    [10] => 36.96.4.0/22    [11] => 36.96.8.0/21    [12] => 36.96.16.0/20    [13] => 36.96.32.0/19    [14] => 36.96.64.0/18    [15] => 36.96.128.0/17    [16] => 36.97.0.0/16    [17] => 36.98.0.0/15    [18] => 36.100.0.0/14    [19] => 36.104.0.0/13    [20] => 36.112.0.0/12    [21] => 36.128.0.0/9)

There is also a simpler one. Two of the functions in PHP both have library function tests.

import java.util.ArrayList;import java.util.List;public class RangeToCidr {    public static List
 
   range2cidrlist( String startIp, String endIp ) {                 long start = ipToLong(startIp);                 long end = ipToLong(endIp);                   ArrayList
  
    pairs = new ArrayList
   
    ();                 while ( end >= start ) {                         byte maxsize = 32;                         while ( maxsize > 0) {                                 long mask = CIDR2MASK[ maxsize -1 ];                                 long maskedBase = start & mask;                                 if ( maskedBase != start ) {                                         break;                                 }                                 maxsize--;                         }                           double x = Math.log( end - start + 1) / Math.log( 2 );                         byte maxdiff = (byte)( 32 - Math.floor( x ) );                         if ( maxsize < maxdiff) {                                 maxsize = maxdiff;                         }                         String ip = longToIP(start);                         pairs.add( ip + "/" + maxsize);                         start += Math.pow( 2, (32 - maxsize) );                 }                 return pairs;         }           public static final int[] CIDR2MASK = new int[] { 0x00000000, 0x80000000,                     0xC0000000, 0xE0000000, 0xF0000000, 0xF8000000, 0xFC000000,                     0xFE000000, 0xFF000000, 0xFF800000, 0xFFC00000, 0xFFE00000,                     0xFFF00000, 0xFFF80000, 0xFFFC0000, 0xFFFE0000, 0xFFFF0000,                     0xFFFF8000, 0xFFFFC000, 0xFFFFE000, 0xFFFFF000, 0xFFFFF800,                     0xFFFFFC00, 0xFFFFFE00, 0xFFFFFF00, 0xFFFFFF80, 0xFFFFFFC0,                     0xFFFFFFE0, 0xFFFFFFF0, 0xFFFFFFF8, 0xFFFFFFFC, 0xFFFFFFFE,                     0xFFFFFFFF };           private static long ipToLong(String strIP) {                 long[] ip = new long[4];                 String[] ipSec = strIP.split("\\.");                 for (int k = 0; k < 4; k++) {                         ip[k] = Long.valueOf(ipSec[k]);                 }                 return (ip[0] << 24) + (ip[1] << 16) + (ip[2] << 8) + ip[3];         }           private static String longToIP(long longIP) {                 StringBuffer sb = new StringBuffer("");                 sb.append(String.valueOf(longIP >>> 24));                 sb.append(".");                 sb.append(String.valueOf((longIP & 0x00FFFFFF) >>> 16));                 sb.append(".");                 sb.append(String.valueOf((longIP & 0x0000FFFF) >>> 8));                 sb.append(".");                 sb.append(String.valueOf(longIP & 0x000000FF));           return sb.toString();         } }
   
  
 

The moderator can check whether the JAVA function idea on the 12th floor can optimize your code to generate three CIDR 36.96.0.0/11 36.128.0.0/10 36.192.0.0/11
Finally, let this function accumulate in PHP for the benefit of everyone.

$r = ip2cidr("36.96.0.0","36.223.255.255");print_r($r);

Array(    [0] => 36.96.0.0/11    [1] => 36.128.0.0/9)

The link you gave is incorrect in the last section.

Are you talking about the http://ip2cidr.com/or the function on the 12th floor?


Indeed, 36.128.0.0/9 has exceeded 36.223.255.255.

$ R = ip2cidr ("36.96.0.0", "36.223.425255"); print_r ($ r); function ip2cidr ($ ip_start, $ ip_end) {$ res = array (); 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); if ($ ipl_start <0) $ ipl_start + = 0x100000000; $ ipl_end = ip2long ($ ip_end); if ($ ipl_end <0) $ ipl_end + = 0x100000000; $ ipl = $ ipl_start; do {$ k = strrpos (sprintf ('% 032b', $ ipl), '1'); $ cidr = $ k + 1; $ dk = pow (2, 32-$ K-1); if ($ ipl + $ dk> $ ipl_end) {$ dk/= 2; $ cidr ++ ;}$ mask = $ dk-1; $ res [] = sprintf ("% s/% d", long2ip ($ ipl &~ $ Mask), $ cidr); $ ipl + = $ dk;} while ($ ipl <$ ipl_end); return $ res ;}
Array(    [0] => 36.96.0.0/11    [1] => 36.128.0.0/10    [2] => 36.192.0.0/11)

I will try to test different IP address segments.

It's easy to split... Can the moderator be optimized?

$ip_st = "103.233.183.0";$ip_end = "103.233.183.255";print $ip_st."-".$ip_end."
";$cidr_arr = ip2cidr($ip_st,$ip_end );print_r($cidr_arr);print "
";for($i = 0 ; $i < count($cidr_arr); $i++){print $cidr_arr[$i]." : ";print cidr_conv($cidr_arr[$i])."
";}


103.233.183.0-103.233.183.255
Array ([0] => 103.233.183.0/25 [1] => 103.233.183.128/26 [2] => 103.233.183.192/27 [3] => 103.233.183.small/28 [4] => Large /29 [5] => 103.233.183.248/30 [6] => 103.233.183.252/31 [7] => 103.233.183.254/32)
103.233.183.0/25: 103.233.183.0-103.233.183.127
103.233.183.128/26: 103.233.183.128-103.233.183.191
103.233.183.192/27: 103.233.183.192-103.233.183.223
103.233.183.small/28: 103.233.183.small-103.233.183.239
103.233.183.240/29: 103.233.183.240-103.233.183.247
103.233.183.248/30: 103.233.183.248-103.233.183.small
103.233.183.252/31: 103.233.183.252-103.233.183.253
103.233.183.254/32: 103.233.183.254-103.233.183.254

function cidr_conv($cidr_address) {  $first = substr($cidr_address, 0, strpos($cidr_address, "/"));  $netmask = substr(strstr($cidr_address, "/"), 1);  $first_bin = str_pad(decbin(ip2long($first)), 32, "0", STR_PAD_LEFT);  $netmask_bin = str_pad(str_repeat("1", (integer)$netmask), 32, "0", STR_PAD_RIGHT);    for ($i = 0; $i < 32; $i++) {    if ($netmask_bin[$i] == "1")       $last_bin .= $first_bin[$i];    else      $last_bin .= "1";  }  $last = long2ip(bindec($last_bin));  return "$first - $last";}

$ R = ip2cidr ("103.233.183.0", "103.233.183.255"); print_r ($ r); function ip2cidr ($ ip_start, $ ip_end) {$ res = array (); 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); if ($ ipl_start <0) $ ipl_start + = 0x100000000; $ ipl_end = ip2long ($ ip_end); if ($ ipl_end <0) $ ipl_end + = 0x100000000; $ ipl = $ ipl_start; do {$ k = strrpos (sprintf ('% 032b', $ ipl), '1'); $ cidr = $ k + 1; $ dk = pow (2, 32-$ K-1); if ($ ipl + $ dk> $ ipl_end + 1) {$ dk/= 2; $ cidr ++;} $ mask = $ dk-1; $ res [] = array ('cidr' => sprintf ("% s/% D ", long2ip ($ ipl &~ $ Mask), $ cidr), 'mask' => long2ip (~ $ Mask), 'net' => long2ip ($ ipl &~ $ Mask), 'usable' => $ mask-1, 'Start' => long2ip ($ ipl &~ $ Mask) + 1), 'end' => long2ip ($ ipl | $ mask)-1 ), 'broadcast' => long2ip ($ ipl | $ mask),); $ ipl + = $ dk;} while ($ ipl <$ ipl_end); return $ res ;}
Array(    [0] => Array        (            [cidr] => 103.233.183.0/24            [mask] => 255.255.255.0            [net] => 103.233.183.0            [usable] => 254            [start] => 103.233.183.1            [end] => 103.233.183.254            [broadcast] => 103.233.183.255        ))

$ R = ip2cidr ("210.80.0.0", "210.80.63.255 ");
Print_r ($ r );

Array
(
[0] => Array
(
[Cidr] => 210.80.0.0/13
[Mask] => 255.248.0.0
[Net] => 210.80.0.0
[Usable] = & gt; 524286
[Start] => 210.80.0.1
[End] => 210.87.255.254
[Broadcast] => 210.87.255.255
)
)
This is a BUG. check whether the method on the 12th floor is suitable.

Final function:

$CIDR2MASK = array( 0x00000000, 0x80000000,                     0xC0000000, 0xE0000000, 0xF0000000, 0xF8000000, 0xFC000000,                     0xFE000000, 0xFF000000, 0xFF800000, 0xFFC00000, 0xFFE00000,                     0xFFF00000, 0xFFF80000, 0xFFFC0000, 0xFFFE0000, 0xFFFF0000,                     0xFFFF8000, 0xFFFFC000, 0xFFFFE000, 0xFFFFF000, 0xFFFFF800,                     0xFFFFFC00, 0xFFFFFE00, 0xFFFFFF00, 0xFFFFFF80, 0xFFFFFFC0,                     0xFFFFFFE0, 0xFFFFFFF0, 0xFFFFFFF8, 0xFFFFFFFC, 0xFFFFFFFE,                     0xFFFFFFFF );        function ipTocidr($ip_start,$ip_end) { global $CIDR2MASK;       $StartIp = ip2long($ip_start);        $EndIp = ip2long($ip_end);   $pairs = array();             while ( $EndIp >= $StartIp )   {                   $maxsize = 32;               while ( $maxsize > 0)       {                      $mask = $CIDR2MASK[$maxsize-1];                        $maskedBase = $StartIp & $mask ;                           if ( $maskedBase != $StartIp )           {                                  break;                           }                           $maxsize--;                   }                 $x = log( $EndIp -  $StartIp + 1) / log(2);                   $maxdiff = 32 - floor($x) ;                   if ( $maxsize < $maxdiff)       {                           $maxsize = $maxdiff;                   }                   $ip = long2ip($StartIp);       $pairs[] = $ip."/".$maxsize;                                      $StartIp += pow( 2, (32 - $maxsize) );         }           return $pairs;     }   

Thank you for your great guidance. at last, I translated the JAVA function.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.