0) return true; } return false; } function normalize_ip($ip) { if (validate_ip4($ip)) return $ip; if (validate_ip6($ip)) { /* trim leading zeroes in any given 4-nibble word. */ $ip = preg_replace("/(^|:)0+([a-fA-F0-9])/", "\\1\\2", $ip); $parts = explode("::", $ip); if (count($parts) == 1) return $ip; /* :: can be both leading and trailing */ if (!$parts[0]) /* leading :: */ $parts[0] = "0"; if (!$parts[1]) /* trailing :: */ $parts[1] = "0"; $ccount = count(explode(":", $parts[0])) + count(explode(":", $parts[1])); $ins = ":"; while ($ccount++ < 8) $ins .= "0:"; return $parts[0].$ins.$parts[1]; } return NULL; } function ip_version($ip) { if (validate_ip4($ip)) return 4; if (validate_ip6($ip)) return 6; return false; } function validate_ip($ip) { return validate_ip4($ip) || validate_ip6($ip); } function validate_ip4($ip) { return ip2long($ip) !== FALSE; } function validate_ip6($ip) { $double = false; $ip = strtolower($ip); $parts = explode(':', $ip); if (count($parts) > 8) /* IPv6 addresses comes in blocks of 4-nibble blocks of 16 bits, or 8 blocks */ return false; if (count($parts) == 1) /* Want at least one : */ return false; /* Special case of leading :: */ if (count($parts) > 1 && !$parts[0]) { if (!$parts[1]) { array_shift($parts); array_shift($parts); $double = true; if (count($parts) == 0) return false; /* : is not valid */ if (count($parts) == 1 && $parts[0] == "") return true; /* :: is "any", which is legal/valid. */ } else { /* Address starting with :something - invalid? */ return false; } } if (count($parts) > 1 && !$parts[count($parts) - 1]) { if ($parts[count($parts) - 2]) { /* Address ending with :something - invalid? */ return false; } else { if ($double) return false; array_pop($parts); array_pop($parts); $double = true; } } foreach ($parts as $p) { if ($p == "") { /* :: use-case, or fill out with zeroes */ if ($double) { return false; /* only one such allowed */ } $double = true; } else if (!preg_match('/^[0-9a-f]{1,4}$/', $p)) { return false; } } if (!$double && count($parts) < 8) return false; /* Unless a :: we should have exactly 8 blocks */ return true; } function ip2range($range) { if (preg_match(",^([0-9.]+)/([0-9]+)$,", $range, $p)) { $ip = ip2long($p[1]); $mask = $p[2]; if ($ip === FALSE || $mask > 32) return [NULL, NULL, NULL]; $rangesize = pow(2, 32-$mask); $ip &= 0xFFFFFFFF & ~($rangesize-1); return [long2ip($ip), long2ip($ip - 1 + $rangesize), $mask]; } elseif (preg_match(",^([0-9.]+)-([0-9.]+)$,", $range, $p)) { $ip1 = ip2long($p[1]); $ip2 = ip2long($p[2]); if ($ip1 === FALSE || $ip2 === FALSE) return [NULL, NULL]; if ($ip1 > $ip2) { $ip1 ^= $ip2; $ip2 ^= $ip1; $ip1 ^= $ip2; } // See if we can calulate some matching mask. $mask = 0xFFFFFFFF; $msize = 0; while (($ip1 & $mask) != 0) { $mask >>= 1; $msize++; } while (($ip2 & $mask) != $mask) { $mask >>= 1; $msize++; } if (($ip1 | $mask) != $ip2) $msize = NULL; return [long2ip($ip1), long2ip($ip2), $msize]; } else return [NULL, NULL]; } /* assume the string is a valid IP address */ function ip_is_private($ipaddress) { return preg_match("/^(192[.]168[.]|10[.]|172[.](1[2-9]|2[0-9]|3[01])[.]|f[cd]00:)/", $ipaddress); } function ip_is_lsn($ipaddress) { return preg_match("/^100[.](6[4-9]|[7-9][0-9]|1[01][0-9]|12[0-7])[.]/", $ipaddress); } function ip_is_localhost($ipaddress) { return preg_match("/^(127[.]|::1$)/", $ipaddress); } function ip_is_multicast($ipaddress) { return preg_match("/^(ff[^:]{2}:|22[4-9][.]|23[0-9][.])/", $ipaddress); } function ip_is_linklocal($ipaddress) { return preg_match("/^(169[.]254[.]|fe80::)/", $ipaddress); } function ip_is_public($ipaddress) { return !ip_is_localhost($ipaddress) && !ip_is_private($ipaddress) && !ip_is_linklocal($ipaddress) && !ip_is_multicast($ipaddress) && !ip_is_lsn($ipaddress); } function ip_is_v4mappedv6($ipaddress) { if (preg_match("/^::ffff:([0-9.]+)$/", $ipaddress, $p) && validate_ip4($p[1])) return $p[1]; return false; } function ip_unmapped($ipaddress) { return ip_is_v4mappedv6($ipaddress) ?: $ipaddress; } function ip_mapped($ipaddress) { if (validate_ip4($ipaddress)) return "::ffff:".$ipaddress; if (validate_ip6($ipaddress)) return $ipaddress; return NULL; } ?>