Skip to content

Commit

Permalink
netfilter: xt_iprange: Incorrect xt_iprange boundary check for IPv6
Browse files Browse the repository at this point in the history
iprange_ipv6_sub was substracting 2 unsigned ints and then casting
the result to int to find out whether they are lt, eq or gt each
other, this doesn't work if the full 32 bits of each part
can be used in IPv6 addresses. Patch should remedy that without
significant performance penalties. Also number of ntohl
calls can be reduced this way (Jozsef Kadlecsik).

Signed-off-by: Thomas Jacob <jacob@internet24.de>
Signed-off-by: Patrick McHardy <kaber@trash.net>
  • Loading branch information
Thomas Jacob authored and Patrick McHardy committed Jan 24, 2011
1 parent c71caf4 commit 08b5194
Showing 1 changed file with 7 additions and 9 deletions.
16 changes: 7 additions & 9 deletions net/netfilter/xt_iprange.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,13 @@ iprange_mt4(const struct sk_buff *skb, struct xt_action_param *par)
}

static inline int
iprange_ipv6_sub(const struct in6_addr *a, const struct in6_addr *b)
iprange_ipv6_lt(const struct in6_addr *a, const struct in6_addr *b)
{
unsigned int i;
int r;

for (i = 0; i < 4; ++i) {
r = ntohl(a->s6_addr32[i]) - ntohl(b->s6_addr32[i]);
if (r != 0)
return r;
if (a->s6_addr32[i] != b->s6_addr32[i])
return ntohl(a->s6_addr32[i]) < ntohl(b->s6_addr32[i]);
}

return 0;
Expand All @@ -75,15 +73,15 @@ iprange_mt6(const struct sk_buff *skb, struct xt_action_param *par)
bool m;

if (info->flags & IPRANGE_SRC) {
m = iprange_ipv6_sub(&iph->saddr, &info->src_min.in6) < 0;
m |= iprange_ipv6_sub(&iph->saddr, &info->src_max.in6) > 0;
m = iprange_ipv6_lt(&iph->saddr, &info->src_min.in6);
m |= iprange_ipv6_lt(&info->src_max.in6, &iph->saddr);
m ^= !!(info->flags & IPRANGE_SRC_INV);
if (m)
return false;
}
if (info->flags & IPRANGE_DST) {
m = iprange_ipv6_sub(&iph->daddr, &info->dst_min.in6) < 0;
m |= iprange_ipv6_sub(&iph->daddr, &info->dst_max.in6) > 0;
m = iprange_ipv6_lt(&iph->daddr, &info->dst_min.in6);
m |= iprange_ipv6_lt(&info->dst_max.in6, &iph->daddr);
m ^= !!(info->flags & IPRANGE_DST_INV);
if (m)
return false;
Expand Down

0 comments on commit 08b5194

Please sign in to comment.