netfilter: add nf_ipv6_ops hook to fix xt_addrtype with IPv6
authorFlorian Westphal <fw@strlen.de>
Fri, 17 May 2013 03:56:10 +0000 (03:56 +0000)
committerPablo Neira Ayuso <pablo@netfilter.org>
Thu, 23 May 2013 09:58:55 +0000 (11:58 +0200)
commit2a7851bffb008ff4882eee673da74718997b4265
tree262c2fc71bd91eabf6bd947944d2050ff1cec923
parent497574c72c9922cf20c12aed15313c389f722fa0
netfilter: add nf_ipv6_ops hook to fix xt_addrtype with IPv6

Quoting https://bugzilla.netfilter.org/show_bug.cgi?id=812:

[ ip6tables -m addrtype ]
When I tried to use in the nat/PREROUTING it messes up the
routing cache even if the rule didn't matched at all.
[..]
If I remove the --limit-iface-in from the non-working scenario, so just
use the -m addrtype --dst-type LOCAL it works!

This happens when LOCAL type matching is requested with --limit-iface-in,
and the default ipv6 route is via the interface the packet we test
arrived on.

Because xt_addrtype uses ip6_route_output, the ipv6 routing implementation
creates an unwanted cached entry, and the packet won't make it to the
real/expected destination.

Silently ignoring --limit-iface-in makes the routing work but it breaks
rule matching (--dst-type LOCAL with limit-iface-in is supposed to only
match if the dst address is configured on the incoming interface;
without --limit-iface-in it will match if the address is reachable
via lo).

The test should call ipv6_chk_addr() instead.  However, this would add
a link-time dependency on ipv6.

There are two possible solutions:

1) Revert the commit that moved ipt_addrtype to xt_addrtype,
   and put ipv6 specific code into ip6t_addrtype.
2) add new "nf_ipv6_ops" struct to register pointers to ipv6 functions.

While the former might seem preferable, Pablo pointed out that there
are more xt modules with link-time dependeny issues regarding ipv6,
so lets go for 2).

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/linux/netfilter_ipv6.h
include/net/addrconf.h
net/ipv6/addrconf.c
net/ipv6/netfilter.c
net/netfilter/core.c
net/netfilter/xt_addrtype.c