Skip to content
rlanvin edited this page Apr 19, 2014 · 14 revisions

IPv4/IPv6 manipulation library for PHP. This library (and documentation) is heavily inspired by Python ipaddress.

Feel free to read the source code for more info!

IP Addresses

The IPv4 and IPv6 objects provide a way to create and manipulate IP Addresses. They both inherit from IP.

Creation

IP addresses can be created either directly by instantiating IPv4 or IPv6, or using the convenience factory method IP::create($ip).

$ip = new IPv4('192.168.0.1');
$ip = new IPv6('2001:db8::');
$ip = new IPv6('::192.168.0.0'); // IPV4-mapped IPv6
$ip = new IPv6('::ffff:192.168.0.0'); // IPV4-mapped IPv6

$ip = IP::create('192.168.0.1'); // return IPv4
$ip = IP::create('2001:db8::'); // return IPv6

It's also possible to create an IP address object from various types:

  • An signed integer (such as the result of ip2long), a double containing an signed/unsigned integer value, or an string containing an unsigned integer value. In the factory method, integers less than 2^32 will be considered to be IPv4 by default.
  • A binary string (such as the result of inet_pton). Binary strings must be exactly 4 chars (32 bits) for IPv4 and 16 chars (128 bits) for IPv6.
  • A GMP ressource number.
$ip = IP::create(294967295); // 17.148.215.255
$ip = IP::create("\000\000\000*"): // 0.0.0.42

A InvalidArgumentException will be thrown in the value provided cannot be converted into an IP address.

Converting to string

IPv4 and IPv6 objects are convertible to string by default. You can also explicitly generate a string representation with humanReadable($compress) method. The parameter $compress (default true) indicates whether or not to display a short version of the address.

$ip = new IPv4(294967295);
echo $ip; // 17.148.215.255
echo $ip->humanReadable(false); // 017.148.215.255

$ip = new IPv6('2a01:8200::');
echo $ip; // 2a01:8200::
echo $ip->humanReadable(false); // 2a01:8200:0000:0000:0000:0000:0000:0000

Note: IPv4-mapped IPv6 will be displayed as plain IPv6 in uncompressed mode.

$ip = new IPv6('::ffff:192.168.0.0');
echo $ip; // ::ffff:192.168.0.0
echo $ip->humanReadable(false),"\n"; // but 0000:0000:0000:0000:0000:ffff:c0a8:0000

Converting to integer

Conversion to integer is done with the numeric() method. Due the limits of the integer type in PHP, this method will return a numeric string, not an actual integer.

This method accepts an optional parameter $base. Default is to return in base 10 (decimal).

$ip = new IPv4('127.0.0.0');
echo $ip->numeric(); // '2130706432'

echo $ip->numeric(2); // '1111111000000000000000000000000'
echo $ip->numeric(16); // '7f000000'

$ip = new IPv6('2a01:8200::');
echo $ip->numeric(); // '55835404833073476206743540170770874368'

echo $ip->numeric(2); // '101010000000011000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
echo $ip->numeric(16); // '2a018200000000000000000000000000'

Operations

PHP doesn't support overloading of operators, so you have to call the methods directly. All methods accepts any data type that can be converted into a IP address.

Arithmetic operators

$ip = new IPv4('127.0.0.0');
echo $ip->plus(1); // 127.0.0.1
echo $ip->minus(1); // 126.255.255.255

Operators will throw a OutOfBoundException if you reach the boundaries of the given IP address (for example, trying to add 1 to 255.255.255.255).

Bitwise operators

$ip = new IPv4('127.0.0.0');
echo $ip->bit_or('255.255.0.0'); // 255.255.0.0
echo $ip->bit_and('255.255.0.0'); // 127.0.0.0

Other methods

Name Description
getVersion() Return the IP version (4 or 6)
isPrivate() Return true if the address is allocated for private networks
isPublic() Return true if the address is allocated for public networks

Blocks (networks)

The IPv4Block and IPv6Block objects provide a way to create and manipulate IP networks. They use the CIDR block notation (e.g. 192.168.0.0/24). They both inherit from IPBlock.

Creation

Like IP addresses, blocks can be created either by instantiating directly IPv4Block or IPv6Block, or by using the convenience factory method IPBlock::create().

