summaryrefslogtreecommitdiff
path: root/sys/netinet/ip_input.c
diff options
context:
space:
mode:
authorHenning Brauer <henning@cvs.openbsd.org>2009-08-10 11:48:03 +0000
committerHenning Brauer <henning@cvs.openbsd.org>2009-08-10 11:48:03 +0000
commit7695152f7c8dffbb2d260534cebaf05ff41d02ca (patch)
treed39e1cee0aeb82e6735f1f3f366f315a0ca3f6b8 /sys/netinet/ip_input.c
parent7f286369dd362fcb8ab472bc3682f0de0568be3d (diff)
this is basically a fixed version of r1.165, avoid m_copym of each and every
forwarded packet in case ip_output returns an error and we have to quote some of it back in an icmp error message. this implementation done from scratch: place an mbuf on the stack. copy the pkthdr from the forwarded packet and the first 68 bytes of payload. if we need to send an icmp error, just m_copym our mbuf-on-the-stack into a real one that icmp_error can fuck with and eat as it desires. ok theo dlg
Diffstat (limited to 'sys/netinet/ip_input.c')
-rw-r--r--sys/netinet/ip_input.c23
1 files changed, 13 insertions, 10 deletions
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index 339a16356b3..0a3f285fd0d 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_input.c,v 1.166 2009/07/28 14:01:50 dlg Exp $ */
+/* $OpenBSD: ip_input.c,v 1.167 2009/08/10 11:48:02 henning Exp $ */
/* $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $ */
/*
@@ -1423,10 +1423,10 @@ ip_forward(m, srcrt)
struct ip *ip = mtod(m, struct ip *);
struct sockaddr_in *sin;
struct rtentry *rt;
- int error, type = 0, code = 0, destmtu = 0;
+ int error, type = 0, code = 0, destmtu = 0, len;
u_int rtableid = 0;
- struct mbuf *mcopy;
n_long dest;
+ struct mbuf mfake, *mcopy;
dest = 0;
#ifdef DIAGNOSTIC
@@ -1472,11 +1472,14 @@ ip_forward(m, 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.
*/
- 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));
+ bzero(&mfake.m_hdr, sizeof(mfake.m_hdr));
+ mfake.m_type = m->m_type;
+ M_DUP_PKTHDR(&mfake, m);
+ mfake.m_data = mfake.m_pktdat;
+ len = min(ntohs(ip->ip_len), 68);
+ bcopy(ip, mfake.m_pktdat, len);
+ mfake.m_pkthdr.len = mfake.m_len = len;
ip->ip_ttl -= IPTTLDEC;
@@ -1525,8 +1528,6 @@ ip_forward(m, srcrt)
else
goto freecopy;
}
- if (mcopy == NULL)
- goto freert;
switch (error) {
@@ -1576,7 +1577,9 @@ ip_forward(m, srcrt)
#endif
}
- icmp_error(mcopy, type, code, dest, destmtu);
+ mcopy = m_copym(&mfake, 0, len, M_DONTWAIT);
+ if (mcopy)
+ icmp_error(mcopy, type, code, dest, destmtu);
goto freert;
freecopy: