Link to home
Start Free TrialLog in
Avatar of kebabs
kebabsFlag for Australia

asked on

How do I summarise CIDR addresses in PHP?

I have a list of CIDR addresses that can be summarised/aggregated and I wish to do this in PHP but cannot find a PEAR package or class through the likes of http://phpclasses.org to do this task.

There is a Perl extension Net::CIDR::Lite and a Ruby class but I'm having a hard time trying to convert this to PHP nor do I want to spend much time on that.

Here is an excerpt of a possible output.
58.6.0.0/15
58.65.248.0/21
58.84.64.0/18
58.84.128.0/18
58.84.192.0/19
58.84.240.0/20
58.87.0.0/20
58.96.0.0/16
58.97.128.0/17
58.104.0.0/13
58.145.128.0/19
58.160.0.0/12
58.178.0.0/15
58.181.64.0/19
58.181.112.0/20
59.86.160.0/19
59.100.0.0/15
59.102.0.0/16
59.151.128.0/18
59.152.224.0/19
59.154.0.0/18
59.154.64.0/19
59.154.96.0/23
59.154.98.0/24
59.154.99.0/25
59.154.99.128/27
59.154.99.160/28
59.154.99.176/29
59.154.99.184/30
59.154.99.192/26
59.154.100.0/22
59.154.104.0/21
59.154.112.0/20
59.154.128.0/17
59.167.0.0/16
59.191.192.0/19
59.191.224.0/20

Open in new window

Avatar of Waschman
Waschman
Flag of Sweden image

You'll need to use the binary operators in PHP (| & << >> etc).
Then you can use the convert-to-binary functions to convert between int and bin.

I assume you know how to calculate summaries with CIDR addressing.
// &	AND
// |	OR
// >>	right-bit-shift
// <<	left-bit-shift
// ^	XOR
$a = 8;
$b = 5;
$c = $a | $b;
echo $c .'<br>';// Prints 13
 
$a = 46;
$b = 248;
$c = $a & $b;
echo $c .'<br>';// Prints 40
 
$a = 10;
$b = 5;
$c = $a ^ $b;
echo $c .'<br>';// Prints 15
 
$a = 128;//10000000
$b = 1;
$c = $a >> $b;//0100000
echo $c .'<br>';// Prints 64
 
$a = 6;//110
$b = 2;
$c = $a << $b;//11000
echo $c .'<br>';// Prints 24

Open in new window

Avatar of kebabs

ASKER

Bitwise operators give me too much of a head ache, possibly the worst aspect of writing code. Otherwise, I could simply transcode the Perl/Ruby variants. I was hoping for a ready solution.
Sorry for that! I searched Google and it didn't come up with anything useful. I want to make a real code that works but this weekend I don't have the time. Maybe tonight when I come home. I'm a nightowl! One question though... are the IP-addresses you submitted already summarized? (I think they are) If so, can you please send some example IP-addresses that should be summarized.

For example: Any IPs that summarize into 58.84.240.0/20.
Avatar of kebabs

ASKER

The example was not a good one... below is one that summarises better. If you do take the time to write one, make sure to leave a point of contact as I doubt some points here are enough reward :)
# Summarised (9 CIDR addresses)
58.147.128.0/19
117.55.192.0/20
121.100.48.0/21
125.213.192.0/19
202.56.176.0/20
202.86.16.0/20
203.215.32.0/20
210.80.0.0/19
210.80.32.0/19
 
# Unsummarised (72 CIDR addresses)
58.147.128.0/19
62.142.210.32/27
63.243.149.0/27
63.243.150.8/29
63.243.150.16/28
64.86.63.64/27
80.247.139.0/24
82.205.190.0/23
82.205.192.0/21
82.205.202.0/23
82.205.204.0/22
82.205.246.0/25
84.11.26.128/26
84.11.33.0/24
84.11.79.0/24
87.249.84.0/24
117.55.192.0/20
117.104.224.0/21
121.100.48.0/21
121.127.32.0/19
125.213.192.0/19
202.56.176.0/20
202.86.16.0/20
202.133.9.240/28
202.133.13.8/29
202.133.13.16/28
202.133.13.40/29
202.133.13.56/29
202.133.13.96/28
202.174.133.8/29
202.174.133.32/28
202.174.133.144/29
202.174.134.0/29
202.174.144.0/29
202.174.144.216/29
202.174.148.48/29
202.174.148.128/29
202.174.153.184/29
202.174.154.0/29
202.174.154.24/29
202.174.154.96/28
202.174.154.128/29
202.174.154.160/29
202.174.154.180/30
202.174.154.184/30
202.174.154.212/30
202.174.155.128/29
202.174.155.144/29
202.174.155.216/29
202.174.155.240/29
202.174.156.64/26
202.174.156.192/28
202.174.156.208/29
202.174.156.248/29
202.174.157.192/27
202.174.157.232/29
203.88.66.64/29
203.88.66.160/29
203.88.82.240/29
203.88.88.24/29
203.88.88.32/29
203.88.88.40/30
203.88.88.160/29
203.88.88.224/29
203.208.205.192/26
203.215.32.0/20
208.35.53.176/28
210.5.226.0/24
212.116.232.208/28
217.10.167.0/24
217.195.144.24/29
217.195.144.32/30

