garrcomm / networking-utilities
PHP library containing some networking utilities
Requires
- php: >=7.4
- ext-json: *
Requires (Dev)
- garrcomm/markdown-generator: v1.x-dev
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^9.4
- squizlabs/php_codesniffer: ^3.5
Suggests
- ext-sockets: Required for native ICMP support
README
Table of contents
Introduction
When working on PHP projects, I often need some network related methods. This repository contains a list of classes that help with that. This package works on PHP 7.4 and higer, including PHP 8.
These services are currently included:
The Dns Service is a wrapper for nslookup
that gives detailed and structured responses.
The IpTools Service wraps around some IP related commands and also returns structured objects.
There are also a few very useful data models;
The Url Model is an object orientated wrapper around parse_url
with the possibility to also modify URLs.
The Ipv4Address and Ipv4Range Models helps formatting IPv4 addresses and performs some subnet based calculations.
The MacAddress Model helps validating and formatting MAC addresses.
The DnsResult and DnsAnswer Models are returned by the Dns
service.
All data models can be serialized with json_encode
and var_export
.
Also, they can all be represented as a string.
How to install
You can install these utilities with Composer by running composer require garrcomm/networking-utilities
or by copying the source files from the src folder.
Code quality
Code quality is checked with several tools to make sure everything is working properly and well documented. The following methods are in use:
- PHP Code Sniffer
- Fully PSR-12 compliant
- Generic and some PEAR DocBlock required
- PHPUnit
- With 100% code coverage
- PHPStan
- With rule level 9
OS Dependencies
These utilities should work on most Windows and Linux installations.
For Linux, it can be possible that you'll need to install some additional packages (depending on the OS config we'll need the commands nslookup
, ip
, ipconfig
, ifconfig
, ping
and/or arp
).
Whenever one of those commands is missing, a RuntimeException
with code 127
will be thrown.
On most Linux distros these tools are already included though. Otherwise, it's easy to solve by locating the appropriate package (apt-file search --regexp 'bin/ping$'
or yum provides ping
, depending on your distro).
How to develop on this package
If you've installed Docker, you can execute these commands in the root of the project:
docker compose up -d
docker compose exec php bash
This will put you in a terminal with the same configuration as the pipelines used for automated testing of this code. In this terminal, you've got a few commands:
# Download all (development) dependencies
composer install
# Run code sniffer
vendor/bin/phpcs
# Run static analyser
vendor/bin/phpstan
# Run unit tests
vendor/bin/phpunit
In this container, the command line tools used in this package are also installed.
Available objects
Below are all available classes in this package. They're divided into two categories;
- Services that executes all kind of actions
- Models that contain data and a few methods to manipulate that data
Service\Dns
Class example
The Dns service wraps around nslookup
and returns neat DNS lookup results.
It's also possible to change the target nameserver.
$dns = new \Garrcomm\Netutils\Service\Dns();
$dns->setDnsServer('dns.google');
var_dump($dns->getMx('google.com'));
Class synopsis
class Dns {
/* Constants */
public const A = 'internet address';
public const AAAA = 'AAAA address';
public const CNAME = 'canonical name';
public const MX = 'mail exchanger';
public const NS = 'nameserver';
public const TXT = 'text';
/* Methods */
public __construct(string dnsServer = 'dns.google')
public getA(string domain): DnsResult
public getAAAA(string domain): DnsResult
public getCname(string domain): DnsResult
public getDnsServer(): string
public getMx(string domain): DnsResult
public getNs(string domain): DnsResult
public getTxt(string domain): DnsResult
public setDnsServer(string dnsServer): void
}
Constants
Dns::A
An IPv4 internet address (A record)
Dns::AAAA
An IPv6 internet address (AAAA record)
Dns::CNAME
An alias to another DNS record (CNAME record)
Dns::MX
IP address(es) to an email server (MX record)
Dns::NS
DNS names of all responsible nameservers (NS record)
Dns::TXT
A record containing plain text, used for domain verification, SPF, DKIM, etc. (TXT record)
Methods
- Dns::__construct — Initiates a new DNS service
- Dns::getA — Fetches all A records
- Dns::getAAAA — Fetches all AAAA records
- Dns::getCname — Fetches all CNAME records
- Dns::getDnsServer — Returns the DNS server used to query all requests
- Dns::getMx — Fetches all MX records
- Dns::getNs — Fetches all NS records
- Dns::getTxt — Fetches all TXT records
- Dns::setDnsServer — Sets the DNS server used to query all requests
Service\IpTools
Class example
IpTools helps with basic IPv4 related stuff;
$tools = new \Garrcomm\Netutils\Service\IpTools();
// getLocalIpv4s() returns a list of all IPv4 addresses on the current machine
$ips = $tools->getLocalIpv4s();
foreach ($ips as $networkName => $ip) {
echo 'Network ' . $networkName . ' has IP address ' . $ip->getIpAddress() . PHP_EOL;
}
// networkQuickScan returns a list of all IPv4 addresses that can be found within a network
$ip = new \Garrcomm\Netutils\Model\Ipv4Address('192.168.2.1', '255.255.255.0');
$ips = $tools->networkQuickScan($ip);
foreach ($ips as $mac => $ip) {
echo 'System ' . $mac . ' has IP address ' . $ip->getIpAddress() . PHP_EOL;
}
// With getIpByMac you can get the IP based on a MAC address
$mac = new \Garrcomm\Netutils\Model\MacAddress('aa-bb-cc-dd-ee-ff');
$ip = $tools->getIpByMac($mac);
echo 'Mac address ' . $mac . ' resolves to ' . $ip . PHP_EOL;
// With isLocalIp you can look up if an IP address is a local IP address
$ips = ['192.168.0.1', '8.8.8.8', '10.0.0.1'];
foreach ($ips as $ip) {
echo $ip . ' is ' . ($tools->isLocalIp($ip) ? 'a' : 'not a') . ' local IP' . PHP_EOL;
}
Class synopsis
class IpTools {
/* Methods */
public __construct(string operatingSystem = 'Linux')
public getIpByMac(MacAddress macAddress, ?Ipv4Address networkInterface = null): Ipv4Address
public getLocalIpv4s(): array<string,Ipv4Address>
public getMacByIp(Ipv4Address ipv4Address): MacAddress
public isLocalIp(?integer|string|Ipv4Address ipAddress): bool
public networkQuickScan(Ipv4Address networkInterface): array<string,Ipv4Address>
}
Methods
- IpTools::__construct — Initializes IP tools
- IpTools::getIpByMac — Looks up the matching IP address for a MAC address.
- IpTools::getLocalIpv4s — Returns a list of all local IPv4 addresses
- IpTools::getMacByIp — Returns the known MAC address by its IP address.
IpTools::isLocalIp — Returns true when the IP is a local IP
The IANA has defined these IP addresses as private or local:
10.0.0.0 to 10.255.255.255, a range that provides up to 16 million unique IP addresses.
172.16.0.0 to 172.31.255.255, providing about 1 million unique IP addresses.
192.168.0.0 to 192.168.255.255, which offers about 65,000 unique IP addresses.IpTools::networkQuickScan — Returns a list of all known IP addresses in a network
Model\Url
Class example
This class wraps and enhances the PHP method parse_url
so you can read and modify URLs
// You can initiate the URL class in two ways;
// 1. By using the current request
$url = \Garrcomm\Netutils\Model\Url::current();
// 2. By using a URL in the constructor
$url = new \Garrcomm\Netutils\Model\Url('https://localhost/foo?one=two&bar=baz');
// It's possible to set and remove elements, in one chain.
echo $url
->setHostname('foo.bar')
->setPath('baz')
->setQuery('bar', 'foo')
->removeQuery('one')
->setFragment('fragment-here'); // https://foo.bar/baz?bar=foo#fragment-here
// The object can be treated as a string:
echo '<a href="' .htmlspecialchars($url) . '">Click here</a>';
// The object can also be json serialized:
echo json_encode($url);
Class synopsis
class Url implements JsonSerializable {
/* Methods */
public __construct(string url)
public getFragment(): string
public getFullQuery(): array<int|string,mixed>
public getHostname(): string
public getPassword(): string
public getPath(): string
public getPort(): int
public getQuery(string key): mixed|string
public getScheme(): string
public getUsername(): string
public jsonSerialize(): mixed
public removeFragment(): self
public removeFullQuery(): self
public removePassword(): self
public removePort(): self
public removeQuery(string key): self
public removeUsername(): self
public setFragment(string fragment): self
public setFullQuery(array<string,mixed> query): self
public setHostname(string hostname): self
public setPassword(string password): self
public setPath(string path): self
public setPort(integer port): self
public setQuery(string key, string|mixed value): self
public setUsername(string username): self
public __toString(): string
public static current(): self
public static __set_state(mixed[] state): self
}
Methods
- Url::__construct — Makes an object based on a URL
- Url::getFragment — Returns the current fragment
- Url::getFullQuery — Returns the full query
- Url::getHostname — Returns the hostname of the URL
- Url::getPassword — Returns the password in the URL, if set
- Url::getPath — Returns the path of the URL
- Url::getPort — Returns the port, when specified in the URL
- Url::getQuery — Returns the value of a specific query string parameter
- Url::getScheme — Returns the scheme (http/https)
- Url::getUsername — Returns the username, if set in the URL
- Url::jsonSerialize — JsonSerializable::jsonSerialize — Specify data which should be serialized to JSON
- Url::removeFragment — Removes the #fragment in the URL
- Url::removeFullQuery — Removes the ?query from the URL
- Url::removePassword — Removes the password in the URL
- Url::removePort — Removes the port from the URL
- Url::removeQuery — Removes a specific query string parameter
- Url::removeUsername — Removes the username from the URL; also removes the password.
- Url::setFragment — Sets the #fragment in the URL
- Url::setFullQuery — Overwrites the query with a complete new query
- Url::setHostname — Sets the hostname of the URL
- Url::setPassword — Sets the password in the URL
- Url::setPath — Changes the path in the URL
- Url::setPort — Sets the port
- Url::setQuery — Sets a specific query string parameter
- Url::setUsername — Sets the username in the URL
- Url::__toString — Gets a string representation of the object
- Url::current — Returns a URL object based on the $_SERVER global (the current request)
- Url::__set_state — This static method is called for classes exported by
var_export()
.
Model\Ipv4Address
Class example
The Ipv4Address
model is also used in the IpTools
service, but it can also help with different notations
and even calculate complete subnets;
$ip = new \Garrcomm\Netutils\Model\Ipv4Address('192.168.1.1', '255.255.255.0');
echo 'CIDR notation: ' . $ip->getCidrAddress() . PHP_EOL;
echo 'Broadcast address: ' . $ip->getBroadcastAddress() . PHP_EOL;
echo 'Network address: ' . $ip->getNetworkAddress() . PHP_EOL;
echo 'Amount of IP\'s in range: ' . count($ip->getIpRange()) . PHP_EOL;
Class synopsis
class Ipv4Address implements JsonSerializable {
/* Methods */
public __construct(?string|integer ipAddress = null, ?string|integer subnetAddress = null)
public getBitMask(): int
public getBroadcastAddress(): string
public getCidrAddress(): string
public getIpAddress(): string
public getIpRange(): Ipv4Address[]|Ipv4Range
public getNetworkAddress(): string
public getSubnetAddress(): string
public jsonSerialize(): mixed
public setBitMask(integer bitMask): Ipv4Address
public setCidrAddress(string ipMask): Ipv4Address
public setIpAddress(?string|integer ipAddress): Ipv4Address
public setSubnetAddress(?string|integer subnetAddress): Ipv4Address
public __toString(): string
public static __set_state(mixed[] state): self
}
Methods
Ipv4Address::__construct — Creates a new IP entity
Input can be an IP address as integer, regular, or in CIDR format.
Ipv4Address::getBitMask — Returns the bitmask presentation of the subnet
- Ipv4Address::getBroadcastAddress — Returns the broadcast address
- Ipv4Address::getCidrAddress — Returns the IP address in CIDR notation
- Ipv4Address::getIpAddress — Returns the IP address
- Ipv4Address::getIpRange — Returns the full IP range in this network
- Ipv4Address::getNetworkAddress — Returns the network address
- Ipv4Address::getSubnetAddress — Returns the subnet address
- Ipv4Address::jsonSerialize — JsonSerializable::jsonSerialize — Specify data which should be serialized to JSON
- Ipv4Address::setBitMask — Sets the bitmask presentation of the subnet
- Ipv4Address::setCidrAddress — Fills this entity with an IP address based on CIDR notation
- Ipv4Address::setIpAddress — Sets the IP address
- Ipv4Address::setSubnetAddress — Sets the subnet address
- Ipv4Address::__toString — Gets a string representation of the object
- Ipv4Address::__set_state — This static method is called for classes exported by
var_export()
.
Model\Ipv4Range
Class example
You can use this object as an array:
// Defines a range
$range = new \Garrcomm\Netutils\Model\Ipv4Range('192.168.2.0', 24);
// Uses the Countable interface to return the amount of IPs in range
echo 'Amount of IPs in the range: ' . count($range) . PHP_EOL;
// Uses the Iterator interface to walk through the results
foreach ($range as $ip) {
echo '- ' . $ip . PHP_EOL;
}
// Uses the ArrayAccess interface to walk through the results
for ($i = 0; $i < count($range); ++$i) {
echo '- ' . $range[$i] . PHP_EOL;
}
// Returns a json array with all IPs in range
echo json_encode($range, JSON_PRETTY_PRINT);
// Returns the IP range as string
echo $range . PHP_EOL;
Class synopsis
class Ipv4Range implements Iterator, Countable, ArrayAccess, JsonSerializable, Traversable {
/* Methods */
public __construct(string|integer networkAddress, integer bitMask)
public count(): int
public current(): mixed
public jsonSerialize(): mixed
public key(): mixed
public next(): void
public offsetExists(mixed offset): bool
public offsetGet(mixed offset): mixed
public offsetSet(mixed offset, mixed value): void
public offsetUnset(mixed offset): void
public rewind(): void
public valid(): bool
public __toString(): string
public static __set_state(mixed[] state): self
}
Methods
- Ipv4Range::__construct — Constructs an IPv4 range
- Ipv4Range::count — Countable::count — Count elements of an object
- Ipv4Range::current — Iterator::current — Return the current element
- Ipv4Range::jsonSerialize — JsonSerializable::jsonSerialize — Specify data which should be serialized to JSON
- Ipv4Range::key — Iterator::key — Return the key of the current element
- Ipv4Range::next — Iterator::next — Move forward to next element
- Ipv4Range::offsetExists — ArrayAccess::offsetExists — Whether an offset exists
- Ipv4Range::offsetGet — ArrayAccess::offsetGet — Offset to retrieve
- Ipv4Range::offsetSet — ArrayAccess::offsetSet — Assign a value to the specified offset
- Ipv4Range::offsetUnset — ArrayAccess::offsetUnset — Unset an offset
- Ipv4Range::rewind — Iterator::rewind — Rewind the Iterator to the first element
- Ipv4Range::valid — Iterator::valid — Checks if current position is valid
- Ipv4Range::__toString — Gets a string representation of the object
- Ipv4Range::__set_state — This static method is called for classes exported by
var_export()
.
Model\MacAddress
Class synopsis
class MacAddress implements JsonSerializable {
/* Constants */
public const LOWERCASE = 0;
public const UPPERCASE = 1;
/* Methods */
public __construct(string macAddress)
public format(string separator = ':', integer casing = 0): string
public jsonSerialize(): mixed
public set(string macAddress): MacAddress
public __toString(): string
public static __set_state(mixed[] state): self
}
Constants
MacAddress::LOWERCASE
MacAddress::UPPERCASE
Methods
- MacAddress::__construct — Initializes a new MAC address model.
- MacAddress::format — Get a string representation of the MAC address
- MacAddress::jsonSerialize — JsonSerializable::jsonSerialize — Specify data which should be serialized to JSON
- MacAddress::set — Set a new value
- MacAddress::__toString — Gets a string representation of the object
- MacAddress::__set_state — This static method is called for classes exported by
var_export()
.
Model\DnsResult
Class synopsis
class DnsResult implements JsonSerializable {
/* Methods */
public __construct(string question, DnsAnswer[] answers, string dnsHostname, string dnsAddress)
public getAnswers(boolean sorted = false): DnsAnswer[]
public getDnsAddress(): string
public getDnsHostname(): string
public getQuestion(): string
public jsonSerialize(): mixed
public __toString(): string
public static __set_state(mixed[] state): self
}
Methods
- DnsResult::__construct — Constructs a DNS result
- DnsResult::getAnswers — Returns all given answers
- DnsResult::getDnsAddress — The address of the DNS server.
- DnsResult::getDnsHostname — Returns the hostname of the DNS server.
- DnsResult::getQuestion — Returns the original DNS question
- DnsResult::jsonSerialize — JsonSerializable::jsonSerialize — Specify data which should be serialized to JSON
- DnsResult::__toString — Gets a string representation of the object
- DnsResult::__set_state — This static method is called for classes exported by
var_export()
.
Model\DnsAnswer
Class synopsis
class DnsAnswer implements JsonSerializable {
/* Methods */
public __construct(string type, string result, integer ttl, ?integer priority)
public getPriority(): int
public getResult(): string
public getTtl(): int
public getType(): string
public jsonSerialize(): mixed
public __toString(): string
public static __set_state(mixed[] state): self
}
Methods
- DnsAnswer::__construct — Constructs a DNS result
- DnsAnswer::getPriority — Returns the priority, if known
- DnsAnswer::getResult — Returns the result
- DnsAnswer::getTtl — Returns the amount of seconds in which the record expires
- DnsAnswer::getType — Returns the type of the record (One of the Dns:: constants)
- DnsAnswer::jsonSerialize — JsonSerializable::jsonSerialize — Specify data which should be serialized to JSON
- DnsAnswer::__toString — Gets a string representation of the object
- DnsAnswer::__set_state — This static method is called for classes exported by
var_export()
.