$block = new IPv4Block('128.0.0.0/16');
$block = new IPv4Block('128.0.0.0', '16'); // alternate way of calling the constructor

$block = new IPv6Block('2001:0db8::/32');
$block = new IPv6Block('2001:0db8::', '32'); // alternate way of calling the constructor

$block = IPBlock::create('128.0.0.0/16'); // IPv4Block
  • The IP parameter can be anything that can be converted into an IP address (string, integer, etc.)
  • The prefix must be an integer between 0 and 32 (IPv4) or 0 and 128 (IPv6)

Basic methods

Name Description
getFirstIp() Return the first IP of the block. (alias getNetworkAddress())
getLastIp() Return the last IP of the block. (alias getBroadcastAddress())
getMask() Return the net mask (IP object)
getDelta() Return the delta to last IP of the block, aka "host mask" (IP object)
getNbAddresses() Return the number of IP addresses in block. Because this number can be huge, this returns a numeric string, not an actual integer.

Example:

$block = new IPv4Block('128.0.0.0/16');
echo $block->getMask(); // 255.255.0.0
echo $block->getDelta(); // 0.0.255.255
echo $block->getFirstIp(); // 128.0.0.0
echo $block->getLastIp(); // 128.0.255.255
echo $block->getNbAddresses(); // '65536'

$block = new IPv6Block('2001:0db8::/32');
echo $block->getMask(); // ffff:ffff::
echo $block->getDelta(); // ::ffff:ffff:ffff:ffff:ffff:ffff
echo $block->getFirstIp(); // 2001:db8::
echo $block->getLastIp(); // 2001:db8:ffff:ffff:ffff:ffff:ffff:ffff
echo $block->getNbAddresses(); // '79228162514264337593543950336'

Arithmetic operators

Like IP addresses, you can make addition and subtractions with blocks. You cannot however do bitwise operations.

$block = new IPv4Block('192.168.0.0/24');
echo $block->plus(42); // 192.168.42.0/24
echo $block->minus(42); // 192.167.214.0/24

Operators will throw a OutOfBoundException if you reach the boundaries of the given IP version (for example, if you try to add 256 to 255.255.255.0/24).

Blocks as containers

IP blocks are containers for IP addresses or other IP blocks. You can test whether a block contains another block or IP, or is contained by another block using contains and isIn. The method isIn is also available for IP objects, to test if a given IP is in a given block.

The method overlaps returns true if the block overlaps another block, whether is is bigger or smaller.

$block = IPBlock::create('192.168.0.0/24');
$block->contains('192.168.0.42'); // true
$block->contains('192.168.1.0/24'); // false
$block->isIn('192.168.0.0/16'); // true
$block->overlaps('192.168.0.0/16'); // true

$ip = IP::create('192.168.0.42');
$ip->isIn($block); // true

Iterator and array access

IP addresses contained in a block can be iterated with foreach directly using the block object.

$block = IPBlock::create('192.168.0.0/24');
foreach ( $block as $ip ) {
    echo $ip,"\n";
}
// outputs:
// 192.168.0.0
// 192.168.0.1
// 192.168.0.2
// ...
// 192.168.0.255

It's also possible to access an IP address directly using array notation.

$block = IPBlock::create('192.168.0.0/24');
echo $block[0]; // 192.168.0.0
echo $block[42]; // 192.168.0.42

$block = IPBlock::create('2001:db8::/32');
echo $block['79228162514264337543950335']; // 2001:db8:41:8937:4bc6:a7ef:9abd:6fff

Trying to access an offset outside of the block will throw a OutOfBoundsException.

Note: It's not possible to use array notation to set values inside the block.

Subnetworks

Blocks can be split into smaller blocks with the split($prefix) method. This method returns a IPBlockIterator object, so you can loop with foreach. The value of $prefix must be greater than the current block prefix. For example, you can split a /16 into /24, but not the other way around. Note that $prefix accepts an optional leading '/', e.g. you can pass "/24" instead of "24" if you find it clearer.

$blocks = IPBlock::create('192.168.0.0/16')->split('/24');
echo $blocks->count(),"\n"; // 256

foreach ( $blocks as $block ) {
	echo $block,"\n";
}
// outputs:
// 192.168.0.0/24
// 192.168.1.0/24
// 192.168.2.0/24
// ...
// 192.168.255.0/24
Clone this wiki locally