Open in new window

Avatar of kebabs

ASKER

BTW, this was data from 2 different sources covering Afghanistan's IP ranges (the country was only for example's sake). I think the unsummarised list is an older/newer list as there seems to be some ranges that are not represented in the summarised one.
Hmm, it was more difficult than I thought it should be. I'm too tired I have to much to do in school so I don't have the time. I have a problem with my code-logic, but I'm posting my code so far and some pseudo-code for you to try. I need to point out that I'm studying for the CCNA exam and so my CIDR knowledge is a bit bad, but I think I know how to calculate it (taking common bits and return network_address/bits). See pseudo for more details.

I am sorry for this but I hope you get a solution soon. You can e-mail me on waschman at gmail dot com when you find a solution. Good luck!
/**
 * Get single IP-address class
 *
 * @param string $ip
 */
function get_ip_class($ip)
{
	$class = false;
	$octet = explode('.', $ip);
	if ($octet[0] <= 126) $class = 'A';
	elseif ($octet[0] == 127) $class = 'Loopback';
	elseif ($octet[0] <= 191) $class = 'B';
	elseif ($octet[0] <= 223) $class = 'C';
	elseif ($octet[0] <= 239) $class = 'Multicast';
	else $class = 'Reserved';
	return $class;
}
 
 
/**
 * Enter description here...
 *
 * @param array $ip
 */
function summarize($ips)
{
	$count = count($ips);
	$octet_diff = 0;
	// Save all octets into an array
	for ($pos=0; $pos<4; $pos++) {
		for ($i=0; $i<$count; $i++) {
			$octets[$i] = explode('.', $ips[$i], 4);
			// Save first octet so we can check which octet differs from
			// the others. Crucial when we want to know where to begin checking
			// of binary digits.
			if ($i==0) $first = $octets[$i][$pos];
			// Find different octets
			if ($first != $octets[$i][$pos]) {
				$debug = $i .':'. $pos;//save which IP and octet
				$octet_diff = $pos;
				break;
			}
		}
	}
	
	echo 'Debug: Position of octet that differs is '. $debug .'<br>';
	
	// Logic problem here -- too tired and too much in to do in school instead
	
	// Some kind of main-loop.
	// Check the diffing octet in IP x and x+1.
	// Convert them both to binary (or leave as int).
	// Loop through binary positions, starting from the left.
	// Is ANDing y bit of octet in IP x y bit of octet in IP x+1 equal to 1?
	// If 1 goto next loop.
	// Now compare y bit of octet in IP x+1 and x+2.
	// Is ANDing equal to 1?
	// And so on...
	//
	// Loop through y bit of all IP:s passed to summarize().
	// If every ANDing did get 1 move on to y+1 bit.
	// And repeat above until you encounter an ANDing equal to 0.
	// If 0 then we have all the bits needed to summarize the IP-addresses.
	//   We only have to keep track of the number of bits tested from left
	//   to right to have the number of bits used for the subnetmask.
}
 
 
 
// Should summarize into 192.168.16.0/20
$ip[] = '192.168.1.0';
$ip[] = '192.168.2.0';
$ip[] = '192.168.3.0';
$ip[] = '192.168.4.0';
$ip[] = '192.168.5.0';
$ip[] = '192.168.6.0';
$ip[] = '192.168.7.0';
$ip[] = '192.168.8.0';
$ip[] = '192.168.9.0';
$ip[] = '192.168.10.0';
 
$cidr_ip = summarize($ip);
echo '<p>'. $cidr_ip .'</p>';

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of Waschman
Waschman
Flag of Sweden image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial