ip2long

(PHP 4, PHP 5, PHP 7)

ip2long将 IPV4 的字符串互联网协议转换成长整型数字

说明

ip2long ( string $ip_address ) : int

函数 ip2long() 返回 IPV4 网络地址的长整型格式,从标准网络地址格式(点字符串)转化得到。

ip2long() 还可以与非完整IP进行工作。 阅读 » http://publibn.boulder.ibm.com/doc_link/en_US/a_doc_lib/libs/commtrf2/inet_addr.htm 获得更多信息。

参数

ip_address

一个标准格式的地址。

返回值

返回IP地址转换后的数字 或 FALSE 如果 ip_address 是无效的。

更新日志

版本 说明
5.5.0 Prior to this version, on Windows ip2long() would sometimes return a valid number even if passed a value which was not an (IPv4) Internet Protocol dotted address.
5.2.10 再此之前的版本, ip2long() 有时会返回即使这不是一个IPV4的标准地址的数字地址。

范例

Example #1 ip2long() 例子

<?php
$ip 
gethostbyname('www.example.com');
$out "The following URLs are equivalent:<br />\n";
$out .= 'http://www.example.com/, http://' $ip '/, and http://' sprintf("%u"ip2long($ip)) . "/<br />\n";
echo 
$out;
?>

Example #2 显示IP地址

第二个例子说明打印一个转换后的地址使用 printf() 在PHP4和PHP5的功能:

<?php
$ip   
gethostbyname('www.example.com');
$long ip2long($ip);

if (
$long == -|| $long === FALSE) {
    echo 
'Invalid IP, please try again';
} else {
    echo 
$ip   "\n";           // 192.0.34.166
    
echo $long "\n";           // -1073732954
    
printf("%u\n"ip2long($ip)); // 3221234342
}
?>

注释

Note:

因为PHP的 integer 类型是有符号,并且有许多的IP地址讲导致在32位系统的情况下为负数, 你需要使用 "%u" 进行转换通过 sprintf()printf() 得到的字符串来表示无符号的IP地址。

Note:

ip2long() 将返回 FALSE 在IP是 255.255.255.255 的情况,版本为 PHP 5 <= 5.0.2. 在修复后 PHP 5.0.3 会返回 -1 (与PHP4相同).

参见

  • long2ip() - 将长整型转化为字符串形式带点的互联网标准格式地址(IPV4)
  • sprintf() - Return a formatted string

User Contributed Notes

schat 10-May-2019 11:20
sorry i just wrote wrong, sorry. this is the right one. thanks.

/**
 * convert cidr to ip range
 * From: <https://github.com/www-schat-top>
 * @param  string $cidr "192.168.0.0/23"
 * @return array  ["192.168.0.0", "192.168.1.255"]
 */
function cidr2range($cidr){
   list( $subnet, $mask ) = explode( '/', $cidr );
   return [$subnet, long2ip(ip2long( $subnet ) | (pow(2,( 32 - $mask ))-1))];
}
Mike B 14-Oct-2017 12:16
<?php
/*
     Given an IP address and Subnet Mask,
     determine the subnet address, broadcast address, and wildcard mask
     by using bitwise operators

     ref:  http://php.net/manual/en/language.operators.bitwise.php
*/

$ip='10.10.10.7';
$mask='255.255.255.0';
$wcmask=long2ip( ~ip2long($mask) );
$subnet=long2ip( ip2long($ip) & ip2long($mask) );
$bcast=long2ip( ip2long($ip) | ip2long($wcmask) );
echo
"Given address $ip and mask $mask, \n" .
"the subnet is $subnet and broadcast is $bcast \n" .
"with a wildcard mask of $wcmask";

/*
Given address 10.10.10.7 and mask 255.255.255.0,
the subnet is 10.10.10.0 and broadcast is 10.10.10.255
with a wildcard mask of 0.0.0.255
*/

?>
alex at alex-at dot ru 14-Sep-2016 08:52
Here are my versions of prefix to mask and mask to prefix conversions. You can remove first lines with if/preg of each function if you don't want sanity precheck.

    function prefix2Mask($prefix)
    {
        if (!preg_match('#^(?:0*[0-2]?[0-9]|3[0-2])$#', $prefix)) return false; # wrong prefix
        return long2ip(0xffffffff << (32 - $prefix));
    }
   
    function mask2Prefix($mask)
    {
        if (!preg_match('#^(?:(?:[0-1][0-9][0-9]|2[0-4][0-9]|25[0-5]|[0-9][0-9]|[0-9])\.){3}'.
            '(?:[0-1][0-9][0-9]|2[0-4][0-9]|25[0-5]|[0-9][0-9]|[0-9])$#', $mask))
            return false; # wrong mask
        $m2p = str_pad(substr(decbin(ip2long($mask)), -32, 32), 32, '0', STR_PAD_LEFT);
        if (!preg_match('#^(1*)0*$#', $m2p, $m)) return false; # wrong mask
        return strlen($m[1]);
    }
