Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F111983734
D41479.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D41479.diff
View Options
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
@@ -237,12 +237,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?
*/
@@ -371,7 +372,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)) {
@@ -382,6 +385,7 @@
(fwd_tag + 1))->sin_addr.s_addr;
m_tag_delete(m, fwd_tag);
m->m_flags &= ~M_IP_NEXTHOP;
+ rt_changed = true;
}
/*
@@ -390,17 +394,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;
@@ -409,18 +409,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:
@@ -430,20 +433,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/netinet/ip_input.c b/sys/netinet/ip_input.c
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -921,6 +921,7 @@
struct sockaddr_in *sin;
struct in_addr dest;
struct route ro;
+ struct m_tag *fwd_tag;
uint32_t flowid;
int error, type = 0, code = 0, mtu = 0;
@@ -942,11 +943,20 @@
bzero(&ro, sizeof(ro));
sin = (struct sockaddr_in *)&ro.ro_dst;
- sin->sin_family = AF_INET;
- sin->sin_len = sizeof(*sin);
- sin->sin_addr = ip->ip_dst;
+
+ if (m->m_flags & M_IP_NEXTHOP && ((fwd_tag = m_tag_find(m,
+ PACKET_TAG_IPFORWARD, NULL)) != NULL)) {
+ bcopy((fwd_tag + 1), sin, sizeof(struct sockaddr_in));
+ m->m_flags &= ~M_IP_NEXTHOP;
+ m_tag_delete(m, fwd_tag);
+ } else {
+ sin->sin_family = AF_INET;
+ sin->sin_len = sizeof(*sin);
+ sin->sin_addr = ip->ip_dst;
+ }
+
flowid = m->m_pkthdr.flowid;
- ro.ro_nh = fib4_lookup(M_GETFIB(m), ip->ip_dst, 0, NHR_REF, flowid);
+ ro.ro_nh = fib4_lookup(M_GETFIB(m), sin->sin_addr, 0, NHR_REF, flowid);
if (ro.ro_nh != NULL) {
ia = ifatoia(ro.ro_nh->nh_ifa);
} else
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
@@ -90,13 +90,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.
@@ -158,6 +159,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.
*/
@@ -178,6 +184,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) {
@@ -187,6 +197,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;
@@ -213,6 +224,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;
@@ -243,30 +255,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
diff --git a/sys/netinet6/ip6_forward.c b/sys/netinet6/ip6_forward.c
--- a/sys/netinet6/ip6_forward.c
+++ b/sys/netinet6/ip6_forward.c
@@ -177,9 +177,17 @@
* 3) packet filters attaching PACKET_TAG_IPFORWARD would embed
* scope for the nexthop.
*/
- bzero(&dst, sizeof(struct sockaddr_in6));
- dst.sin6_family = AF_INET6;
- dst.sin6_addr = ip6->ip6_dst;
+ if (m->m_flags & M_IP6_NEXTHOP && ((fwd_tag = m_tag_find(m,
+ PACKET_TAG_IPFORWARD, NULL)) != NULL)) {
+ bcopy((fwd_tag + 1), &dst, sizeof(dst));
+ m->m_flags &= ~M_IP6_NEXTHOP;
+ m_tag_delete(m, fwd_tag);
+ } else {
+ bzero(&dst, sizeof(struct sockaddr_in6));
+ dst.sin6_family = AF_INET6;
+ dst.sin6_addr = ip6->ip6_dst;
+ }
+
dst.sin6_scope_id = in6_get_unicast_scopeid(&ip6->ip6_dst, m->m_pkthdr.rcvif);
again:
nh = fib6_lookup(M_GETFIB(m), &dst.sin6_addr, dst.sin6_scope_id,
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Mar 12, 4:32 AM (9 h, 12 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17112746
Default Alt Text
D41479.diff (7 KB)
Attached To
Mode
D41479: Draft: Forwarding: Use the next hop installed by pfil_mbuf_in
Attached
Detach File
Event Timeline
Log In to Comment