Match IP in CIDR

Recently, I needed a simple PHP function that will match an IP Address in a CIDR block.

I have a list of CIDR notations/blocks in a text file, like this:

...
151.237.190.0/24
192.74.228.0/26
198.50.140.64/27
...

CIDR is Classless Inter-Domain Routing.

Every time my PHP script runs, it is given an IP (IPv4) address, and the job of the script is to loop through this text file and report back to me, if the IP address matches any of the CIDR blocks therein.

PHP Function to Match IP Address in CIDR

Since there doesn’t seem to be an existing PHP function that does this today, I wrote one of my own. Also, since I was not interested to figure out the intricacies of CIDR,  or how to translate CIDR notations, I decided to use a program already installed and existing on my Linux servers that handles all this very well. ipcalc fits the bill and provides a simple way to calculate IP information for a host.

Full path to ipcalc command in Fedora

[me@beefong ~]$ which ipcalc
/bin/ipcalc

Incorporating ipcalc in my PHP script, this is what I ended up with:

/**
 * Returns TRUE if IP address (IPv4) is in CIDR block.
 * @author J de Silva
 * @link http://gidblog.com/?p=180
 * @uses getNetworkIpFromCidr()
 * @param string $ip IP Address (IPv4) to match with CIDR
 * @param string $cidr CIDR Notation
 * @return boolean
 */
function isIpInCidr($ip, $cidr) {
	// We need just the prefix from the CIDR notation i.e. the '24' from '198.1.1.0/24'
	list(, $prefix) = explode('/', $cidr);
	return getNetworkIpFromCidr($cidr) == getNetworkIpFromCidr("$ip/$prefix");
}

/**
 * Returns the the network address for the given IP address (IPv4) and netmask.
 * @author J de Silva
 * @link http://gidblog.com/?p=180
 * @usedby isIpInCidr()
 * @access private
 * @param string $cidr CIDR Notation (IPv4)
 * @return string Network IP Address
 */
function getNetworkIpFromCidr($cidr) {
	// Using ipcalc program commonly found on Linux servers.
	$output = rtrim(shell_exec("/bin/ipcalc -n $cidr")); // $output example value: 'NETWORK=198.1.1.0'
	// we only want the second part of the resulting array i.e. '198.1.1.0' if considering the example above.
	list(, $network) = explode('=', $output);
	return $network;
}

I hope you find it useful too.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>