Netmask class - parse, manipulate and lookup IP network blocks

From: Date: Fri, 25 Jul 2003 06:44:01 +0000
Subject: Netmask class - parse, manipulate and lookup IP network blocks
Groups: php.pear.dev 
Request: Send a blank email to pear-dev+get-18672@lists.php.net to get a copy of this message
<?php // Netmask class - parse, manipulate and lookup IP network blocks // Copyright (C) 1998, 2001 David Muir Sharnoff <muir@idiom.com> // Net::Netmask ported from Perl to PHP by Dennis S.Davidoff <null@1system.ru> // TODO: // Methods: hostmask, storeNetblock, deleteNetblock // Functions: findNetblock, findOuterNetblock, findAllNetblock, cidrs2contiglists, by_net_netmask_block class Netmask { var $error, $IBASE, $BITS; var $remembered = array(); var $netblock = array(); var $quadmask2bits = array(); var $imask2bits = array(); var $size2bits = array(); var $debug = true; function init($net = '', $mask = '') { unset($this->error); for ($i = 0; $i <= 32; $i++) { $imask = $this->imask($i); $this->imask2bits["$imask"] = $i; $this->quadmask2bits[$this->int2quad($imask)] = $i; $k = pow(2, (32-$i)); $size2bits["$k"] = $i; } if (preg_match("/^(\d+\.\d+\.\d+\.\d+)\/(\d+)$/", $net, $matched)) { $base = $matched[1]; $bits = $matched[2]; } elseif (preg_match("/^(\d+\.\d+\.\d+\.\d+)[:\/](\d+\.\d+\.\d+\.\d+)$/", $net, $matched)) { $base = $matched[1]; $quadmask = $matched[2]; if (array_key_exists($quadmask, $this->quadmask2bits)) { $bits = $this->quadmask2bits[$quadmask]; } else { $this->error = "illegal netmask: $quadmask"; } } elseif ( preg_match("/^\d+\.\d+\.\d+\.\d+$/", $net) && preg_match("/\d+\.\d+\.\d+\.\d+$/", $mask) ) { $base = $net; if (array_key_exists($mask, $this->quadmask2bits)) { $bits = $this->quadmask2bits[$mask]; } else { $this->error = "illegal netmask: $mask"; } } elseif (preg_match("/^\d+\.\d+\.\d+\.\d+$/", $net) && preg_match("/0x([a-z0-9]+)/", $mask, $matched)) { $base = $net; $imask = hexdec($matched[1]); if (array_key_exists("$imask", $this->imask2bits)) { $bits = $this->imask2bits["$imask"]; } else { $this->error = "illegal netmask: $imask"; } } elseif (preg_match("/^\d+\.\d+\.\d+\.\d+$/", $net) && empty($mask)) { $base = $net; $bits = 32; } elseif (preg_match("/^\d+\.\d+\.\d+$/", $net) && empty($mask)) { $base = "$net.0"; $bits = 24; } elseif (preg_match("/^\d+\.\d+$/", $net) && empty($mask)) { $base = "$net.0.0"; $bits = 16; } elseif (preg_match("/^\d+$/", $net) && empty($mask)) { $base = "$net.0.0.0"; $bits = 8; } elseif (preg_match("/^(\d+\.\d+\.\d+)\/(\d+)$/", $net, $matched)) { $base = $matched[1] . ".0"; $bits = $matched[2]; } elseif (preg_match("/^(\d+\.\d+)\/(\d+)$/", $net, $matched)) { $base = $matched[1] . ".0.0"; $bits = $matched[2]; } elseif ($net == 'default') { $base = '0.0.0.0'; $bits = 0; } elseif (preg_match("/^(\d+\.\d+\.\d+\.\d+)\s*\-\s*(\d+\.\d+\.\d+\.\d+)$/", $net, $matched)) { $ibase = $this->quad2int($matched[1]); $end = $this->quad2int($matched[2]); if ($ibase == false || $end == false) $this->error = "illegal dotted quad: $net"; $diff = ($end == false ? 0 : $end) - ($ibase == false ? 0 : $ibase) + 1; if (!array_key_exists("$diff", $size2bits) && empty($this->error)) $this->error = "could not find exact fit for $net"; else $bits = $size2bits{"$diff"}; } else { $this->error = "could not parse $net"; if (!empty($mask)) $this->error .= " $mask"; } if ($this->debug == true && !empty($this->error)) die($this->error); if (!isset($ibase)) { if (($ibase = $this->quad2int( isset($base) ? $base : 0)) == false && empty($this->error)) { $this->error = "could not parse $net"; if (!empty($mask)) $this->error .= " $mask"; } else { $ibase += 0; $ibase = sprintf('%u', ($ibase &= $this->imask($bits))); } } $this->IBASE = $ibase + 0; $this->BITS = $bits; if ($this->debug == true && !empty($this->error)) die($this->error); return empty($this->error) ? true : false; } function imask ($i) { return pow(2, 32) - pow(2, (32 - $i)); } function errstr () { return $this->error; } function bits () { return $this->BITS; } function base () { return $this->int2quad($this->IBASE); } function size () { return pow(2, (32 - $this->BITS)); } function next () { $this->int2quad($this->IBASE + $this->size()); } function mask () { return $this->int2quad ( $this->imask($this->BITS)); } function desc () { return $this->int2quad($this->IBASE).'/'.$this->BITS; } function int2quad ($n) { return implode('.', unpack('C4', pack("N", $n))); } function broadcast () { return $this->int2quad($this->IBASE + $this->size() - 1); } function nth ($index = 1, $bitstep = 0) { $size = $this->size(); $ibase = $this->IBASE; if ($bitstep == 0) $bitstep = 32; $increment = pow(2, (32-$bitstep)); $index *= $increment; if ($index < 0) $index += $size; if ($index < 0) return false; if ($index >= $size) return false; return $this->int2quad($ibase+$index); } function enumerate ($bitstep = 0) { $size = $this->size(); $ibase = $this->IBASE; if ($bitstep == 0) $bitstep = 32; $increment = pow(2, (32-$bitstep)); for ($i = 0; $i < $size; $i += $increment) { $array[] = $this->int2quad($ibase+$i); } return $array; } function inaddr () { $ibase = $this->IBASE; $blocks = intval($this->size()/256); if ($blocks == 0) return array( implode('.', unpack('x/C3', pack("V", $ibase))) . ".in-addr.arpa", fmod($ibase, 256), fmod($ibase, 256) + $this->size() - 1 ); for ($i = 0; $i < $blocks; $i++) { $array[] = array(implode('.', unpack('x/C3', pack("V", $ibase + $i*256))) . ".in-addr.arpa", 0, 255); } return $array; } function quad2int ($ip) { $bytes = split('\.', $ip); if (count($bytes) == 4) { for ($i = 0; $i < count($bytes); $i++) if ($bytes[$i] > 255) return false; else eval("\$oct$i = $bytes[$i];"); } else { $this->error = "quad2int(): illegal ipaddr: $ip"; if ($this->debug == true && !empty($this->error)) die($this->error); return false; } $assoc_array = unpack("Nipaddr", pack('C4', $oct0, $oct1, $oct2, $oct3)); return sprintf('%u', $assoc_array['ipaddr']); } function imaxblock ($ibase, $tbit) { while($tbit > 0) { $im = $this->imask($tbit-1); if ((sprintf('%u', $ibase & $im)) != $ibase) break; $tbit--; } return $tbit; } function sort_by_ip_address ($array) { if (is_array($array)) { natsort($array); return $array; } else return false; } function range2cidrlist ($startip, $endip) { if (($start = $this->quad2int($startip)) == false) { $this->error = "range2cidrlist(): illegal \$startip: $startip"; if ($this->debug == true && !empty($this->error)) die($this->error); return false; } if (($end = $this->quad2int($endip)) == false) { $this->error = "range2cidrlist(): illegal \$startip: $startip"; if ($this->debug == true && !empty($this->error)) die($this->error); return false; } $start += 0; $end += 0; if ($start > $end) { $k = $end; $end = $start; $start = $k; } while($end >= $start) { $maxsize = $this->imaxblock($start, 32); $maxdiff = 32 - intval(log($end - $start + 1)/log(2)); if ($maxsize < $maxdiff) $maxsize = $maxdiff; $array[] = $this->int2quad($start)."/$maxsize"; $start += pow(2, (32 - $maxsize)); } return $array; } function match ($ipaddr) { if (($i = $this->quad2int($ipaddr)) == false) { $this->error = "match(): illegal ipaddr: $ipaddr"; if ($this->debug == true && !empty($this->error)) die($this->error); return false; } $i += 0; $imask = $this->imask($this->BITS); if ((sprintf('%u',($i & $imask))) == $this->IBASE) return (($i & ~$imask) || "0 "); else return 0; } } ?>

« previous php.pear.dev (#18672) next »