summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/netinet/ip_input.c50
1 files changed, 19 insertions, 31 deletions
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index 06b6a7e2f50..339a16356b3 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_input.c,v 1.165 2009/07/24 12:30:05 dlg Exp $ */
+/* $OpenBSD: ip_input.c,v 1.166 2009/07/28 14:01:50 dlg Exp $ */
/* $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $ */
/*
@@ -1416,17 +1416,16 @@ int inetctlerrmap[PRC_NCMDS] = {
* via a source route.
*/
void
-ip_forward(struct mbuf *m, int srcrt)
+ip_forward(m, srcrt)
+ struct mbuf *m;
+ int srcrt;
{
- u_int8_t icmp_buf[68];
struct ip *ip = mtod(m, struct ip *);
struct sockaddr_in *sin;
struct rtentry *rt;
int error, type = 0, code = 0, destmtu = 0;
u_int rtableid = 0;
- u_int icmp_len;
- struct ifnet *ifp;
- u_int8_t generated;
+ struct mbuf *mcopy;
n_long dest;
dest = 0;
@@ -1473,11 +1472,11 @@ ip_forward(struct mbuf *m, int srcrt)
/*
* Save at most 68 bytes of the packet in case
* we need to generate an ICMP message to the src.
+ * Pullup to avoid sharing mbuf cluster between m and mcopy.
*/
- icmp_len = min(sizeof(icmp_buf), ntohs(ip->ip_len));
- m_copydata(m, 0, icmp_len, (caddr_t)icmp_buf);
- ifp = m->m_pkthdr.rcvif;
- generated = m->m_pkthdr.pf.flags & PF_TAG_GENERATED;
+ mcopy = m_copym(m, 0, min(ntohs(ip->ip_len), 68), M_DONTWAIT);
+ if (mcopy)
+ mcopy = m_pullup(mcopy, min(ntohs(ip->ip_len), 68));
ip->ip_ttl -= IPTTLDEC;
@@ -1524,8 +1523,10 @@ ip_forward(struct mbuf *m, int srcrt)
if (type)
ipstat.ips_redirectsent++;
else
- goto freert;
+ goto freecopy;
}
+ if (mcopy == NULL)
+ goto freert;
switch (error) {
@@ -1567,33 +1568,20 @@ ip_forward(struct mbuf *m, int srcrt)
* source quench could be a big problem under DoS attacks,
* or the underlying interface is rate-limited.
*/
+ goto freecopy;
#else
type = ICMP_SOURCEQUENCH;
code = 0;
-#endif
break;
+#endif
}
- MGETHDR(m, M_DONTWAIT, MT_DATA);
- if (m == NULL)
- goto freert;
-
- if (icmp_len > MHLEN) {
- MCLGET(m, M_DONTWAIT);
- if (!ISSET(m->m_flags, M_EXT)) {
- m_free(m);
- goto freert;
- }
- }
-
- m->m_len = m->m_pkthdr.len = icmp_len;
- m->m_pkthdr.rcvif = ifp;
- m->m_pkthdr.rdomain = rtableid;
- m->m_pkthdr.pf.flags |= generated;
- bcopy(icmp_buf, m->m_data, icmp_len);
-
- icmp_error(m, type, code, dest, destmtu);
+ icmp_error(mcopy, type, code, dest, destmtu);
+ goto freert;
+ freecopy:
+ if (mcopy)
+ m_free(mcopy);
freert:
#ifndef SMALL_KERNEL
if (ipmultipath && ipforward_rt.ro_rt &&