Mercurial > dovecot > core-2.2
diff src/lib/network.c @ 7517:e0007da64cdc HEAD
Moved net_is_in_network() to lib/network.c.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Thu, 15 May 2008 07:43:13 +0300 |
parents | da971cec0395 |
children | 85203e817f90 |
line wrap: on
line diff
--- a/src/lib/network.c Thu May 15 07:01:40 2008 +0300 +++ b/src/lib/network.c Thu May 15 07:43:13 2008 +0300 @@ -703,3 +703,50 @@ return TRUE; } + +bool net_is_in_network(const struct ip_addr *ip, + const struct ip_addr *net_ip, unsigned int bits) +{ + const uint32_t *ip1, *ip2; + uint32_t mask; + unsigned int pos, i; + + if (IPADDR_IS_V4(ip) != IPADDR_IS_V4(net_ip)) { + /* one is IPv6 and one is IPv4 */ + return FALSE; + } + i_assert(IPADDR_IS_V6(ip) == IPADDR_IS_V6(net_ip)); + + if (IPADDR_IS_V4(ip)) { + ip1 = &ip->u.ip4.s_addr; + ip2 = &net_ip->u.ip4.s_addr; + } else { +#ifdef HAVE_IPV6 + ip1 = (const void *)&ip->u.ip6; + ip2 = (const void *)&net_ip->u.ip6; +#else + /* shouldn't get here */ + return FALSE; +#endif + } + + /* check first the full 32bit ints */ + for (pos = 0, i = 0; pos + 32 <= bits; pos += 32, i++) { + if (ip1[i] != ip2[i]) + return FALSE; + } + + /* check the last full bytes */ + for (mask = 0xff; pos + 8 <= bits; pos += 8, mask <<= 8) { + if ((ip1[i] & mask) != (ip2[i] & mask)) + return FALSE; + } + + /* check the last bits, they're reversed in bytes */ + bits -= pos; + for (mask = 0x80 << (pos % 32); bits > 0; bits--, mask >>= 1) { + if ((ip1[i] & mask) != (ip2[i] & mask)) + return FALSE; + } + return TRUE; +}