diff options
author | Henning Brauer <henning@cvs.openbsd.org> | 2009-08-10 11:48:03 +0000 |
---|---|---|
committer | Henning Brauer <henning@cvs.openbsd.org> | 2009-08-10 11:48:03 +0000 |
commit | 7695152f7c8dffbb2d260534cebaf05ff41d02ca (patch) | |
tree | d39e1cee0aeb82e6735f1f3f366f315a0ca3f6b8 /sys/netinet/ip_input.c | |
parent | 7f286369dd362fcb8ab472bc3682f0de0568be3d (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.c | 23 |
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: |