Karl Rixon 18-Sep-2014 02:01
The manual states that "ip2long() will also work with non-complete IP addresses", however this is system-dependant so cannot be relied upon. For example, on my system ip2long() will return FALSE for incomplete addresses:

<?php
var_dump
(ip2long("255.255")); // bool(false)
?>

This is because ip2long will use inet_pton if available, which does not support non-complete addresses. If inet_pton is not available on your system, inet_addr will be used and incomplete addresses will work as stated.
oo dot para at gmail dot com 08-Jan-2014 10:30
If you want to validate IPs using this function, please be careful:
The function filter_var should be used instead for validating IPs.

<?php
$ip
= '192.168.0355.24';
var_dump(ip2long($ip) !== false); // true (expected false)
var_dump(filter_var($ip, FILTER_VALIDATE_IP) !== false); // false

$ip = '192.168.355.24';
var_dump(ip2long($ip) !== false); // false
var_dump(filter_var($ip, FILTER_VALIDATE_IP) !== false); // false
?>
rasmus at mindplay dot dk 27-Aug-2013 02:54
As pointed out by others, this function's return value is not consistent on 32 and 64-bit platforms.

Your best bet for consistent behavior across 32/64-bit platforms (and Windows) is the lowest common denominator: force the return value of ip2long() into a signed 32-bit integer, e.g.:

    var_dump(unpack('l', pack('l', ip2long('255.255.255.0'))));

This looks idiotic, but it gives you a consistent signed integer value on all platforms.

(the arguments to both pack() and unpack() are the lower-case letter "L", not the number "1", in case it looks that way on your screen...)
admin at wudimei dot com 04-Jul-2012 02:42
<?php

/**
  *
  *get the first ip and last ip from cidr(network id and mask length)
  * i will integrate this function into "Rong Framework" :)
  * @author admin@wudimei.com
  * @param string $cidr 56.15.0.6/16 , [network id]/[mask length]
  * @return array $ipArray = array( 0 =>"first ip of the network", 1=>"last ip of the network" );
  *                         Each element of $ipArray's type is long int,use long2ip( $ipArray[0] ) to convert it into ip string.
  * example:
  * list( $long_startIp , $long_endIp) = getIpRange( "56.15.0.6/16" );
  * echo "start ip:" . long2ip( $long_startIp );
  * echo "<br />";
  * echo "end ip:" . long2ip( $long_endIp );
  */

 
function getIpRang$cidr) {

   list(
$ip, $mask) = explode('/', $cidr);
 
  
$maskBinStr =str_repeat("1", $mask ) . str_repeat("0", 32-$mask );      //net mask binary string
  
$inverseMaskBinStr = str_repeat("0", $mask ) . str_repeat("1"32-$mask ); //inverse mask
  
  
$ipLong = ip2long( $ip );
  
$ipMaskLong = bindec( $maskBinStr );
  
$inverseIpMaskLong = bindec( $inverseMaskBinStr );
  
$netWork = $ipLong & $ipMaskLong

  
$start = $netWork+1;//去掉网络号 ,ignore network ID(eg: 192.168.1.0)
 
  
$end = ($netWork | $inverseIpMaskLong) -1 ; //去掉广播地址 ignore brocast IP(eg: 192.168.1.255)
  
return array( $start, $end );
}
?>
replay111 at tlen dot pl 26-May-2012 01:28
Hi,
based on examples above I have mixed class IPFilter with netMatch function wich gives me complete class for IP4 check including CIDR IP format:

<?php
class IP4Filter {

    private static
$_IP_TYPE_SINGLE = 'single';
    private static
$_IP_TYPE_WILDCARD = 'wildcard';
    private static
$_IP_TYPE_MASK = 'mask';
    private static
$_IP_TYPE_CIDR = 'CIDR';
    private static
$_IP_TYPE_SECTION = 'section';
    private
$_allowed_ips = array();

    public function
__construct($allowed_ips) {
       
$this->_allowed_ips = $allowed_ips;
    }

    public function
check($ip, $allowed_ips = null) {
       
$allowed_ips = $allowed_ips ? $allowed_ips : $this->_allowed_ips;

        foreach (
$allowed_ips as $allowed_ip) {
           
$type = $this->_judge_ip_type($allowed_ip);
           
$sub_rst = call_user_func(array($this, '_sub_checker_' . $type), $allowed_ip, $ip);

            if (
$sub_rst) {
                return
true;
            }
        }

        return
false;
    }

