Page MenuHomeFreeBSD

D5330.id.diff
No OneTemporary

D5330.id.diff

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

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)

Event Timeline