0

I have ip and I want to convert it into CIDR block with specific mask (/28, for example). Using PHP.

So that input "1.1.1.100" and "28" and output is "1.1.1.96/28"

ip_to_cidr('1.1.1.100', '28') // '1.1.1.96/28'

I found a lot of functions to match and ranges, but nothing about actually converting from ip to CIDR. Seems like to be most basic operation, may be I am missing something, using wrong search terms or misunderstanding masks.

For context: I need to block bots, I have their IP and want to block range in ipset. /24 is a bit to much (but easy to make, just replace last bit with ".0/24"), so I want to use /27 /28 /29.

Qiao
  • 16,565
  • 29
  • 90
  • 117

2 Answers2

1

It's ... beautiful

function ip_to_mask28($ip)
{
    $ip_parts = explode('.', $ip);
    $mask28 = [0, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240, 256];
    foreach ( $mask28 as $key => $value )
        if ( $ip_parts[3] < $mask28[$key + 1] )
            return $ip_parts[0].'.'.$ip_parts[1].'.'.$ip_parts[2].'.'.$value.'/28';
}
echo ip_to_mask28('1.1.1.100'); // 1.1.1.96/28 

Rolling with this now

Qiao
  • 16,565
  • 29
  • 90
  • 117
0

Is this what you are looking for ? I searched about it and found this which is close to your output. you can find more information here

function ipRange($cidr) {
   $range = array();
   $cidr = explode('/', $cidr);
   $range[0] = long2ip((ip2long($cidr[0])) & ((-1 << (32 - (int)$cidr[1]))));
   $range[1] = long2ip((ip2long($range[0])) + pow(2, (32 - (int)$cidr[1])) - 1);
   return $range;
}

var_dump(ipRange('1.1.1.100/28'));

Output:

array(2) {
 [0]=>
 string(8) "1.1.1.96"
 [1]=>
 string(9) "1.1.1.111"
}
Umer Abbas
  • 1,866
  • 3
  • 13
  • 19