    private function
_judge_ip_type($ip) {
        if (
strpos($ip, '*')) {
            return
self :: $_IP_TYPE_WILDCARD;
        }

        if (
strpos($ip, '/')) {
           
$tmp = explode('/', $ip);
            if (
strpos($tmp[1], '.')) {
                return
self :: $_IP_TYPE_MASK;
            } else {
                return
self :: $_IP_TYPE_CIDR;
            }
        }

        if (
strpos($ip, '-')) {
            return
self :: $_IP_TYPE_SECTION;
        }

        if (
ip2long($ip)) {
            return
self :: $_IP_TYPE_SINGLE;
        }

        return
false;
    }

    private function
_sub_checker_single($allowed_ip, $ip) {
        return (
ip2long($allowed_ip) == ip2long($ip));
    }

    private function
_sub_checker_wildcard($allowed_ip, $ip) {
       
$allowed_ip_arr = explode('.', $allowed_ip);
       
$ip_arr = explode('.', $ip);
        for (
$i = 0; $i < count($allowed_ip_arr); $i++) {
            if (
$allowed_ip_arr[$i] == '*') {
                return
true;
            } else {
                if (
false == ($allowed_ip_arr[$i] == $ip_arr[$i])) {
                    return
false;
                }
            }
        }
    }

    private function
_sub_checker_mask($allowed_ip, $ip) {
        list(
$allowed_ip_ip, $allowed_ip_mask) = explode('/', $allowed_ip);
       
$begin = (ip2long($allowed_ip_ip) & ip2long($allowed_ip_mask)) + 1;
       
$end = (ip2long($allowed_ip_ip) | (~ ip2long($allowed_ip_mask))) + 1;
       
$ip = ip2long($ip);
        return (
$ip >= $begin && $ip <= $end);
    }

    private function
_sub_checker_section($allowed_ip, $ip) {
        list(
$begin, $end) = explode('-', $allowed_ip);
       
$begin = ip2long($begin);
       
$end = ip2long($end);
       
$ip = ip2long($ip);
        return (
$ip >= $begin && $ip <= $end);
    }

    private function
_sub_checker_CIDR($CIDR, $IP) {
        list (
$net, $mask) = explode('/', $CIDR);
        return (
ip2long($IP) & ~((1 << (32 - $mask)) - 1) ) == ip2long($net);
    }

}
?>

For me this code works great, so I wanna thank to all You guys!!!
Aleksey Kuznetsov 07-May-2012 05:30
Unfortunately sprintf('%u', ...) is low and returns string representation of integer value instead of integer.
Here is a function I use to convert IP to mySQL-compatible signed integer:

function ip2int($ip) {
  if (!$r = ip2long($ip)) return 0; // we want 0 instead of false, even in case of bad IP
  if ($r > 2147483647)
      $r-= 4294967296;
  return $r; // ok
}
pink at pink dot art dot pl 26-Apr-2012 01:09
Be aware when you're running 64bit system, ip2long will result 64 bit integer which doesn't fit in MySQL INT, you can use BIGINT or INT UNSIGNED because on 64bit systems ip2long will never return negative integer. See also https://bugs.php.net/bug.php?id=54338
PandoraBox2007 at gmail dot com 03-Dec-2011 07:06
Universal ip4/ip6

<?php
// encoded --
function encode_ip ($ip)
{
   
$d = explode('.', $ip);
    if (
count($d) == 4) return sprintf('%02x%02x%02x%02x', $d[0], $d[1], $d[2], $d[3]);
 
   
$d = explode(':', preg_replace('/(^:)|(:$)/', '', $ip));
   
$res = '';
    foreach (
$d as $x)
       
$res .= sprintf('%0'. ($x == '' ? (9 - count($d)) * 4 : 4) .'s', $x);
    return
$res;
}

// decoded
function decode_ip($int_ip)
{
    function
hexhex($value) { return dechex(hexdec($value)); };
 
    if (
strlen($int_ip) == 32) {
       
$int_ip = substr(chunk_split($int_ip, 4, ':'), 0, 39);
       
$int_ip = ':'. implode(':', array_map("hexhex", explode(':',$int_ip))) .':';
       
preg_match_all("/(:0)+/", $int_ip, $zeros);
        if (
count($zeros[0]) > 0) {
           
$match = '';
            foreach(
$zeros[0] as $zero)
                if (
strlen($zero) > strlen($match))
                   
$match = $zero;
           
$int_ip = preg_replace('/'. $match .'/', ':', $int_ip, 1);
        }
        return
preg_replace('/(^:([^:]))|(([^:]):$)/', '$2$4', $int_ip);
    }
   
$hexipbang = explode('.', chunk_split($int_ip, 2, '.'));
    return
hexdec($hexipbang[0]). '.' . hexdec($hexipbang[1]) . '.' . hexdec($hexipbang[2]) . '.' . hexdec($hexipbang[3]);
}
?>

