summaryrefslogtreecommitdiff
path: root/sys/netinet
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2009-10-06 21:21:49 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2009-10-06 21:21:49 +0000
commit97550e178734cbfb577fa6b89efc04968a4f9c3b (patch)
treedb990b0c33fd2bf3aef1b7f1058172e301f8be03 /sys/netinet
parent37fb3c82fd5a3ecf936d94f1a66c44aa7868ecf4 (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.c25
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