Matching IPv6 address to a CIDR subnet

前端 未结 7 2136
长情又很酷
长情又很酷 2020-12-15 12:24

Is there a good way to match an IPv6 address to an IPv6 subnet using CIDR notation? What I am looking for is the IPv6 equivalent to this: Matching an IP to a CIDR mask in PH

7条回答
  •  醉梦人生
    2020-12-15 13:11

    Since you cannot convert IPv6 addresses to integer, you should operate bits, like this:

    $ip='21DA:00D3:0000:2F3B:02AC:00FF:FE28:9C5A';
    $cidrnet='21DA:00D3:0000:2F3B::/64';
    
    // converts inet_pton output to string with bits
    function inet_to_bits($inet) 
    {
       $splitted = str_split($inet);
       $binaryip = '';
       foreach ($splitted as $char) {
                 $binaryip .= str_pad(decbin(ord($char)), 8, '0', STR_PAD_LEFT);
       }
       return $binaryip;
    }    
    
    $ip = inet_pton($ip);
    $binaryip=inet_to_bits($ip);
    
    list($net,$maskbits)=explode('/',$cidrnet);
    $net=inet_pton($net);
    $binarynet=inet_to_bits($net);
    
    $ip_net_bits=substr($binaryip,0,$maskbits);
    $net_bits   =substr($binarynet,0,$maskbits);
    
    if($ip_net_bits!==$net_bits) echo 'Not in subnet';
    else echo 'In subnet';
    

    Also, if you use some database to store IPs, it may already have all the functions to compare them. For example, Postgres has an inet type and can determine, whether IP is contained within subnet like this:

    SELECT 
       '21DA:00D3:0000:2F3B:02AC:00FF:FE28:9C5A'::inet << 
       '21DA:00D3:0000:2F3B::/64'::inet;
    

    9.11. Network Address Functions and Operators in PostgreSQL

提交回复
热议问题