DB:
`user_ip` varchar(32) DEFAULT NULL
anjo2 28-May-2011 09:13
In 32bits systems, you cannot convert ipv6 to long, but you can convert ip2bin and bin2ip

This function converts ipv4 and ipv6, returns false if ip is not valid

<?php
function ip2bin($ip)
{
    if(
filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== false)
        return
base_convert(ip2long($ip),10,2);
    if(
filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false)
        return
false;
    if((
$ip_n = inet_pton($ip)) === false) return false;
   
$bits = 15; // 16 x 8 bit = 128bit (ipv6)
   
while ($bits >= 0)
    {
       
$bin = sprintf("%08b",(ord($ip_n[$bits])));
       
$ipbin = $bin.$ipbin;
       
$bits--;
    }
    return
$ipbin;
}

function
bin2ip($bin)
{
   if(
strlen($bin) <= 32) // 32bits (ipv4)
      
return long2ip(base_convert($bin,2,10));
   if(
strlen($bin) != 128)
       return
false;
  
$pad = 128 - strlen($bin);
   for (
$i = 1; $i <= $pad; $i++)
   {
      
$bin = "0".$bin;
   }
  
$bits = 0;
   while (
$bits <= 7)
   {
      
$bin_part = substr($bin,($bits*16),16);
      
$ipv6 .= dechex(bindec($bin_part)).":";
      
$bits++;
   }
   return
inet_ntop(inet_pton(substr($ipv6,0,-1)));
}
?>
hanguofeng at gmail dot com 13-Mar-2011 07:50
I've write an IPFilter class to check if a ip is in given ips.

<?php
class IPFilter
{
    private static
$_IP_TYPE_SINGLE = 'single';
    private static
$_IP_TYPE_WILDCARD = 'wildcard';
    private static
$_IP_TYPE_MASK = 'mask';
    private static
$_IP_TYPE_SECTION = 'section';
    private
$_allowed_ips = array();

    public function
__construct($allowed_ips)
    {
       
$this -> _allowed_ips = $allowed_ips;
    }

    public function
check($ip, $allowed_ips = null)
    {
       
$allowed_ips = $allowed_ips ? $allowed_ips : $this->_allowed_ips;

        foreach(
$allowed_ips as $allowed_ip)
        {
           
$type = $this -> _judge_ip_type($allowed_ip);
           
$sub_rst = call_user_func(array($this,'_sub_checker_' . $type), $allowed_ip, $ip);

            if (
$sub_rst)
            {
                return
true;
            }
        }

        return
false;
    }

    private function
_judge_ip_type($ip)
    {
        if (
strpos($ip, '*'))
        {
            return
self :: $_IP_TYPE_WILDCARD;
        }

        if (
strpos($ip, '/'))
        {
            return
self :: $_IP_TYPE_MASK;
        }

        if (
strpos($ip, '-'))
        {
            return
self :: $_IP_TYPE_SECTION;
        }

        if (
ip2long($ip))
        {
            return
self :: $_IP_TYPE_SINGLE;
        }

        return
false;
    }

    private function
_sub_checker_single($allowed_ip, $ip)
    {
        return (
ip2long($allowed_ip) == ip2long($ip));
    }

    private function
_sub_checker_wildcard($allowed_ip, $ip)
    {
       
$allowed_ip_arr = explode('.', $allowed_ip);
       
$ip_arr = explode('.', $ip);
        for(
$i = 0;$i < count($allowed_ip_arr);$i++)
        {
            if (
$allowed_ip_arr[$i] == '*')
            {
                return
true;
            }
            else
            {
                if (
false == ($allowed_ip_arr[$i] == $ip_arr[$i]))
                {
                    return
false;
                }
            }
        }
    }

    private function
_sub_checker_mask($allowed_ip, $ip)
    {
        list(
$allowed_ip_ip, $allowed_ip_mask) = explode('/', $allowed_ip);
       
$begin = (ip2long($allowed_ip_ip) &ip2long($allowed_ip_mask)) + 1;
       
$end = (ip2long($allowed_ip_ip) | (~ip2long($allowed_ip_mask))) + 1;
       
$ip = ip2long($ip);
        return (
$ip >= $begin && $ip <= $end);
    }

    private function
_sub_checker_section($allowed_ip, $ip)
    {
        list(
$begin, $end) = explode('-', $allowed_ip);
       
$begin = ip2long($begin);
       
$end = ip2long($end);
       
$ip = ip2long($ip);
        return (
$ip >= $begin && $ip <= $end);
    }
}
?>

