web-dev-qa-db-fra.com

Faire correspondre une IP à un masque CIDR dans PHP 5?

Je cherche une méthode rapide/simple pour faire correspondre un IP quadruple pointillé IP4 donné à un masque de notation CIDR.

J'ai un tas d'adresses IP dont j'ai besoin pour voir si elles correspondent à une plage d'adresses IP.

exemple:

$ips = array('10.2.1.100', '10.2.1.101', '10.5.1.100', '1.2.3.4');

foreach ($ips as $IP) {
    if (cidr_match($IP, '10.2.0.0/16') == true) {
        print "you're in the 10.2 subnet\n"; 
    }
}

À quoi ressemblerait cidr_match()?

Ce n'est pas vraiment simple, mais rapide serait bien. Tout ce qui n'utilise que des fonctions intégrées/communes est un bonus (car je vais probablement demander à une personne de me montrer quelque chose dans pear qui fait cela, mais je ne peux pas dépendre de pear ou du paquet installé où mon code est déployés).

51
Uberfuzzy

Si vous utilisez uniquement IPv4:

  • utilisez ip2long() pour convertir les adresses IP et la plage de sous-réseaux en entiers longs
  • convertir le/xx en masque de sous-réseau
  • faire un bitwise 'et' (c'est-à-dire ip & mask) 'et vérifier que' result = subnet '

quelque chose comme ça devrait fonctionner:

function cidr_match($ip, $range)
{
    list ($subnet, $bits) = explode('/', $range);
    if ($bits === null) {
        $bits = 32;
    }
    $ip = ip2long($ip);
    $subnet = ip2long($subnet);
    $mask = -1 << (32 - $bits);
    $subnet &= $mask; # nb: in case the supplied subnet wasn't correctly aligned
    return ($ip & $mask) == $subnet;
}
73
Alnitak

Dans une situation similaire, j'ai fini par utiliser symfony/http-foundation.

Lors de l'utilisation de ce package, votre code ressemblerait à:

$ips = array('10.2.1.100', '10.2.1.101', '10.5.1.100', '1.2.3.4');

foreach($ips as $IP) {
    if (\Symfony\Component\HttpFoundation\IpUtils::checkIp($_SERVER['REMOTE_ADDR'], '10.2.0.0/16')) {
        print "you're in the 10.2 subnet\n";
    }
}

Il gère également IPv6.

Lien: https://packagist.org/packages/symfony/http-foundation

47
Dávid Veszelovszki

J'ai trouvé que plusieurs de ces méthodes se cassaient après PHP 5.2. Cependant, la solution suivante fonctionne sur les versions 5.2 et supérieures:

function cidr_match($ip, $cidr)
{
    list($subnet, $mask) = explode('/', $cidr);

    if ((ip2long($ip) & ~((1 << (32 - $mask)) - 1) ) == ip2long($subnet))
    { 
        return true;
    }

    return false;
}

Exemples de résultats

 cidr_match ("1.2.3.4", "0.0.0.0/0"): vrai 
 cidr_match ("127.0.0.1", "127.0.0.1/32"): vrai 
 cidr_match ("127.0.0.1", "127.0.0.2/32"): faux 

Source http://www.php.net/manual/en/function.ip2long.php#82397 .

42
Samuel Parkinson

Ma technique utilise la correspondance bit à bit en utilisant un sous-réseau et un masque.

function cidr_match($ip, $range){
    list ($subnet, $bits) = explode('/', $range);
    $ip = substr(IP2bin($ip),0,$bits) ;
    $subnet = substr(IP2Bin($subnet),0,$bits) ;
    return ($ip == $subnet) ;
}

function IP2Bin($ip){
    $ipbin = '';
    $ips = explode(".",$ip) ;
    foreach ($ips as $iptmp){
        $ipbin .= sprintf("%08b",$iptmp) ;
    }
    return $ipbin ;
}
3
A.R. Nasir Qureshi

Certaines fonctions ont changé:

  • diviser avec exploser

function cidr_match($ip, $range)
{
    list ($subnet, $bits) = explode('/', $range);
    $ip = ip2long($ip);
    $subnet = ip2long($subnet);
    $mask = -1 << (32 - $bits);
    $subnet &= $mask; 
    return ($ip & $mask) == $subnet;
}
3
Decebal

J'ai également eu besoin de tester les IP contre les masques CIDR. J'ai trouvé un site Web avec une excellente explication et un code source qui fonctionne parfaitement bien.

Le site Web http://pgregg.com/blog/2009/04/php-algorithms-determining-if-an-ip-is-within-a-specific-range/

Parce que le site Web peut un jour cesser d'exister, voici le code

<?php

/*
 * ip_in_range.php - Function to determine if an IP is located in a
 *                   specific range as specified via several alternative
 *                   formats.
 *
 * Network ranges can be specified as:
 * 1. Wildcard format:     1.2.3.*
 * 2. CIDR format:         1.2.3/24  OR  1.2.3.4/255.255.255.0
 * 3. Start-End IP format: 1.2.3.0-1.2.3.255
 *
 * Return value BOOLEAN : ip_in_range($ip, $range);
 *
 * Copyright 2008: Paul Gregg <[email protected]>
 * 10 January 2008
 * Version: 1.2
 *
 * Source website: http://www.pgregg.com/projects/php/ip_in_range/
 * Version 1.2
 *
 * This software is Donationware - if you feel you have benefited from
 * the use of this tool then please consider a donation. The value of
 * which is entirely left up to your discretion.
 * http://www.pgregg.com/donate/
 *
 * Please do not remove this header, or source attibution from this file.
 */


// decbin32
// In order to simplify working with IP addresses (in binary) and their
// netmasks, it is easier to ensure that the binary strings are padded
// with zeros out to 32 characters - IP addresses are 32 bit numbers
Function decbin32 ($dec) {
  return str_pad(decbin($dec), 32, '0', STR_PAD_LEFT);
}

// ip_in_range
// This function takes 2 arguments, an IP address and a "range" in several
// different formats.
// Network ranges can be specified as:
// 1. Wildcard format:     1.2.3.*
// 2. CIDR format:         1.2.3/24  OR  1.2.3.4/255.255.255.0
// 3. Start-End IP format: 1.2.3.0-1.2.3.255
// The function will return true if the supplied IP is within the range.
// Note little validation is done on the range inputs - it expects you to
// use one of the above 3 formats.
Function ip_in_range($ip, $range) {
  if (strpos($range, '/') !== false) {
    // $range is in IP/NETMASK format
    list($range, $netmask) = explode('/', $range, 2);
    if (strpos($netmask, '.') !== false) {
      // $netmask is a 255.255.0.0 format
      $netmask = str_replace('*', '0', $netmask);
      $netmask_dec = ip2long($netmask);
      return ( (ip2long($ip) & $netmask_dec) == (ip2long($range) & $netmask_dec) );
    } else {
      // $netmask is a CIDR size block
      // fix the range argument
      $x = explode('.', $range);
      while(count($x)<4) $x[] = '0';
      list($a,$b,$c,$d) = $x;
      $range = sprintf("%u.%u.%u.%u", empty($a)?'0':$a, empty($b)?'0':$b,empty($c)?'0':$c,empty($d)?'0':$d);
      $range_dec = ip2long($range);
      $ip_dec = ip2long($ip);

      # Strategy 1 - Create the netmask with 'netmask' 1s and then fill it to 32 with 0s
      #$netmask_dec = bindec(str_pad('', $netmask, '1') . str_pad('', 32-$netmask, '0'));

      # Strategy 2 - Use math to create it
      $wildcard_dec = pow(2, (32-$netmask)) - 1;
      $netmask_dec = ~ $wildcard_dec;

      return (($ip_dec & $netmask_dec) == ($range_dec & $netmask_dec));
    }
  } else {
    // range might be 255.255.*.* or 1.2.3.0-1.2.3.255
    if (strpos($range, '*') !==false) { // a.b.*.* format
      // Just convert to A-B format by setting * to 0 for A and 255 for B
      $lower = str_replace('*', '0', $range);
      $upper = str_replace('*', '255', $range);
      $range = "$lower-$upper";
    }

    if (strpos($range, '-')!==false) { // A-B format
      list($lower, $upper) = explode('-', $range, 2);
      $lower_dec = (float)sprintf("%u",ip2long($lower));
      $upper_dec = (float)sprintf("%u",ip2long($upper));
      $ip_dec = (float)sprintf("%u",ip2long($ip));
      return ( ($ip_dec>=$lower_dec) && ($ip_dec<=$upper_dec) );
    }

    echo 'Range argument is not in 1.2.3.4/24 or 1.2.3.4/255.255.255.0 format';
    return false;
  }

}
?>

(Je n'ai pas développé cela; c'est développé par Paul Gregg ( http://pgregg.com/ )

2
erik404

Voici une fonction 64 bits rapide pour le faire, veuillez commenter la ligne de retour dont vous n'avez pas besoin. Accepter tout Ipv4 valide avec ou sans préfixe de routage CIDR valide, par exemple 63.161.156.0/24 ou 63.161.156.0

<?php
function cidr2range($ipv4){
if ($ip=strpos($ipv4,'/'))
{$n_ip=(1<<(32-substr($ipv4,1+$ip)))-1;   $ip_dec=ip2long(substr($ipv4,0,$ip)); }
else
{$n_ip=0;                                   $ip_dec=ip2long($ipv4);             }
$ip_min=$ip_dec&~$n_ip;
$ip_max=$ip_min+$n_ip;
#Array(2) of Decimal Values Range
return [$ip_min,$ip_max];
#Array(2) of Ipv4 Human Readable Range
return [long2ip($ip_min),long2ip($ip_max)];
#Array(2) of Ipv4 and Subnet Range
return [long2ip($ip_min),long2ip(~$n_ip)];
#Array(2) of Ipv4 and Wildcard Bits
return [long2ip($ip_min),long2ip($n_ip)];
#Integer Number of Ipv4 in Range
return ++$n_ip;
}

Pour vérifier rapidement si une donnée ipv4 correspond à un CIDR donné vous pouvez le faire en ligne comme dans cet exemple

<?php
$given_cidr='55.55.55.0/24';
$given_ipv4='55.55.55.55';
if(($range=cidr2range($given_cidr)) &&
($check=ip2long($given_ipv4))!==false &&
$check>=$range[0] && $check<=$range[1])
{
echo 'Yes, '.$given_ipv4.' is included in '.$given_cidr;
}
else
{
echo 'No, '.$given_ipv4.' is not included in '.$given_cidr;
}

Pour obtenir la plage complète en tant que tableau pour une IP donnée (avec ou sans préfixe de routage CIDR), vous pouvez utiliser le code suivant mais faites attention car par exemple 25.25.25.25/16 retourne un tableau avec 65536 éléments et vous pouvez facilement manquer de mémoire en utilisant un préfixe de routage plus petit

<?php
$result=cidr2range($ipv4);
for($ip_dec=$result[0];$ip_dec<=$result[1];$ip_dec++)
$full_range[$ip_dec]=long2ip($ip_dec);
print_r($full_range);

Pour vérifier rapidement si une donnée ipv4 correspond à un tableau IP donné (avec ou sans préfixe de routage CIDR)

<?php
#This code is checking if a given ip belongs to googlebot
$given_ipv4='74.125.61.208';
$given_cidr_array=['108.59.93.43/32','108.59.93.40/31','108.59.93.44/30','108.59.93.32/29','108.59.93.48/28','108.59.93.0/27','108.59.93.64/26','108.59.93.192/26','108.59.92.192/27','108.59.92.128/26','108.59.92.96/27','108.59.92.0/27','108.59.94.208/29','108.59.94.192/28','108.59.94.240/28','108.59.94.128/26','108.59.94.16/29','108.59.94.0/28','108.59.94.32/27','108.59.94.64/26','108.59.95.0/24','108.59.88.0/22','108.59.81.0/27','108.59.80.0/24','108.59.82.0/23','108.59.84.0/22','108.170.217.128/28','108.170.217.160/27','108.170.217.192/26','108.170.217.0/25','108.170.216.0/24','108.170.218.0/23','108.170.220.0/22','108.170.208.0/21','108.170.192.0/20','108.170.224.0/19','108.177.0.0/17','104.132.0.0/14','104.154.0.0/15','104.196.0.0/14','107.167.160.0/19','107.178.192.0/18','125.17.82.112/30','125.16.7.72/30','74.125.0.0/16','72.14.192.0/18','77.109.131.208/28','77.67.50.32/27','66.102.0.0/20','66.227.77.144/29','66.249.64.0/19','67.148.177.136/29','64.124.98.104/29','64.71.148.240/29','64.68.64.64/26','64.68.80.0/20','64.41.221.192/28','64.41.146.208/28','64.9.224.0/19','64.233.160.0/19','65.171.1.144/28','65.170.13.0/28','65.167.144.64/28','65.220.13.0/24','65.216.183.0/24','70.32.132.0/23','70.32.128.0/22','70.32.136.0/21','70.32.144.0/20','85.182.250.128/26','85.182.250.0/25','80.239.168.192/26','80.149.20.0/25','61.246.224.136/30','61.246.190.124/30','63.237.119.112/29','63.226.245.56/29','63.158.137.224/29','63.166.17.128/25','63.161.156.0/24','63.88.22.0/23','41.206.188.128/26','12.234.149.240/29','12.216.80.0/24','8.34.217.24/29','8.34.217.0/28','8.34.217.32/27','8.34.217.64/26','8.34.217.128/25','8.34.216.0/24','8.34.218.0/23','8.34.220.0/22','8.34.208.128/29','8.34.208.144/28','8.34.208.160/27','8.34.208.192/26','8.34.208.0/25','8.34.209.0/24','8.34.210.0/23','8.34.212.0/22','8.35.195.128/28','8.35.195.160/27','8.35.195.192/26','8.35.195.0/25','8.35.194.0/24','8.35.192.0/23','8.35.196.0/22','8.35.200.0/21','8.8.8.0/24','8.8.4.0/24','8.6.48.0/21','4.3.2.0/24','23.236.48.0/20','23.251.128.0/19','216.239.32.0/19','216.252.220.0/22','216.136.145.128/27','216.33.229.160/29','216.33.229.144/29','216.34.7.176/28','216.58.192.0/19','216.109.75.80/28','216.74.130.48/28','216.74.153.0/27','217.118.234.96/28','208.46.199.160/29','208.44.48.240/29','208.21.209.0/28','208.184.125.240/28','209.185.108.128/25','209.85.128.0/17','213.200.103.128/26','213.200.99.192/26','213.155.151.128/26','199.192.112.224/29','199.192.112.192/27','199.192.112.128/26','199.192.112.0/25','199.192.113.176/28','199.192.113.128/27','199.192.113.192/26','199.192.113.0/25','199.192.115.80/28','199.192.115.96/27','199.192.115.0/28','199.192.115.128/25','199.192.114.192/26','199.192.114.0/25','199.223.232.0/21','198.108.100.192/28','195.16.45.144/29','192.104.160.0/23','192.158.28.0/22','192.178.0.0/15','206.160.135.240/28','207.223.160.0/20','203.222.167.144/28','173.255.125.72/29','173.255.125.80/28','173.255.125.96/27','173.255.125.0/27','173.255.125.128/25','173.255.124.240/29','173.255.124.232/29','173.255.124.192/27','173.255.124.128/29','173.255.124.144/28','173.255.124.160/27','173.255.124.48/29','173.255.124.32/28','173.255.124.0/27','173.255.124.64/26','173.255.126.0/23','173.255.122.128/26','173.255.122.64/26','173.255.123.0/24','173.255.121.128/26','173.255.121.0/25','173.255.120.0/24','173.255.117.32/27','173.255.117.64/26','173.255.117.128/25','173.255.116.192/27','173.255.116.128/26','173.255.116.0/25','173.255.118.0/23','173.255.112.0/22','173.194.0.0/16','172.102.8.0/21','172.253.0.0/16','172.217.0.0/16','162.216.148.0/22','162.222.176.0/21','180.87.33.64/26','128.177.109.0/26','128.177.119.128/25','128.177.163.0/25','130.211.0.0/16','142.250.0.0/15','146.148.0.0/17'];
echo '<pre>';
$in_range=false;
if (($given_ipv4_dec=ip2long($given_ipv4))!==false)
{
foreach($given_cidr_array as $given_cidr){
if(($range=cidr2range($given_cidr)) &&
$given_ipv4_dec>=$range[0] && $given_ipv4_dec<=$range[1])
{
$in_range=true;
echo $given_ipv4.' matched '.$given_cidr.' ('.join(array_map('long2ip',$range),' - ').")\n";
}
}
}
echo $given_ipv4.' is probably'.($in_range?'':' not').' a Googlebot IP';

Pour fonctionner rapidement, la fonction ne vérifie pas l'entrée, mais formellement, il doit s'agir d'une chaîne correspondant à l'expression régulière suivante

#^(?:((?:0)|(?:2(?:(?:[0-4][0-9])|(?:5[0-5])))|(?:1?[0-9]{1,2}))\.((?:0)|(?:2(?:(?:[0-4][0-9])|(?:5[0-5])))|(?:1?[0-9]{1,2}))\.((?:0)|(?:2(?:(?:[0-4][0-9])|(?:5[0-5])))|(?:1?[0-9]{1,2}))\.((?:0)|(?:2(?:(?:[0-4][0-9])|(?:5[0-5])))|(?:1?[0-9]{1,2}))(?:/((?:(?:0)|(?:3[0-2])|(?:[1-2]?[0-9]))))?)$#

Si vous voulez vérifier l'entrée avant d'utiliser la fonction

<?php
if (is_string($ipv4) && preg_match('#^(?:((?:0)|(?:2(?:(?:[0-4][0-9])|(?:5[0-5])))|(?:1?[0-9]{1,2}))\.((?:0)|(?:2(?:(?:[0-4][0-9])|(?:5[0-5])))|(?:1?[0-9]{1,2}))\.((?:0)|(?:2(?:(?:[0-4][0-9])|(?:5[0-5])))|(?:1?[0-9]{1,2}))\.((?:0)|(?:2(?:(?:[0-4][0-9])|(?:5[0-5])))|(?:1?[0-9]{1,2}))(?:/((?:(?:0)|(?:3[0-2])|(?:[1-2]?[0-9]))))?)$#',$ipv4))
{
#This is a valid ipv4 with or without CIDR Routing Prefix
$result=cidr2range($ipv4);
print_r($result);
}

Alors le formel réponse à votre question est le suivant

<?php
#Requiring cidr2range shown above function
function cidr_match($mixed_ip,$mixed_cidr){
if (!is_array($mixed_ip)){
$string_mode=true;
$mixed_ip=[$mixed_ip=>0];
}
else $mixed_ip=array_fill_keys($mixed_ip,0);
if (!is_array($mixed_cidr)) $mixed_cidr=[$mixed_cidr];
foreach($mixed_ip   as $ip => &$result)
foreach($mixed_cidr as $cidr)
{
if(($range=cidr2range($cidr)) &&
($check=ip2long($ip))!==false &&
$check>=$range[0] && $check<=$range[1]){
$result=$cidr;
break;
}
}
$mixed_ip=array_filter($mixed_ip);
return $string_mode?($mixed_ip?true:false):$mixed_ip;
}

print '<pre>';

#Your example
$ips = array('10.2.1.100', '10.2.1.101', '10.5.1.100', '1.2.3.4');

foreach ($ips as $IP) {
    if (cidr_match($IP, '10.2.0.0/16') == true) {
        print "you're in the 10.2 subnet\n"; 
    }
}


#Also working with IP array and/or CIDR array
#If IP array is given then return an array containing IP (keys) matching CIDR (values)
$result=cidr_match($ips,['20.2.0.0/16','10.2.0.0/15']);
foreach($result as $ip => $cidr){
print "$ip is in the $cidr subnet\n"; 
}

Vous pouvez compiler votre propre fonction en utilisant ces exemples, j'espère que ces quelques lignes vous ont aidé…

2
Php'Regex

C'est peut-être utile à quelqu'un.

Convertissez le masque de bits en masque IP:

// convert 12 => 255.240.0.0
// ip2long('255.255.255.255') == -1
$ip = long2ip((-1 << (32 - $bit)) & -1);

Convertir le masque IP en masque de bits:

// convert 255.240.0.0 => 12

// is valid IP
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === false) {
    throw new \InvalidArgumentException(sprintf('Invalid IP "%s".', $ip));
}

// convert decimal to binary
$mask = '';
foreach (explode('.', $ip) as $octet) {
    $mask .= str_pad(decbin($octet), 8, '0', STR_PAD_LEFT);
}

// check mask
if (strpos('01', $mask) !== false) {
    // valid   11111111111111111111111100000000 -> 255.255.255.0
    // invalid 11111111111111111111111100000001 -> 255.255.255.1
    throw new \InvalidArgumentException(sprintf('IP mask "%s" is not valid.', $ip));
}

$bit = substr_count($mask, '1'); // bit mask
1
ghost404

Vous pouvez également utiliser Net_IPv4 PEAR .

function cidr_match($ip, $net){
  include_once("Net/IPv4.php");
  $objIP = new Net_IPv4();
  return $objIP->ipInNetwork($ip, $net);
}
1
Evgeny Liskovets

J'ai récemment dû faire correspondre une adresse IP à un masque CIDR et suis tombé sur cet article. Vous trouverez ci-dessous une approche légèrement différente basée sur les idées ci-dessus et comprend une vérification de l'entrée CIDR. La fonction retourne false si un format CIDR incorrect est soumis.

J'ai posté cette solution pour tous ceux qui ont besoin d'une fonction clé en main qui a été testée.

/**
 * Validates subnet specified by CIDR notation.of the form IP address followed by 
 * a '/' character and a decimal number specifying the length, in bits, of the subnet
 * mask or routing prefix (number from 0 to 32).
 *
 * @param $ip - IP address to check
 * @param $cidr - IP address range in CIDR notation for check
 * @return bool - true match found otherwise false
 */
function cidr_match($ip, $cidr) {
    $outcome = false;
    $pattern = '/^(([01]?\d?\d|2[0-4]\d|25[0-5])\.){3}([01]?\d?\d|2[0-4]\d|25[0-5])\/(\d{1}|[0-2]{1}\d{1}|3[0-2])$/';
    if (preg_match($pattern, $cidr)){
        list($subnet, $mask) = explode('/', $cidr);
        if (ip2long($ip) >> (32 - $mask) == ip2long($subnet) >> (32 - $mask)) {
            $outcome = true;
        }
    }
    return $outcome;
}

Les données de test sont affichées dans l'image ci-dessous:

Test Results IP Checks

1
Clinton

Juste une note, la réponse d'Alnitak fonctionne en 32/64 bits.

Voici une version préparée de celui-ci, pour une protection rapide contre le spam basée sur les listes IP des pays que vous pouvez obtenir partout. google for country ip list or country ip block (Doivent en donner une ici, vraiment difficile à trouver dans la navigation de cette page de sites: Country ip block generator )

Copiez-collez votre liste IP cidr dans la chaîne $ cidrs. Et mettez ce code juste avant la page html, éventuellement dans le fichier header.php.

Peut également être utilisé pour filtrer l'utilisation d'Adsense dans les modèles de page en fonction du pays.

Il s'agit uniquement d'une solution d'urgence au milieu de la nuit. Parfois, il faut trouver quelque chose comme ça pour un client rapidement hier, alors le voici.

//++++++++++++++++++++++
//COUNTRY SPAM PROTECTOR
//speed: ~5ms @ 2000 cidrs
//comments start with #
//++++++++++++++++++++++
$cidrs=
'
#yourcountry
1.3.4.5/21
#mycountry
6.7.8.9/20
';
//$cidrs.="\n".'123.12.12.12/32';//test, your ip
$cidrs_ar=preg_split('/\s+/',$cidrs,-1,PREG_SPLIT_NO_EMPTY);
$ip=@$_SERVER['REMOTE_ADDR'];
$iplong=ip2long($ip);
//var_export($cidrs_ar);var_export($ip);var_export($iplong);
if($iplong)
  foreach($cidrs_ar as $cidr)
    {
    $ar=explode ('/', $cidr);
    $netiplong=ip2long($ar[0]);
    if($netiplong===false) continue;
    $mask=intval(@$ar[1]);
    if(!$mask) continue;
    $bitmask=-1 <<(32-$mask);
    if(($iplong & $bitmask) == ($netiplong & $bitmask))
        {
        header('Location: http://www.someotherwebsite.com/',true,303);
        exit;
        }
    }
1
Johan
function cidr_match($ipStr, $cidrStr) {
  $ip = ip2long($ipStr);
  $cidrArr = split('/',$cidrStr);
  $maskIP = ip2long($cidrArr[0]);
  $maskBits = 32 - $cidrArr[1];
  return (($ip>>$maskBits) == ($maskIP>>$maskBits));
}
1
vartec

Je veux que vous regardiez mes quelques lignes. Les exemples que les gens ont suggérés avant moi ne semblent pas fonctionner. Une des raisons étant, si je comprends bien, est que les bits de masque CIDR sont des nombres binaires, donc le décalage de bits doit être effectué sur un nombre binaire. J'ai essayé de convertir les longues adresses IP en binaires, mais j'ai rencontré une limite de nombre binaire max. OK, voici mes quelques lignes ... J'attends vos commentaires.

function cidr_match($ipStr, $cidrStr) {

$ipStr = explode('.', $ipStr);
foreach ($ipStr as $key => $val) {
    $ipStr[$key] = str_pad(decbin($val), 8, '0', STR_PAD_LEFT);
    }
$ip = '';
foreach ($ipStr as $binval) {
    $ip = $ip . $binval;
    }

$cidrArr = explode('/',$cidrStr);

$maskIP = explode('.', $cidrArr[0]);
foreach ($maskIP as $key => $val) {
    $maskIP[$key] = str_pad(decbin($val), 8, '0', STR_PAD_LEFT);
    }
$maskIP = '';
foreach ($ipStr as $binval) {
    $maskIP = $maskIP . $binval;
    }
$maskBits = 32 - $cidrArr[1];
return (($ip>>$maskBits) == ($maskIP>>$maskBits));  
}
0
jammer