;

Simple IP Address & Subnetting Class

Published October 04, 2009 | Development, Mobile, App | 0 Comments

On a few occasions, I’ve been faced with situations where I’ve needed to determine whether a given IP address was part of a particular subnet. Granted, usually PHP sites don’t need to worry about things like that, but sometimes it is necessary to restrict access to users in certain locations, or maybe you want a reporting tool to be able to filter by a range of IPs when you click on an individual address.

To accomplish these tasks, I have written a couple of classes that are intended to simplify things. Rather than completely reinventing the wheel, I started with the excellent open source SubnetCalc project by Ramond Ferguson. I adapted the existing code into an object-oriented class structure, and updated the regular expression handling to use the superior preg_* functions to improve speed and future compatibility, as ereg has been deprecated. In addition to the detailed subnet calculation functions already offered by the project, I have added a few new features:

  • Test if a given IP is a valid address
  • Determine IP type (node, network, or broadcast) based on the associated subnet schema
  • Test whether an IP is within in the subnet’s address range
  • Dynamically alter the subnet schema — calculations are automatically updated to the new values

They always say the proof is in the pudding, so here are a couple of usage examples. First, let’s create an IP object. The class will automatically test to see that the IP is valid, and throw an exception if it’s not:

Create an IP object
try {
	$ip = new IPAddress('192.168.1.12');
} catch( Exception $e ) {
	print $e;
}

To assign a subnet mask, you can call the SetCIDR method:

Configure the subnet using SetCIDR
$ip->Subnet->SetCIDR(24);

And now your object is populated with a handful of useful calculations:

Output of the IPAddress object
IPAddress Object
(
    [Address] => 192.168.1.12
    [Subnet] => Subnet Object
        (
            [Class] => C
            [Netmask] => 255.255.255.0
            [CIDR] => 24
            [Wildcard] => 0.0.0.255
            [Network] => 192.168.1.0
            [Broadcast] => 192.168.1.255
            [FirstHost] => 192.168.1.1
            [LastHost] => 192.168.1.254
            [Hosts] => 254
            [Private] => 1
        )

)

You can also use the Subnet object by itself to perform simple calculations without a specific IP address, and you can call the IsValidHost() method to test an IP address to see if it fits in the subnet. An example of how this might look:

Working With Subnets
try {
	$subnet = new Subnet("192.168.1.0/27");
        print $subnet->IsValidHost("192.168.1.21") ? "YES" : "NO";
        print $subnet->IsValidHost("192.168.1.64") ? "YES" : "NO";
} catch( Exception $e ) {
	print $e;
}

In this example, a subnet is created, with possible hosts from 192.168.1.1 to 192.168.1.30. So the first print statement would display YES, since node 21 falls within the subnet, and the second statement would display NO, as node 64 is not part of the subnet.

If you would like to try these out for yourself, you can download the classes here. Thus far, the class seems to work well for my purposes, but as this is based on some unfamiliar code from another project, I could have easily missed something. I will continue to fine tune the code, and will be doing some minor cleanup on the imported functions as time permits, so be sure to check back periodically for any updates.

;