Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F175656608
D5330.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D5330.id.diff
View Options
Index: sys/netinet/ip_fastfwd.c
===================================================================
--- sys/netinet/ip_fastfwd.c
+++ sys/netinet/ip_fastfwd.c
@@ -109,7 +109,7 @@
#include <machine/in_cksum.h>
static struct sockaddr_in *
-ip_findroute(struct route *ro, struct in_addr dest, struct mbuf *m)
+ip_findroute(struct route *ro, struct in_addr dest, struct mbuf *m, struct mbuf *mcopy)
{
struct sockaddr_in *dst;
struct rtentry *rt;
@@ -138,7 +138,8 @@
IPSTAT_INC(ips_cantforward);
if (rt)
RTFREE(rt);
- icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, 0, 0);
+ icmp_error(mcopy, ICMP_UNREACH, ICMP_UNREACH_HOST, 0, 0);
+ m_freem(m);
return NULL;
}
return dst;
@@ -165,6 +166,8 @@
int mtu;
struct m_tag *fwd_tag = NULL;
+ struct mbuf *mcopy = NULL;
+
/*
* Are we active and forwarding packets?
*/
@@ -230,6 +233,38 @@
IPSTAT_INC(ips_total);
/*
+ * Save the IP header and at most 8 bytes of the payload,
+ * in case we need to generate an ICMP message to the src.
+ *
+ * XXX this can be optimized a lot by saving the data in a local
+ * buffer on the stack (72 bytes at most), and only allocating the
+ * mbuf if really necessary. The vast majority of the packets
+ * are forwarded without having to send an ICMP back (either
+ * because unnecessary, or because rate limited), so we are
+ * really we are wasting a lot of work here.
+ *
+ * We don't use m_copy() because it might return a reference
+ * to a shared cluster. Both this function and ip_output()
+ * assume exclusive access to the IP header in `m', so any
+ * data in a cluster may change before we reach icmp_error().
+ */
+ mcopy = m_gethdr(M_NOWAIT, m->m_type);
+ if (mcopy != NULL && !m_dup_pkthdr(mcopy, m, M_NOWAIT)) {
+ /*
+ * It's probably ok if the pkthdr dup fails (because
+ * the deep copy of the tag chain failed), but for now
+ * be conservative and just discard the copy since
+ * code below may some day want the tags.
+ */
+ m_free(mcopy);
+ mcopy = NULL;
+ }
+ if (mcopy != NULL) {
+ mcopy->m_len = min(ntohs(ip->ip_len), M_TRAILINGSPACE(mcopy));
+ mcopy->m_pkthdr.len = mcopy->m_len;
+ m_copydata(m, 0, mcopy->m_len, mtod(mcopy, caddr_t));
+ }
+ /*
* Step 3: incoming packet firewall processing
*/
@@ -285,8 +320,9 @@
if (!V_ipstealth) {
#endif
if (ip->ip_ttl <= IPTTLDEC) {
- icmp_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, 0, 0);
- return NULL; /* mbuf already free'd */
+ icmp_error(mcopy, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, 0, 0);
+ m_freem(m);
+ return NULL;
}
/*
@@ -306,8 +342,9 @@
/*
* Find route to destination.
*/
- if ((dst = ip_findroute(&ro, dest, m)) == NULL)
+ if ((dst = ip_findroute(&ro, dest, m, mcopy)) == NULL)
return NULL; /* icmp unreach already sent */
+
ifp = ro.ro_rt->rt_ifp;
/*
@@ -355,6 +392,8 @@
m->m_flags |= M_FASTFWD_OURS;
if (ro.ro_rt)
RTFREE(ro.ro_rt);
+ if (mcopy)
+ m_freem(mcopy);
return m;
}
/*
@@ -367,8 +406,9 @@
m->m_flags &= ~M_IP_NEXTHOP;
}
RTFREE(ro.ro_rt);
- if ((dst = ip_findroute(&ro, dest, m)) == NULL)
+ if ((dst = ip_findroute(&ro, dest, m, mcopy)) == NULL)
return NULL; /* icmp unreach already sent */
+
ifp = ro.ro_rt->rt_ifp;
}
@@ -384,7 +424,8 @@
*/
if ((ro.ro_rt->rt_flags & RTF_REJECT) &&
(ro.ro_rt->rt_expire == 0 || time_uptime < ro.ro_rt->rt_expire)) {
- icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, 0, 0);
+ icmp_error(mcopy, ICMP_UNREACH, ICMP_UNREACH_HOST, 0, 0);
+ m_freem(m);
goto consumed;
}
@@ -392,7 +433,8 @@
* Check if media link state of interface is not down
*/
if (ifp->if_link_state == LINK_STATE_DOWN) {
- icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, 0, 0);
+ icmp_error(mcopy, ICMP_UNREACH, ICMP_UNREACH_HOST, 0, 0);
+ m_freem(m);
goto consumed;
}
@@ -421,8 +463,9 @@
*/
if (ip_off & IP_DF) {
IPSTAT_INC(ips_cantfrag);
- icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG,
+ icmp_error(mcopy, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG,
0, mtu);
+ m_freem(m);
goto consumed;
} else {
/*
@@ -469,11 +512,15 @@
IPSTAT_INC(ips_fastforward);
}
consumed:
+ if (mcopy)
+ m_freem(mcopy);
RTFREE(ro.ro_rt);
return NULL;
drop:
if (m)
m_freem(m);
+ if (mcopy)
+ m_freem(mcopy);
if (ro.ro_rt)
RTFREE(ro.ro_rt);
return NULL;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Oct 13, 7:58 AM (4 h, 30 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
40737295
Default Alt Text
D5330.id.diff (4 KB)
Attached To
Mode
D5330: Fix tryforward so that it can return ICMP errors to the correct origin, even in the face of IPFW and NAT.
Attached
Detach File
Event Timeline
Log In to Comment