Page MenuHomeFreeBSD

D41479.id126141.diff
No OneTemporary

D41479.id126141.diff

diff --git a/sys/netinet/ip_fastfwd.c b/sys/netinet/ip_fastfwd.c
--- a/sys/netinet/ip_fastfwd.c
+++ b/sys/netinet/ip_fastfwd.c
@@ -239,12 +239,13 @@
struct route ro;
struct sockaddr_in *dst;
const struct sockaddr *gw;
- struct in_addr dest, odest, rtdest, osrc;
+ struct in_addr dest, odest, osrc;
uint16_t ip_len, ip_off;
int error = 0;
struct m_tag *fwd_tag = NULL;
struct mbuf *mcopy = NULL;
struct in_addr redest;
+ bool rt_changed = false;
/*
* Are we active and forwarding packets?
*/
@@ -373,7 +374,9 @@
#endif
/*
- * Next hop forced by pfil(9) hook?
+ * After pfil_mbuf_in we use the changed destination no matter if it
+ * comes from IP headers (see right after pfil_mbuf_in) or from the
+ * PACKET_TAG_IPFORWARD tag.
*/
if ((m->m_flags & M_IP_NEXTHOP) &&
((fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL)) != NULL)) {
@@ -384,6 +387,7 @@
(fwd_tag + 1))->sin_addr.s_addr;
m_tag_delete(m, fwd_tag);
m->m_flags &= ~M_IP_NEXTHOP;
+ rt_changed = true;
}
/*
@@ -392,17 +396,13 @@
if (ip_findroute(&nh, dest, m) != 0)
return (NULL); /* icmp unreach already sent */
- /*
- * Avoid second route lookup by caching destination.
- */
- rtdest.s_addr = dest.s_addr;
-
/*
* Step 5: outgoing firewall packet processing
*/
if (!PFIL_HOOKED_OUT(V_inet_pfil_head))
goto passout;
+ odest.s_addr = ip->ip_dst.s_addr;
if (pfil_mbuf_out(V_inet_pfil_head, &m, nh->nh_ifp,
NULL) != PFIL_PASS)
goto drop;
@@ -411,18 +411,21 @@
M_ASSERTPKTHDR(m);
ip = mtod(m, struct ip *);
- dest.s_addr = ip->ip_dst.s_addr;
/*
- * Destination address changed?
+ * After pfil_mbuf_out we might keep the destination set by pfil_mbuf_in
+ * if it was set via the PACKET_TAG_IPFORWARD tag.
*/
if (m->m_flags & M_IP_NEXTHOP)
fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
else
fwd_tag = NULL;
- if (odest.s_addr != dest.s_addr || fwd_tag != NULL) {
+
+ if (!rt_changed && odest.s_addr != ip->ip_dst.s_addr) {
+ dest.s_addr = ip->ip_dst.s_addr;
/*
* Is it now for a local address on this host?
+ * XXX Should we direct to local also by routing, not just NAT?
*/
if (m->m_flags & M_FASTFWD_OURS || in_localip(dest)) {
forwardlocal:
@@ -432,20 +435,23 @@
m->m_flags |= M_FASTFWD_OURS;
return (m);
}
- /*
- * Redo route lookup with new destination address
- */
- if (fwd_tag) {
- dest.s_addr = ((struct sockaddr_in *)
- (fwd_tag + 1))->sin_addr.s_addr;
- m_tag_delete(m, fwd_tag);
- m->m_flags &= ~M_IP_NEXTHOP;
- }
- if (dest.s_addr != rtdest.s_addr &&
- ip_findroute(&nh, dest, m) != 0)
- return (NULL); /* icmp unreach already sent */
+ rt_changed = true;
}
+ if (fwd_tag) {
+ dest.s_addr = ((struct sockaddr_in *)
+ (fwd_tag + 1))->sin_addr.s_addr;
+ m_tag_delete(m, fwd_tag);
+ m->m_flags &= ~M_IP_NEXTHOP;
+ rt_changed = true;
+ }
+
+ /*
+ * Redo route lookup with new destination address
+ */
+ if (rt_changed && ip_findroute(&nh, dest, m) != 0)
+ return (NULL); /* icmp unreach already sent */
+
passout:
/*
* Step 6: send off the packet
diff --git a/sys/netinet6/ip6_fastfwd.c b/sys/netinet6/ip6_fastfwd.c
--- a/sys/netinet6/ip6_fastfwd.c
+++ b/sys/netinet6/ip6_fastfwd.c
@@ -92,13 +92,14 @@
struct mbuf*
ip6_tryforward(struct mbuf *m)
{
- struct sockaddr_in6 dst;
+ struct sockaddr_in6 dst, odst;
struct nhop_object *nh;
struct m_tag *fwd_tag;
struct ip6_hdr *ip6;
struct ifnet *rcvif;
uint32_t plen;
int error;
+ bool rt_changed = false;
/*
* Fallback conditions to ip6_input for slow path processing.
@@ -160,6 +161,11 @@
dst.sin6_len = sizeof(dst);
dst.sin6_addr = ip6->ip6_dst;
+ bzero(&odst, sizeof(odst));
+ odst.sin6_family = AF_INET6;
+ odst.sin6_len = sizeof(dst);
+ odst.sin6_addr = ip6->ip6_dst;
+
/*
* Incoming packet firewall processing.
*/
@@ -180,6 +186,10 @@
if (m->m_flags & M_FASTFWD_OURS)
return (m);
+ /*
+ * After pfil_mbuf_in we use the changed destination no matter if it
+ * comes from IP headers or from the PACKET_TAG_IPFORWARD tag.
+ */
ip6 = mtod(m, struct ip6_hdr *);
if ((m->m_flags & M_IP6_NEXTHOP) &&
(fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL)) != NULL) {
@@ -189,6 +199,7 @@
bcopy((fwd_tag + 1), &dst, sizeof(dst));
m->m_flags &= ~M_IP6_NEXTHOP;
m_tag_delete(m, fwd_tag);
+ rt_changed = true;
} else {
/* Update dst since pfil could change it */
dst.sin6_addr = ip6->ip6_dst;
@@ -215,6 +226,7 @@
/*
* Outgoing packet firewall processing.
*/
+ odst.sin6_addr = ip6->ip6_dst;
if (pfil_mbuf_out(V_inet6_pfil_head, &m, nh->nh_ifp,
NULL) != PFIL_PASS)
goto dropout;
@@ -245,30 +257,34 @@
*/
return (m);
}
- /*
- * Again. A packet filter could change the destination address.
- */
+
ip6 = mtod(m, struct ip6_hdr *);
+
+ /*
+ * After pfil_mbuf_out we might keep the destination set by pfil_mbuf_in
+ * if it was set via the PACKET_TAG_IPFORWARD tag.
+ */
if (m->m_flags & M_IP6_NEXTHOP)
fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
else
fwd_tag = NULL;
- if (fwd_tag != NULL ||
- !IN6_ARE_ADDR_EQUAL(&dst.sin6_addr, &ip6->ip6_dst)) {
- if (fwd_tag != NULL) {
- bcopy((fwd_tag + 1), &dst, sizeof(dst));
- m->m_flags &= ~M_IP6_NEXTHOP;
- m_tag_delete(m, fwd_tag);
- } else
- dst.sin6_addr = ip6->ip6_dst;
- /*
- * Redo route lookup with new destination address
- */
- if (ip6_findroute(&nh, &dst, m) != 0) {
- m = NULL;
- goto dropout;
- }
+ if (!rt_changed && !IN6_ARE_ADDR_EQUAL(
+ &odst.sin6_addr, &ip6->ip6_dst)) {
+ dst.sin6_addr = ip6->ip6_dst;
+ rt_changed = true;
+ }
+
+ if (fwd_tag != NULL) {
+ bcopy((fwd_tag + 1), &dst, sizeof(dst));
+ m->m_flags &= ~M_IP6_NEXTHOP;
+ m_tag_delete(m, fwd_tag);
+ rt_changed = true;
+ }
+
+ if (rt_changed && ip6_findroute(&nh, &dst, m) != 0) {
+ m = NULL;
+ goto dropout;
}
passout:
#ifdef IPSTEALTH

File Metadata

Mime Type
text/plain
Expires
Sat, Mar 21, 7:17 AM (11 h, 26 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30069396
Default Alt Text
D41479.id126141.diff (5 KB)

Event Timeline