useage:
<?php
$filter
= new IPFilter(
    array(
       
'127.0.0.1',
       
'172.0.0.*',
       
'173.0.*.*',
       
'126.1.0.0/255.255.0.0',
       
'125.0.0.1-125.0.0.9',
));
$filter -> check('126.1.0.2');
?>
me at iaincollins dot com 19-May-2010 03:37
I would just like to try and clear up simply that if storing IPV4 addresses in an SQL database you should use an unsigned int (4 bytes).

The easiest way to do this in PHP is to use sprintf():

<?php
 $dottedFormatAddress
= '127.0.0.1';
 
$ipv4address = sprintf("%u", ip2long($dottedFormatAddress));
?>

Primary reasons are it's compatible with database functions like MySQL's INET_ATON & INET_NTOA (which also use unsigned int's), it's efficient,  and it's the most common format used by IP lookup databases.
joe at joeceresini dot com 24-Nov-2009 05:45
A quick method to convert a netmask (ex: 255.255.255.240) to a cidr mask (ex: /28):

<?php
function mask2cidr($mask){
 
$long = ip2long($mask);
 
$base = ip2long('255.255.255.255');
  return
32-log(($long ^ $base)+1,2);

 
/* xor-ing will give you the inverse mask,
      log base 2 of that +1 will return the number
      of bits that are off in the mask and subtracting
      from 32 gets you the cidr notation */
       
}
?>
f dot wiessner at smart-weblications dot net 07-Nov-2009 06:12
Here some working ip2long6 and long2ip6 functions - keep in mind that this needs php gmp-lib:

<?php

$ipv6
= "2001:4860:a005::68";

function
ip2long6($ipv6) {
 
$ip_n = inet_pton($ipv6);
 
$bits = 15; // 16 x 8 bit = 128bit
 
while ($bits >= 0) {
   
$bin = sprintf("%08b",(ord($ip_n[$bits])));
   
$ipv6long = $bin.$ipv6long;
   
$bits--;
  }
  return
gmp_strval(gmp_init($ipv6long,2),10);
}

function
long2ip6($ipv6long) {

 
$bin = gmp_strval(gmp_init($ipv6long,10),2);
  if (
strlen($bin) < 128) {
   
$pad = 128 - strlen($bin);
    for (
$i = 1; $i <= $pad; $i++) {
   
$bin = "0".$bin;
    }
  }
 
$bits = 0;
  while (
$bits <= 7) {
   
$bin_part = substr($bin,($bits*16),16);
   
$ipv6 .= dechex(bindec($bin_part)).":";
   
$bits++;
  }
 
// compress

 
return inet_ntop(inet_pton(substr($ipv6,0,-1)));
}

print
$ipv6long ip2long6($ipv6)."\n";
print
$ipv6 = long2ip6($ipv6long)."\n";

?>

outputs:

42541956150894553250710573749450571880
2001:4860:a005::68
david dot schueler at tel-billig dot de 27-Oct-2009 06:41
To get the network adress out of the broadcast adress and netmask just to an AND on it:

<?php
// simple example
$bcast = ip2long("192.168.178.255");
$smask = ip2long("255.255.255.0");
$nmask = $bcast & $smask;
echo
long2ip($nmask); // Will give 192.168.178.0
?>

With this example you are able to check if a given host is in your own local net or not (on linux):

<?php
/**
 * Check if a client IP is in our Server subnet
 *
 * @param string $client_ip
 * @param string $server_ip
 * @return boolean
 */
function clientInSameSubnet($client_ip=false,$server_ip=false) {
    if (!
$client_ip)
       
$client_ip = $_SERVER['REMOTE_ADDR'];
    if (!
$server_ip)
       
$server_ip = $_SERVER['SERVER_ADDR'];
   
// Extract broadcast and netmask from ifconfig
   
if (!($p = popen("ifconfig","r"))) return false;
   
$out = "";
    while(!
feof($p))
       
$out .= fread($p,1024);
   
fclose($p);
   
// This is because the php.net comment function does not
    // allow long lines.
   
$match  = "/^.*".$server_ip;
   
$match .= ".*Bcast:(\d{1,3}\.\d{1,3}i\.\d{1,3}\.\d{1,3}).*";
   
$match .= "Mask:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/im";
    if (!
preg_match($match,$out,$regs))
        return
false;
   
$bcast = ip2long($regs[1]);
   
$smask = ip2long($regs[2]);
   
$ipadr = ip2long($client_ip);
   
$nmask = $bcast & $smask;
    return ((
$ipadr & $smask) == ($nmask & $smask));
}
?>
joshua_r108 at hotmail dot com 01-Aug-2009 11:30
I wrote something on the different ways to get an IP and convert it using ip2long(), the different ways to store an IP or an IP range in MySQL, and the different ways to query for the IP(s). Maybe something useful for others?

http://strictcoder.blogspot.com/2009_08_01_archive.html
Title: Query For An IP In A Database

Regards,
Joshua K Roberson
jwadhams1 at yahoo dot com 28-Jul-2009 03:41
I wanted to build on what kaputt and spinyn contributed in a way that I think is a little more intuitive (e.g., let sprintf do all the binary conversion and padding, and let substr_compare do the trimming and comparing):

<?php
function ip_in_network($ip, $net_addr, $net_mask){
    if(
$net_mask <= 0){ return false; }
       
$ip_binary_string = sprintf("%032b",ip2long($ip));
       
$net_binary_string = sprintf("%032b",ip2long($net_addr));
        return (
substr_compare($ip_binary_string,$net_binary_string,0,$net_mask) === 0);
}

ip_in_network("192.168.2.1","192.168.2.0",24); //true
ip_in_network("192.168.6.93","192.168.0.0",16); //true
ip_in_network("1.6.6.6","128.168.2.0",1); //false
?>
spinyn at gmail dot com 16-Apr-2009 07:51
Just want to add a comment to kaputt's valuable contribution to the task of matching hosts to ip ranges, efficiently.  The script works fine if the binary representation of the ip involves no leading zeros.  Unfortunately, the way decbin() seems to work, leading zeros in the binary representation of the first ip quad get dropped.  That is a serious matter if you're trying to match all possible candidates in the checklist.  In those cases the leading zeros need to be added back to get accurate matches for values in the first quad between 0-127 (or the binary equivalent, 0-01111111).

The solution I came up with to address this issue was the following function:

<?php
function addLeadingZero($ip) {
   if ((
$result = (32 - strlen($ip))) > 0)
      return
str_repeat("0", $result).$ip;
}
?>
Anonymous 18-Feb-2009 11:43
To always get the signed 32bit representation of an ip, I found this workaround:
<?php
list(, $ip) = unpack('l',pack('l',ip2long('200.200.200.200')));
?>

In this example, $ip will be -926365496 regardless of a 32 or 64 bit system.
randolf 20-Jan-2009 01:19
Convert IP to unsigned long

<?php
//$strIP  :   IP in String-format
//$lngIP  :   IP in unsigned long

if (($lngIP=ip2long($strIP)) < 0){ $lngIP += 4294967296 ;}

                                                      
// ADD 2^32

thats all.
?>
Teguh Iskanto - Kamprettos at yahoo 29-Aug-2008 09:53
to Anonymous @ 29-Aug-2008 10:19

If you're speaking about efficiency, there's no absolute right / wrong as it all depends on the user's needs, specs and requirements.

But from what I'm coming from , this method served me well,  I've used this to match 2 network ends of approx 2700++ something unique VRFs (Nortel Shasta) and yes, each VRF is a virtualized firewall that consists of at least 20 different network objects (some could have couple of hundreds). Not to mention that these , still have to be compared with another hundreds of contivity boxes and each box have a range of around 1-600 vpn peers (to add more complexity, each peer has around 1-50 network ranges).

So, if you do the math, the number of permutations that need to be calculated, is indeed quite complex. I could get the whole result somewhere in around 50-65 secs tops.

Had I used a php function to crunch those data the result would have been longer.
Anonymous 29-Aug-2008 05:19
@Teguh Iskanto

Hi,

Your solution requires you to store the IP addresses and masks as strings, and also to store the subnet mask being used by your hosts.  This is very inefficient.

If you stored your network addresses as unsigned Integers, and your masks as TinyInts (i.e. a value between 0 & 32), you could instead do this:

select * from networks WHERE inet_aton('10.20.251.130') between `ipnumber` AND (`ipnumber` + (POW(2,(32-`mask`)))-1);

Obviously this can be made quicker on very high load systems by storing the broadcast address in the table instead of calculating it on the fly:

select * from networks WHERE inet_aton('10.20.251.130') between `ipnumber` AND `broadcast`;

Nick
ncritten at gmail dot youknowwhat 29-Aug-2008 04:58
Hi,
Please find below a little function I wrote for handling IP addresses as unsigned integers.
This function will take an IP address or IP number in ANY FORMAT (that I can think of) and will return it's decimal unsigned equivalent, as a string.

<?php
function myip2long($ip){
    if (
is_numeric($ip)){
        return
sprintf("%u", floatval($ip));
    } else {
        return
sprintf("%u", floatval(ip2long($ip)));
    }
}
?>

Here is is in action:

<?php
$ip
['DottedQuadDec'] = "192.168.255.109";
$ip['PosIntStr']     = "3232300909";
$ip['NegIntStr']     = "-1062666387";
$ip['PosInt']        = 3232300909;
$ip['NegInt']        = -1062666387;
$ip['DottedQuadHex'] = "0xc0.0xA8.0xFF.0x6D";
$ip['DottedQuadOct'] = "0300.0250.0377.0155";
$ip['HexIntStr']     = "0xC0A8FF6D";
$ip['HexInt']        = 0xC0A8FF6D;

printf("\n% 16s : % 20s => % 11s => % 16s","Input Type","Input Value","Converted","Converted Back");
echo
"\n    ------------------------------------------------------------------";
foreach (
$ip as $type => $value){
   
$ipnum = myip2long($value);
   
printf("\n% 16s : % 20s => % 11s => % 16s",$type,$value,$ipnum,long2ip($ipnum));
}
?>
chrisp-phpnet at inventivedingo dot com 30-May-2008 07:36
I had a problem with calling this function with REMOTE_ADDR on my lighttpd web server. Turned out that IPv6 was installed on this server, so even though REMOTE_ADDR was an IPv4 address, it was being formatted using IPv6's IPv4 compatibility mode. For example, 10.0.0.1 was becoming ::ffff:10.0.0.1, which caused iplong to report the address as invalid instead of parsing it correctly.

The correct fix would of course be to update my infrastructure so that it's properly IPv6-compatible; but in the context of my particular situation, this would involve a lot of re-engineering. So in the meantime, I worked around the issue using this quick and dirty hack:

<?php
    $ip
= htmlspecialchars($_SERVER['REMOTE_ADDR']);
    if (
strpos($ip, '::') === 0) {
       
$ip = substr($ip, strrpos($ip, ':')+1);
    }
   
$host = ip2long($ip);
?>

Ugly but functional.
jpmarcotte at gmail dot com 20-May-2008 03:10
In using a combination of jbothe's code below and some of the "$mask = 0xFFFFFFFF << (32 - $bits)" type code, I ran into an error with some later calculations on a 64 bit machine.

Keep in mind that when you're analyzing numbers meant to be treated as 32 bits wide (such as IP addresses), you may want to truncate them. Without relying on other libraries, it was simple enough to follow any calculations that may end with different results on a 64 bit machine with " & 0xFFFFFFFF"

Though in many cases, it seems like it might be simpler to just use "~0 << ..." for initial shifting to create the network mask instead of "0xFFFFFFFF << ...". I don't know that it guarantees further operations to work as expected though.
lutel 09-Apr-2008 04:45
here is netMatch function which is the fastest I could wrote, I hope developers will include native function soon...

<?php
function netMatch ($CIDR,$IP) {
    list (
$net, $mask) = explode ('/', $CIDR);
    return (
ip2long ($IP) & ~((1 << (32 - $mask)) - 1) ) == ip2long ($net);
}
?>
php dot net at kenman dot net 01-Apr-2008 10:02
To nate, who advises that there is no reason to use an unsigned version of the IP in a MySQL DB:

I think it would depend on your application, but personally, I find it useful to store IP's as unsigneds since MySQL has 2 native functions, INET_ATON() and INET_NTOA(), which work the same as ip2long()/long2ip() _except_ that they generate the unsigned counterpart. So if you want, you could do:

-- IANA Class-B reserved/private
SELECT * FROM `servers`
WHERE `ip` >= INET_ATON('192.168.0.0')
AND `ip` <= INET_ATON('192.168.255.255');

In my current application, I find it easier to use the MySQL built-ins than the PHP counter-parts.

In case you're curious as to the names ATON and NTOA:

ATON = address to number aka. ip2long
NTOA = number to address aka. long2ip
johniskew at yahoo dot com 24-Mar-2008 10:14
The following function ipToHex will take an IP (v4 or v6 formatted) and if it is valid, will return a 32 byte hex string representing that address.  Requires php >= 5.2 as it uses the filter_var function.

<?php

function ipToHex($ipAddress) {
   
$hex = '';
    if(
strpos($ipAddress, ',') !== false) {
       
$splitIp = explode(',', $ipAddress);
       
$ipAddress = trim($splitIp[0]);
    }
   
$isIpV6 = false;
   
$isIpV4 = false;
    if(
filter_var($ipAddress, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false) {
       
$isIpV6 = true;
    }
    else if(
filter_var($ipAddress, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== false) {
       
$isIpV4 = true;
    }
    if(!
$isIpV4 && !$isIpV6) {
        return
false;
    }
   
// IPv4 format
   
if($isIpV4) {
       
$parts = explode('.', $ipAddress);
        for(
$i = 0; $i < 4; $i++) {
           
$parts[$i] = str_pad(dechex($parts[$i]), 2, '0', STR_PAD_LEFT);
        }
       
$ipAddress = '::'.$parts[0].$parts[1].':'.$parts[2].$parts[3];
       
$hex = join('', $parts);
    }
   
// IPv6 format
   
else {
       
$parts = explode(':', $ipAddress);
       
// If this is mixed IPv6/IPv4, convert end to IPv6 value
       
if(filter_var($parts[count($parts) - 1], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== false) {
           
$partsV4 = explode('.', $parts[count($parts) - 1]);
            for(
$i = 0; $i < 4; $i++) {
               
$partsV4[$i] = str_pad(dechex($partsV4[$i]), 2, '0', STR_PAD_LEFT);
            }
           
$parts[count($parts) - 1] = $partsV4[0].$partsV4[1];
           
$parts[] = $partsV4[2].$partsV4[3];
        }
       
$numMissing = 8 - count($parts);
       
$expandedParts = array();
       
$expansionDone = false;
        foreach(
$parts as $part) {
            if(!
$expansionDone && $part == '') {
                for(
$i = 0; $i <= $numMissing; $i++) {
                   
$expandedParts[] = '0000';
                }
               
$expansionDone = true;
            }
            else {
               
$expandedParts[] = $part;
            }
        }
        foreach(
$expandedParts as &$part) {
           
$part = str_pad($part, 4, '0', STR_PAD_LEFT);
        }
       
$ipAddress = join(':', $expandedParts);
       
$hex = join('', $expandedParts);
    }
   
// Validate the final IP
   
if(!filter_var($ipAddress, FILTER_VALIDATE_IP)) {
        return
false;
    }
    return
strtolower(str_pad($hex, 32, '0', STR_PAD_LEFT));
}
$ips = array(
   
'::192.168.0.2',
   
'0:0:0:0:0:0:192.168.0.2',
   
'192.168.0.2',
   
'::C0A8:2',
   
'0:0:0:0:0:0:C0A8:2'
);
$finals = array();
foreach(
$ips as $ip) {
   
$finals[] = ipToHex($ip);
}
var_dump($finals);

?>
og_sam at homail dot com 16-Mar-2008 07:15
@ samb057 at gmail dot com

This function will not return a correct bigint.

base_convert() is limited to the double type,
which usually counts 64bits and not 128 like an IPv6 address.

For example:

FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF

will __NOT__ be converted to 128^2 -1

You should use a bigint lib's multiplication function,
with decimal shifting factors defined as string constants (much faster than recalculating them every time).
Grab 8 short integers (the 16bits between the ':' with base_convert($hex,16,10)) and shift the 7 higher ones with a bigint_multiplication.

Of course you can also do it with less bigint ops using 32bit integers, but then you should create them this way (additionally 'sprintf' for making an uint32 string):
$uint32= sprintf('%u',intval(base_convert($hex,16,10)));

Finally, "bigint_add" the shifted ones to the least (unshifted) significant interger string and be happy

PS: I'm working on an IPv4/6 tool class with raw (also endianness), 6/4 compatibility and validation methods,
I'll post it here as soon as it's finished and tested.
ir on ir id is at gm ai ld ot co m 20-Oct-2007 11:54
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. :)
andrew dot minerd at sellingsource dot com 20-Jul-2007 05:15
A somewhat more efficient alternative to convert the signed integer return by ip2long:

$float = ((ip2long($ip) & 0x7FFFFFFF) + 0x80000000);
one tiger one at gee mail dot comm 02-Apr-2007 07:49
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.

<?php
// 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;
 }
}
?>
laacz at php dot net 16-Feb-2007 01:06
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.
samb057 at gmail dot com 26-Dec-2006 12:20
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.

<?php
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.
Ian B 24-Dec-2006 04:22
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.
jgwright 25-Oct-2006 12:13
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
*/

}

?>
ken at expitrans dot com 31-Aug-2005 03:31
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

?>
mailNO at SPAMdapuzz dot com 13-Feb-2005 11:05
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
01-Dec-2004 06: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";
?>
mediator 02-Jun-2004 03:50
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));
}
?>
jbothe at hotmail dot com 26-Nov-2003 11:01
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
<?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
daevid at daevid dot com 13-Oct-2003 09:23
<?php
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."<BR>";

   
$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()
?>
anderson at piq dot com dot br 06-Aug-2003 10:02
If you want to get the interface of an IP, based on the local route table, use this.

<?php
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;
            }
        }
    }
}
?>
phl AT cyways.com 22-Oct-2001 04:36
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:

<?php
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;
}
?>