PHP netMatch ipv6 and 4

netMatch ipv6 version 6 ip addresses

A PHP based netMatch function updated to match ipv6 (version 6 and 4) ip addresses to multiple mixed networks.

Supports all network representations that satisfy php’s inet_pton(), which includes ipv6 condensed ‘::1′ and alternative ”fe80:0:0:0:0:0:192.168.1.64’ addresses.

# netmatch6 cobbled 2/16, Classless inter-domain routing (CIDR)
# inspired by various at php.net/manual/en/function.ip2long.php, stephane at deluca dot biz 2006
# Supports ipv4 and ipv6 Condensed and Alternative ( ip portion of cidr nust pass php's inet_pton() ):
#  $CIDRs[] = "fe80::c0a8:140/124";
#  $CIDRs = array( '::1/128', '127.0.0.1/32', '192.168.1.64/28', 'fe80:0:0000:0:0:0:c0a8:140/124', 'fe80:0:0:0:0:0:192.168.1.64/124');
# relies on functions: filter_var, custom ip2bin, and inet_pton
# returns bool true or string
#
function netMatch6 ( $CIDRs = array(), $ip = '::1' ) {
    $ip_is_in_the_net = false;
 $msg = "";
 # ip4
 if( false !== $ip_f = filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) ) {
  $mask_min = 0; $mask_max = 32;
 }
 # ip6
 elseif( false !== $ip_f = filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ) ) {
  $mask_min = 12; $mask_max = 128;     # Cisco CCNA: Network Basics, Ch 7, Lab D, 2013
 }
 else return "Apparently $ip is NOT a valid v4 nor v6 address"; //  die( $ip );
 $ip_bin_str = ip2bin( $ip_f );
 
 foreach ($CIDRs as $cidr)
 {
  list( $net, $mask ) = explode( '/', $cidr );
  if( false === $net_f = filter_var( $net, FILTER_VALIDATE_IP ) ) return "Invalid \$net $net"; // die( var_dump( $net ) );
  # gotta let the next one fail silent in case a subsequent net matches
  if( false === $mask_f = filter_var( $mask, FILTER_VALIDATE_INT, array( "options" => array( "min_range"=>$mask_min, "max_range"=>$mask_max ) ) ) ) $msg .= "Bitmask $mask is outside the range $mask_min to $mask_max | ";
  $net_bin_str = ip2bin( $net_f );
  //die( "$ip_bin_str = \$ip_bin_str <br /> $net_bin_str = \$net_bin_str <br /> & \$mask = $mask on line ".__LINE__ );
  if( 0 == strncmp( $net_bin_str, $ip_bin_str, $mask_f ) ) return $ip_is_in_the_net = true;
 }
 return $msg; # could not find a CIDR network that includes the ip address passed in

} # end netMatch


# return string representation of an ip(4|6) address converted to a binary number
# inspired by anjo2 2006 php.net/manual/en/function.ip2long.php#104163
# relies on inet_pton()
#
function ip2bin ( $ip )
{
    # filter user provided ips if you haven't already
 $ipbin = "";
    if( ( $ip_n = inet_pton( $ip ) ) === false ) return false; // die( strlen( $ip_n )." on line ".__LINE__ );
 $bytes = strlen( $ip_n ) - 1; # going to retrieve from the zero ordinal
    while ($bytes >= 0)
    {
        $bin = sprintf( "%08b", ord( $ip_n[ $bytes ] ) );
        $ipbin = $bin.$ipbin;
        $bytes--;
    }
    return $ipbin;
 
} # end ip2bin

 

Published
Categorized as PHP