diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2009-10-06 21:21:49 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2009-10-06 21:21:49 +0000 |
commit | 97550e178734cbfb577fa6b89efc04968a4f9c3b (patch) | |
tree | db990b0c33fd2bf3aef1b7f1058172e301f8be03 /sys/netinet | |
parent | 37fb3c82fd5a3ecf936d94f1a66c44aa7868ecf4 (diff) |
Redo the route lookup in the output (and IPv6 forwarding) path if the
destination of a packet was changed by pf. This allows for some evil
games with rdr-to or nat-to but is mostly needed for better rdomain/rtable
support. This is a first step and more work and cleanup is needed.
Here a list of what works and what does not (needs a patched pfctl):
pass out rdr-to:
from local rdr-to local addr works (if state tracking on lo0 is done)
from remote rdr-to local addr does NOT work
from local rdr-to remote works
from remote rdr-to remote works
pass in nat-to:
from remote nat-to local addr does NOT work
from remote nat-to non-local addr works
non-local is an IP that is routed to the FW but is not assigned on the FW.
The non working cases need some magic to correctly rewrite the incomming
packet since the rewriting would happen outbound which is too late.
"time to get it in" deraadt@
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/ip_output.c | 25 |
1 files changed, 23 insertions, 2 deletions
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index 8247955acab..b59ffcaaf2d 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_output.c,v 1.194 2009/06/05 00:05:22 claudio Exp $ */ +/* $OpenBSD: ip_output.c,v 1.195 2009/10/06 21:21:48 claudio Exp $ */ /* $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $ */ /* @@ -245,6 +245,10 @@ ip_output(struct mbuf *m0, ...) ip->ip_src = ia->ia_addr.sin_addr; } +#if NPF > 0 +reroute: +#endif + #ifdef IPSEC if (!ipsec_in_use && inp == NULL) goto done_spd; @@ -594,6 +598,13 @@ sendit: } ip = mtod(m, struct ip *); hlen = ip->ip_hl << 2; + /* + * PF_TAG_REROUTE handling or not... + * Packet is entering IPsec so the routing is + * already overruled by the IPsec policy. + * Until now the change was not reconsidered. + * What's the behaviour? + */ #endif tdb = gettdb(sspi, &sdst, sproto); @@ -703,9 +714,19 @@ sendit: } if (m == NULL) goto done; - ip = mtod(m, struct ip *); hlen = ip->ip_hl << 2; + if ((m->m_pkthdr.pf.flags & (PF_TAG_REROUTE | PF_TAG_GENERATED)) == + (PF_TAG_REROUTE | PF_TAG_GENERATED)) + /* already rerun the route lookup, go on */ + m->m_pkthdr.pf.flags &= ~(PF_TAG_GENERATED | PF_TAG_REROUTE); + else if (m->m_pkthdr.pf.flags & PF_TAG_REROUTE) { + /* tag as generated to skip over pf_test on rerun */ + m->m_pkthdr.pf.flags |= PF_TAG_GENERATED; + ro = NULL; + donerouting = 0; + goto reroute; + } #endif #ifdef IPSEC |