2011-08-27 2 views
3

J'ai besoin de savoir, est ip appartiennent à un masque IP. Par exemple:IP cidr match fonction

ip = 192.168.0.1 masque = 192.168.0.1/24.

Je trouve que la fonction convertir IP masque:

inet_cidrtoaddr(int cidr, struct in_addr *addr) 
{ 
     int ocets; 

     if (cidr < 0 || cidr > 32) { 
       errno = EINVAL; 
       return -1; 
     } 
     ocets = (cidr + 7)/8; 

     addr->s_addr = 0; 
     if (ocets > 0) { 
       memset(&addr->s_addr, 255, (size_t)ocets - 1); 
       memset((unsigned char *)&addr->s_addr + (ocets - 1), 
         (256 - (1 << (32 - cidr) % 8)), 1); 
     } 

     return 0; 
} 

Comment puis-je comparer ip et la gamme cidr?

+0

forme plus facile de cette fonction: 'addr-> s_addr = 0xffffffffU << (32 - Longueur du préfixe)' –

+2

@ Steve-o: Cela conduit à des résultats non définis si 'prefixLength' est 0. –

Répondre

2

Si vous avez l'adresse IP, l'adresse réseau et le masque de réseau, vous pouvez utiliser une fonction comme ceci:

bool 
is_in_net (
     const struct in_addr* addr,  /* host byte order */ 
     const struct in_addr* netaddr, 
     const struct in_addr* netmask 
     ) 
{ 
    if ((addr->s_addr & netmask->s_addr) == (netaddr->s_addr & netmask->s_addr)) 
     return true; 
    return false; 
} 
2

Cette fonction calcule un masque de réseau (par exemple quelque chose de la forme 255.255.255.128). Donc, pour vérifier si une adresse IP spécifiée tombe dans un sous-réseau spécifié, il suffit d'appliquer le masque à l'adresse CIDR et à l'adresse IP (vous faites cela avec bitwise AND). Si les résultats sont les mêmes, l'adresse IP est valide.

6

Donc, pour mettre Olis réponse dans le code:

// Check if 192.168.0.1 is inside 192.168.0.0/24 
in_addr ip, net, netmask; 
inet_aton("192.168.0.1", &ip); 
inet_aton("192.168.0.0", &net); 

il a dit:

inet_cidrtoaddr(24, &netmask); 
bool is_inside = ((ip.s_addr & netmask.s_addr) == (net.s_addr & netmask.s_addr)); 

Je préfère la méthode addr4_match si:

bool cidr_match(const in_addr &addr, const in_addr &net, uint8_t bits) { 
    if (bits == 0) { 
    // C99 6.5.7 (3): u32 << 32 is undefined behaviour 
    return true; 
    } 
    return !((addr.s_addr^net.s_addr) & htonl(0xFFFFFFFFu << (32 - bits))); 
} 
bool is_inside = cidr_match(ip, net, 24); 

J'ai expérimenté avec un groupe d'entrée différent: https://gist.github.com/duedal/b83303b4988a4afb2a75

Si quelqu'un trouver ce manque une solution IPv6 aussi:

bool cidr6_match(const in6_addr &address, const in6_addr &network, uint8_t bits) { 
#ifdef LINUX 
    const uint32_t *a = address.s6_addr32; 
    const uint32_t *n = network.s6_addr32; 
#else 
    const uint32_t *a = address.__u6_addr.__u6_addr32; 
    const uint32_t *n = network.__u6_addr.__u6_addr32; 
#endif 
    int bits_whole, bits_incomplete; 
    bits_whole = bits >> 5;   // number of whole u32 
    bits_incomplete = bits & 0x1F; // number of bits in incomplete u32 
    if (bits_whole) { 
    if (memcmp(a, n, bits_whole << 2)) { 
     return false; 
    } 
    } 
    if (bits_incomplete) { 
    uint32_t mask = htonl((0xFFFFFFFFu) << (32 - bits_incomplete)); 
    if ((a[bits_whole]^n[bits_whole]) & mask) { 
     return false; 
    } 
    } 
    return true; 
} 

Vérifiez si 2001: DB8 :: FF00: 42: 8329 est présent en 2001: db8/32. Méfiez-vous inet_net_pton est très pointilleux, c'est 2001: db8/32 pas 2001: db8 ::/32. Cependant 2001: db8 ::/48 est parfaitement valide (aussi connu comme 2001: db8: 0/48).

in6_addr ip6, net6, net6_48; 
memset(&net6, 0, sizeof(net6)); 
memset(&net6_48, 0, sizeof(net6_48)); 
assert(inet_pton(AF_INET6, "2001:db8::ff00:42:8329", &ip6)); 

int bits = inet_net_pton(AF_INET6, "2001:db8/32", &net6, sizeof(net6)); 
assert((bits != -1)); // assert that inet_net_pton understood us 
bool is_inside6 = cidr6_match(ip6, net6, bits); 

int bits_48 = inet_net_pton(AF_INET6, "2001:db8::/48", &net6_48, sizeof(net6_48)); 
assert((bits_48 == 48)); 
bool is_inside6_48 = cidr6_match(ip6, net6_48, bits_48); 
+0

Remarque: pour IPv6 voir http://grothoff.org/christian/rmv608.pdf et http://stackoverflow.com/questions/24723439/how-to-compare-an-ipv6-is-greater-less-than-in-c/43481706 # 43481706 – pevik

Questions connexes