|
ip2long
Converts a string containing an (IPv4) Internet Protocol dotted address into a proper address
(PHP 4, PHP 5)
Example 1606. ip2long() Example<?php Example 1607. Displaying an IP addressThis second example shows how to print a converted address with the printf() function in both PHP 4 and PHP 5: <?php Example 1608. IP validationip2long() should not be used as the sole form of IP validation. Combine it with long2ip(): <?php Code Examples / Notes » ip2longrbsmith
Yet another word on IP_Match here is the complete functions as described by php-net at dreams4net dot com on 08-Aug-2002 09:31 # determine if an IP address is within # a particular network with mask function IP_Match($network, $mask, $ip) { $ip_long=ip2long($ip); $network_long=ip2long($network); $mask_long=ip2long($mask); if (($ip_long & $mask_long) == $network_long) { return true; } else { return false; } } Thank you, it is simple, fast, and best of all works! polarina
Using the option that "paul at santasoft point com" mentioned will make IP Addresses larger than 2147483647 (Around 128.0.0.0) become 2147483647 and it wont go higher than that. So it's not recommended to use his solution. paul
to complement daevid at daevid dot com's note (11 Nov 2004) about the catch being that PHP returns negative values.... If you define your mysql column that stores the ip address in INT format as signed (not unsigned), then it'll work just fine. No need to do any conversion using sprintf and this way you'll keep the value and be able to use PHP's long2ip() function on the value and get an accurate result. SO.. define your MySQL column as signed (leave the Attributes select box in phpMyAdmin blank) and you won't need to do any conversions or whatnot. daevid
This seems obvious in hindsight, but since nobody else posted it, it had me and two others scratching our heads. Thought I'd save someone else the trouble... In mySQL, you can use the INET_ATON() function, but to save queries, you could use this function. However, the catch is that PHP returns negative values, so you have to use it like this: $LongIP = sprintf('%u', ip2long($dotted_name)); sunfire
The original function was writen by J.Adams <jna@retina.net> see this page. I found a mistake his code, and make it a little simpler. function testip($range,$ip) { ..... $maskl = 0; for ($i = 0; $i < $regs[5]-1; $i++) { $maskl += pow(2,(31-$i)); } if (($maskl & $rangel) == ($maskl & $ipl)) { ..... } jbothe
The following script will print out subnet statistics when you supply the IP Address and Subnet Mask. Usefull to calculate the broadcast address and network address as well as the number of hosts and the range of IP addresses in the subnet. #!/usr/local/bin/php <? $ip_addr = "172.14.1.57"; $subnet_mask = "255.255.255.0"; $ip = ip2long($ip_addr); $nm = ip2long($subnet_mask); $nw = ($ip & $nm); $bc = $nw | (~$nm); echo "IP Address: " . long2ip($ip) . "\n"; echo "Subnet Mask: " . long2ip($nm) . "\n"; echo "Network Address: " . long2ip($nw) . "\n"; echo "Broadcast Address: " . long2ip($bc) . "\n"; echo "Number of Hosts: " . ($bc - $nw - 1) . "\n"; echo "Host Range: " . long2ip($nw + 1) . " -> " . long2ip($bc - 1) . "\n"; ?> Produces the output: IP Address: 172.14.1.57 Subnet Mask: 255.255.255.0 Network Address: 172.14.1.0 Broadcast Address: 172.14.1.255 Number of Hosts: 254 Host Range: 172.14.1.1 -> 172.14.1.254 frank
remixing mediator's function further: <?php function matchCIDR($addr, $cidr) { list($ip, $mask) = explode('/', $cidr); return (ip2long($addr) >> (32 - $mask) == ip2long($ip) >> (32 - mask)); } ?> greg
Re: m.ozarek's isIpMask() function You might want to adjust your preg_match line from: if(preg_match("/[0-9].[0-9].[0-9].[0-9]/",$mask)){ to if(preg_match("/[0-9]++\.[0-9]++\.[0-9]++\.[0-9]++/",$mask)){ this should properly match up to 3 characters per octet and require that the periods be periods not just any character. I tested against a handful of IPs, and it seemed to match fine, and did not allow a 7 digit number to be considered a mask to check. This is probably more useful if doing a match against a regular IP than against the subnet mask, but its always good to have more layers of checking. *note.. not all applications support the regex + metacharacter. novikov
Please not , that the results of ip2long on 64bit servers is different form 32bit. Take a look here: http://bugs.php.net/bug.php?id=18816 It's a feature, that ip2long on 64bit always returned UNSIGNED result like after spitf("%u\n",ip2long()); jna
One thing PHP lacks is a way to compare two IP addresses, which I thought might be under this function, but isn't. Here goes: function testip($range,$ip) { $result = 1; # IP Pattern Matcher # J.Adams <jna@retina.net> # # Matches: # # xxx.xxx.xxx.xxx (exact) # xxx.xxx.xxx.[yyy-zzz] (range) # xxx.xxx.xxx.xxx/nn (nn = # bits, cisco style -- i.e. /24 = class C) # # Does not match: # xxx.xxx.xxx.xx[yyy-zzz] (range, partial octets not supported) if (ereg("([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/([0-9]+)",$range,$regs)) { # perform a mask match $ipl = ip2long($ip); $rangel = ip2long($regs[1] . "." . $regs[2] . "." . $regs[3] . "." . $regs[4]); $maskl = 0; for ($i = 0; $i< 31; $i++) { if ($i < $regs[5]-1) { $maskl = $maskl + pow(2,(30-$i)); } } if (($maskl & $rangel) == ($maskl & $ipl)) { return 1; } else { return 0; } } else { # range based $maskocts = split("\.",$range); $ipocts = split("\.",$ip); # perform a range match for ($i=0; $i<4; $i++) { if (ereg("\[([0-9]+)\-([0-9]+)\]",$maskocts[$i],$regs)) { if ( ($ipocts[$i] > $regs[2]) || ($ipocts[$i] < $regs[1])) { $result = 0; } } else { if ($maskocts[$i] <> $ipocts[$i]) { $result = 0; } } } } return $result; } ian b
NOTE: ip2long() should NOT be used for CIDR calculation. Instead, you should use something like the following: <?php /* get the base and the bits from the ban in the database */ list($base, $bits) = explode('/', $CIDR); /* now split it up into it's classes */ list($a, $b, $c, $d) = explode('.', $base); /* now do some bit shfiting/switching to convert to ints */ $i = ($a << 24) + ($b << 16) + ($c << 8) + $d; $mask = $bits == 0 ? 0 : (~0 << (32 - $bits)); /* here's our lowest int */ $low = $i & $mask; /* here's our highest int */ $high = $i | (~$mask & 0xFFFFFFFF); /* now split the ip were checking against up into classes */ list($a, $b, $c, $d) = explode('.', $iptocheck); /* now convert the ip we're checking against to an int */ $check = ($a << 24) + ($b << 16) + ($c << 8) + $d; /* if the ip is within the range, including highest/lowest values, then it's witin the CIDR range */ if ($check >= $low && $check <= $high) return 1; else return 0; ?> This means that you should check to see if the IP address is of the correct format each time. paragina silviu
Note: ip2long and long2ip do not function as the c linux functions inet_addr and inet_ntoa. They store the long in reverse byte order (little endian vs big endian i guess). For example you send 10.0.0.1 to inet_ntoa you take the long from the result and you pass it to long2ip you get 1.0.0.10. You won't run into this issue unless you use a database both from c linux programs and php scripts. My first ideea was to reverse the long, but unfortunatley the long was stored as unsigned and i got a lot of problems doing calculations with it (some operations would work well others not; probably it was stored as float i do not know for sure...) So my solution was function str_rev_ip($str) { $ar=explode(".",$str); return "$ar[3].$ar[2].$ar[1].$ar[0]"; } and i take the result from inet_ntoa and parse it as str_rev_ip(long2ip($var)) dzver
Mix of rbsmith's function and pasted above url: <? // returns 1 if $ip is part of $network function IP_Match($network, $ip) { $ip_arr = explode("/",$network); $network_long=ip2long($ip_arr[0]); $mask_long= pow(2,32)-pow(2,(32-$ip_arr[1])); $ip_long=ip2long($ip); if (($ip_long & $mask_long) == $network_long) { return 1; } else { return 0; } } // usage $network="200.100.50.0/23"; $ip="200.100.51.55"; $ip2="200.100.52.2"; echo IP_Match($network, $ip); //prints 1 echo IP_Match($network, $ip2); //prints 0 ?> ir on ir id is
Keep in mind that storing IP addresses inside of your database as integers (rather than 15 character strings in decimal format, or 8 character strings in hex format) is hundreds of times faster. Take the typical case of a MySQL database doing a search for an IP address on thousands (or millions!) of rows; you're either doing a string compare for each entry, or an integer equation. If you do your indexes correctly, your lookups should be literally 100x faster using an INT rather than a VARCHAR. Also note that an integer doesn't need to be escaped when passed to a database. :) laacz
Just to save you some time. Beware that octets in IP address are being treated as numbers. So, '10.0.0.11' is not equal to '10.0.0.011'. '011' is octal number (base 8), so it converts to '9'. You can even go further and see that '10.0.0.0xa' also works (equals to '10.0.0.16'). This is not PHP issue, though. anderson
If you want to get the interface of an IP, based on the local route table, use this. function GetIfaceforIP($user_ip) { $route = "/bin/netstat -rn"; exec($route, $aoutput); foreach($aoutput as $key => $line) { if($key > 1) { $line = ereg_replace("[[:space:]]+",",",$line); list($network, $gateway, $mask, $flags, $mss, $window, $irtt, $iface) = explode(",", $line) if((ip2long($user_ip) & ip2long($mask)) == ip2long($network)) { return $iface; } } } } mkr
If you want to expand IP ranges, for instance: 111.111.111.0/24 You can get the function here - improved with more features and bug fixed: http://binarywerks.dk/php_src/expand_CIDR.phps one tiger one
I wrote a small function to validate a netmask (We have a form where the netmask of a given server is entered in, and I wanted to make sure it was valid). Hope this is useful. // Netmask Validator // function checkNetmask($ip) { if (!ip2long($ip)) { return false; } elseif(strlen(decbin(ip2long($ip))) != 32 && ip2long($ip) != 0) { return false; } elseif(ereg('01',decbin(ip2long($ip))) || !ereg('0',decbin(ip2long($ip)))) { return false; } else { return true; } } 01-dec-2004 02:06
I re-wrote the functions from jbothe at hotmail dot com as a little exercise in OO and added a couple of extra functions. <?php //-------------- // IPv4 class class ipv4 { var $address; var $netbits; //-------------- // Create new class function ipv4($address,$netbits) { $this->address = $address; $this->netbits = $netbits; } //-------------- // Return the IP address function address() { return ($this->address); } //-------------- // Return the netbits function netbits() { return ($this->netbits); } //-------------- // Return the netmask function netmask() { return (long2ip(ip2long("255.255.255.255") << (32-$this->netbits))); } //-------------- // Return the network that the address sits in function network() { return (long2ip((ip2long($this->address)) & (ip2long($this->netmask())))); } //-------------- // Return the broadcast that the address sits in function broadcast() { return (long2ip(ip2long($this->network()) | (~(ip2long($this->netmask()))))); } //-------------- // Return the inverse mask of the netmask function inverse() { return (long2ip(~(ip2long("255.255.255.255") << (32-$this->netbits)))); } } $ip = new ipv4("192.168.2.1",24); print "Address: $ip->address()\n"; print "Netbits: $ip->netbits()\n"; print "Netmask: $ip->netmask()\n"; print "Inverse: $ip->inverse()\n"; print "Network: $ip->network()\n"; print "Broadcast: $ip->broadcast()\n"; ?> stephane
I propose a new function to match an IP against a network. You can define the network in two different manner, most suited for handling data grabed from WHOIS records: - 202.1.192.0-202.1.192.255: a range of IPs - 200.36.161.0/24: a range of IP by using net masking - 200.36.161/24: a shorten syntax similar to the above. Sdl <?php function netMatch($network, $ip) { $network=trim($network); $ip = trim($ip); $d = strpos($network,"-"); if ($d===false) { $ip_arr = explode('/', $network); if (!preg_match("@\d*\.\d*\.\d*\.\d*@",$ip_arr[0],$matches)){ $ip_arr[0].=".0"; // Alternate form 194.1.4/24 } $network_long = ip2long($ip_arr[0]); $x = ip2long($ip_arr[1]); $mask = long2ip($x) == $ip_arr[1] ? $x : (0xffffffff << (32 - $ip_arr[1])); $ip_long = ip2long($ip); return ($ip_long & $mask) == ($network_long & $mask); } else { $from = trim(ip2long(substr($network,0,$d))); $to = trim(ip2long(substr($network,$d+1))); $ip = ip2long($ip); return ($ip>=$from and $ip<=$to); } } ?> dh06
I made one tiny change to Stephane's routine below when I had problems with spaces in an IP range. I moved the trim function before the ip2long call. Thanks Stephane! Dirk. <?php function netMatch($network, $ip) { $network=trim($network); $ip = trim($ip); $d = strpos($network,"-"); if ($d===false) { $ip_arr = explode('/', $network); if (!preg_match("@\d*\.\d*\.\d*\.\d*@",$ip_arr[0],$matches)){ $ip_arr[0].=".0"; // Alternate form 194.1.4/24 } $network_long = ip2long($ip_arr[0]); $x = ip2long($ip_arr[1]); $mask = long2ip($x) == $ip_arr[1] ? $x : (0xffffffff << (32 - $ip_arr[1])); $ip_long = ip2long($ip); return ($ip_long & $mask) == ($network_long & $mask); } else { $from = ip2long(trim(substr($network,0,$d))); $to = ip2long(trim(substr($network,$d+1))); $ip = ip2long($ip); return ($ip>=$from and $ip<=$to); } } ?> samb057
Here's a simple IP address match checking function. It takes 3 arguments: ip address to check (after ip2long), ip address to check against (after ip2long), and mask to check against (integer 0-32). Just make sure you perform ip2long on the ip addresses before inputting them to the function. function match_ip($check_ip, $match_ip, $match_mask = 32) { for ($i = 0 ; $i < $match_mask ; $i++) { $n = pow(2, 31 - $i) ; if (($n & $check_ip) != ($n & $match_ip)) { return FALSE ; } } return TRUE ; } I've been looking for a function like this for a while, i hope it helps someone. phl
Here's a function I whipped up today to deduce some important network information given a hostname (or its IP address) and its subnet mask: function find_net($host,$mask) { ### Function to determine network characteristics ### $host = IP address or hostname of target host (string) ### $mask = Subnet mask of host in dotted decimal (string) ### returns array with ### "cidr" => host and mask in CIDR notation ### "network" => network address ### "broadcast" => broadcast address ### ### Example: find_net("192.168.37.215","255.255.255.224") ### returns: ### "cidr" => 192.168.37.215/27 ### "network" => 192.168.37.192 ### "broadcast" => 192.168.37.223 ### $bits=strpos(decbin(ip2long($mask)),"0"); $net["cidr"]=gethostbyname($host)."/".$bits; $net["network"]=long2ip(bindec(decbin(ip2long(gethostbyname($host))) & decbin(ip2long($mask)))); $binhost=str_pad(decbin(ip2long(gethostbyname($host))),32,"0",STR_PAD_LEFT); $binmask=str_pad(decbin(ip2long($mask)),32,"0",STR_PAD_LEFT); for ($i=0; $i<32; $i++) { if (substr($binhost,$i,1)=="1" || substr($binmask,$i,1)=="0") { $broadcast.="1"; } else { $broadcast.="0"; } } $net["broadcast"]=long2ip(bindec($broadcast)); return $net; } legetz81
Here is a script that will calculate host range and number of hosts with a given ip address CIDR notation (modified code which was posted by phl AT cyways.com): $ip_addr_cidr = "192.168.37.215/27"; $ip_arr = explode('/', $ip_addr_cidr); $bin = ''; for($i=1;$i<=32;$i++) { $bin .= $ip_arr[1] >= $i ? '1' : '0'; } $ip_arr[1] = bindec($bin); $ip = ip2long($ip_arr[0]); $nm = ip2long($ip_arr[1]); $nw = ($ip & $nm); $bc = $nw | (~$nm); echo "Number of Hosts: " . ($bc - $nw - 1) . "\n"; echo "Host Range: " . long2ip($nw + 1) . " -> " . long2ip($bc - 1) . "\n"; This will produce: Number of Hosts: 30 Host Range: 192.168.37.193 -> 192.168.37.222 jgwright
Here is a modified version of the code posted by legetz81 (AT) yahoo (dot) com. It handles the shorter, and more common, notation: "189.128/11". <?php $ip_addr_cidr = "192.168.37.215/27"; cidr($ip_addr_cidr); function cidr($ip_addr_cidr) { $ip_arr = explode('/', $ip_addr_cidr); $dotcount = substr_count($ip_arr[0], "."); $padding = str_repeat(".0", 3 - $dotcount); $ip_arr[0].=$padding; $bin = ''; for($i=1;$i<=32;$i++) { $bin .= $ip_arr[1] >= $i ? '1' : '0'; } $ip_arr[1] = bindec($bin); $ip = ip2long($ip_arr[0]); $nm = ip2long($ip_arr[1]); $nw = ($ip & $nm); $bc = $nw | (~$nm); echo "Number of Hosts: " . ($bc - $nw - 1) . "\n"; echo "Host Range: " . long2ip($nw + 1) . " -> " . long2ip($bc - 1) . "\n"; /* This will produce: Number of Hosts: 30 Host Range: 192.168.37.193 -> 192.168.37.222 */ } ?> lawpoop
Here is a function that tells you if an ip address is in a CIDR range. However, the CIDR argument can be an array of CIDRs. This was created from other matchCIDR functions in the user notes. function matchCIDR($addr, $cidr) { // $addr should be an ip address in the format '0.0.0.0' // $cidr should be a string in the format '100/8' // or an array where each element is in the above format $output = false; if ( is_array($cidr) ) { foreach ( $cidr as $cidrlet ) { if ( matchCIDR( $addr, $cidrlet) ) { $output = true; } } } else { list($ip, $mask) = explode('/', $cidr); $mask = 0xffffffff << (32 - $mask); $output = ((ip2long($addr) & $mask) == (ip2long($ip) & $mask)); } return $output; } daevid
function CalculateIPRange($iprange) { // Daevid Vincent [daevid@daevid.com] 10.13.03 // This function will return an array of either a negative error code // or all possible IP addresses in the given range. // format is NNN.NNN.NNN.NNN - NNN.NNN.NNN.NNN (spaces are okay) $temp = preg_split("/-/",$iprange, -1, PREG_SPLIT_NO_EMPTY); $QRange1 = $temp[0]; $QRange2 = $temp[1]; if ($QRange2 == "") return array($QRange1); //special case, they didn't put a second quad parameter //basic error handling to see if it is generally a valid IP in the form N.N.N.N if ( preg_match("/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/",$QRange1) != 1 ) return array(-1); if ( preg_match("/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/",$QRange2) != 1 ) return array(-1); $quad1 = explode(".",$QRange1); $quad2 = explode(".",$QRange2); reset ($quad1); while (list ($key, $val) = each ($quad1)) { $quad1[$key] = intval($val); if ($quad1[$key] < 0 || $quad1[$key] > 255) return array(-2); } reset ($quad2); while (list ($key, $val) = each ($quad2)) { $quad2[$key] = intval($val); if ($quad2[$key] < 0 || $quad2[$key] > 255) return array(-2); } $startIP_long = sprintf("%u",ip2long($QRange1)); $endIP_long = sprintf("%u",ip2long($QRange2)); $difference = $endIP_long - $startIP_long; //echo "startIP_long = ".$startIP_long." and endIP_long = ".$endIP_long." difference = ".$difference." "; $ip = array(); $k = 0; for ($i = $startIP_long; $i <= $endIP_long; $i++) { $temp = long2ip($i); //this is a total hack. there must be a better way. $thisQuad = explode(".",$temp); if ($thisQuad[3] > 0 && $thisQuad[3] < 255) $ip[$k++] = $temp; } return $ip; } //CalculateIPRange() someone
For those poor little people using PHP 3, here's an ip2long: <?php if (!function_exists("ip2long")) { function ip2long($ip) { $ex = explode(".", $ip); if (count($ex)!=4) return -1; list($a, $b, $c, $d) = $ex; $a = $a*16777216; $b = $b*65536; $c = $c*256; return $a+$b+$c+$d; } } ?> divinehawk
For PHP5 I had to replace: $mask_long= pow(2,32)-pow(2,(32-$ip_arr[1])); -with- $mask_long = 0xffffffff << (32 - $ip_arr[1]); in dzver's IP_Match Function below. theliberal
Doh! That's what I get for copying the wrong code. The correct code is: <?php function ip2base10($ip) { $parts=explode(".",$ip); $base10=($parts[0]<<24)|($parts[1]<<16)|($parts[2]<<8)|($parts[3]); return $base10; } ?> samb057
Convert an ipv6 address to an base 10 integer function ip2long6($ip) { if (substr_count($ip, '::')) { $ip = str_replace('::', str_repeat(':0000', 8 - substr_count($ip, ':')) . ':', $ip) ; } $ip = explode(':', $ip) ; $r_ip = '' ; foreach ($ip as $v) { $r_ip .= str_pad(base_convert($v, 16, 2), 16, 0, STR_PAD_LEFT) ; } return base_convert($r_ip, 2, 10) ; } ken
Below is a merged form of all various notes, and a better (and correct) network matching function. <?php function net_match($network, $ip) { // determines if a network in the form of 192.168.17.1/16 or // 127.0.0.1/255.255.255.255 or 10.0.0.1 matches a given ip $ip_arr = explode('/', $network); $network_long = ip2long($ip_arr[0]); $x = ip2long($ip_arr[1]); $mask = long2ip($x) == $ip_arr[1] ? $x : 0xffffffff << (32 - $ip_arr[1]); $ip_long = ip2long($ip); // echo ">".$ip_arr[1]."> ".decbin($mask)."\n"; return ($ip_long & $mask) == ($network_long & $mask); } echo net_match('192.168.17.1/16', '192.168.15.1')."\n"; // returns true echo net_match('127.0.0.1/255.255.255.255', '127.0.0.2')."\n"; // returns false echo net_match('10.0.0.1', '10.0.0.1')."\n"; // returns true ?> sealbreaker
As a note : if you are using (PHP 4, PHP 5) and are looking to get the integer value of an IP address, i have found that the following works flawlessly for converting to and from IPv4 and it's integer equivalent. I must give credit elsewhere for this portion of the code (ip2long($ip) & 0x7FFFFFFF) + 0x80000000). I looked but was unable to find the comment where it was included. $ip = "127.0.0.0"; // as an example $integer_ip = (substr($ip, 0, 3) > 127) ? ((ip2long($ip) & 0x7FFFFFFF) + 0x80000000) : ip2long($ip); echo $integer_ip; // integer value of IP address echo long2ip($integer_ip); // convert to an IPv4 formatted address ----------------------- Results are as follows: ----------------------- 2130706432 127.0.0.0 ----------------------- 255.255.255.255 (converts to) 4294967295 (and back to) 255.255.255.255 209.65.0.0 (converts to) 3510697984 (and back to) 209.65.0.0 12.0.0.0 (converts to) 201326592 (and back to) 12.0.0.0 1.0.0.0 (converts to) 16777216 (and back to) 1.0.0.0 mediator
Another function for matching $_SERVER['REMOTE_ADDR'] against CIDR. <?php function matchCIDR($addr, $cidr) { list($ip, $mask) = explode('/', $cidr); $mask = 0xffffffff << (32 - $mask); return ((ip2long($addr) & $mask) == (ip2long($ip) & $mask)); } ?> andrew dot minerd
A somewhat more efficient alternative to convert the signed integer return by ip2long: $float = ((ip2long($ip) & 0x7FFFFFFF) + 0x80000000); cam
A simple function to compare two IP addresses against a netmask. Useful if you're locking down a web app with an IP address, but can't force the IPs to be exactly the same. function ipcompare ($ip1, $ip2, $mask) { $masked1 = ip2long($ip1) & ip2long($mask); // bitwise AND of $ip1 with the mask $masked2 = ip2long($ip2) & ip2long($mask); // bitwise AND of $ip2 with the mask if ($masked1 == $masked2) return true; else return false; } Examples: ipcompare("192.168.1.63","192.168.1.65","255.255.255.0") // true ipcompare("192.168.1.63","192.168.1.65","255.255.255.192") // false tomlove
A quick and efficient way to compare two IPs with a given mask: <? function ipmatch ($ip1, $ip2, $mask) { if ((ip2long($ip1) & ~(pow(2, 32-$mask)-1)) == (ip2long($ip2) & ~(pow(2, 32-$mask)-1))) return true; else return false; } ?> Here's an application of it that selects the best IP given the choice of a (possibly private or invalid) forwarded address or a (possibly proxy) apparent address: <? $a = $_SERVER['HTTP_X_FORWARDED_FOR']; if ($a == '' || ipmatch($a, "10.0.0.0", 8) || ipmatch($a, "172.16.0.0", 12) || ipmatch($a, "192.168.0.0", 16) || ipmatch($a, "255.255.255.255", 32)) $ip = $_SERVER['REMOTE_ADDR']; else $ip = $a; ?> Or use it to ban people: <? $banned_ip = '135.23.12.3'; if (ipmatch($ip, $banned_ip, 32)) die('BANNED!'); ?> The bitwise comparison the function uses can be done in SQL to do ban matches right in your database. mailno
a little function to make a range in this form: 0.0.0.1/0.0.0.255 ==> 0.0.0.1/255 0.0.0.1/255.255.255.255 ==> 0.0.0.1/255.255.255.255 <?php $primo = "62.4.32.0"; $ultimo = "62.4.63.255"; echo do_range($primo,$ultimo); //Example function do_range($primo,$ultimo) { list($a,$b,$c,$d)=explode(".",$primo); list($e,$f,$g,$h)=explode(".",$ultimo); if ($a !== $e) return "$primo/$ultimo"; else { if ($b !== $f) return "$primo/$f.$g.$h"; else{ if ($c !== $g) return "$primo/$g.$h"; else { if ($d !== $h) return "$primo/$h"; else return -1; //error } } } } ?> Please write me if you have any suggestion tristram
<?php if (!function_exists("ip2long")) { function ip2long($ip) { $ip = explode(".",$ip); if (!is_numeric(join(NULL,$ip)) or count($ip) != 4) {return false;} else {return $ip[3]+256*$ip[2]+256*256*$ip[1]+256*256*256*$ip[0];} } } ?> 01-sep-2005 08:47
# m.ozarek # # Check if given mask is correct. You can check the short format mask # like 8,16,24 or long format like 255.255.255.0 # function isIpMask($mask){ $format = ''; if(preg_match("/[0-9].[0-9].[0-9].[0-9]/",$mask)){ $format = "long"; }else{ if($mask<=30){ $format = "short"; }else{ return false; } } switch($format){ case long; $mask = decbin(ip2long($mask)); break; case short: $tmp = $mask; for($i=0; $i < $mask ;$i++){ $tmp.= 1; } for($j=0; $j < (32 - $mask);$j++){ $tmp.= 0; } $mask = $tmp; break; } if(strlen($mask) <= 32){ for($i=0;$i<=32 ;$i++){ $bit = substr($mask,$i,1); if(($bit - substr($mask,$i+1,1)) < 0){ return false; } } } return true; } # EXAMPLE # isIpMask("255.255.255.0") -> return true # isIpMask("24") -> return true # isIpMask("5.5.5.5") -> return false |
Change Languagecheckdnsrr closelog debugger_off debugger_on define_syslog_variables dns_check_record dns_get_mx dns_get_record fsockopen gethostbyaddr gethostbyname gethostbynamel getmxrr getprotobyname getprotobynumber getservbyname getservbyport header headers_list headers_sent inet_ntop inet_pton ip2long long2ip openlog pfsockopen setcookie setrawcookie socket_get_status socket_set_blocking socket_set_timeout syslog |