From 6b773dff30ea223c1ece875d88921ddc8876806e Mon Sep 17 00:00:00 2001 From: Andre Oppermann Date: Mon, 22 Aug 2005 14:12:18 +0000 Subject: [PATCH] Always quote the entire TCP header when responding and allocate an mbuf cluster if needed. Fixes the TCP issues raised in I-D draft-gont-icmp-payload-00.txt. This aids in-the-wild debugging a lot and allows the receiver to do more elaborate checks on the validity of the response. MFC after: 2 weeks Sponsored by: TCP/IP Optimization Fundraise 2005 --- sys/netinet/ip_icmp.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c index a6d04aff780a..12ff81472893 100644 --- a/sys/netinet/ip_icmp.c +++ b/sys/netinet/ip_icmp.c @@ -183,7 +183,7 @@ icmp_error(n, type, code, dest, mtu) /* * First, formulate icmp message */ - m = m_gethdr(M_DONTWAIT, MT_HEADER); + MGETHDR(m, M_DONTWAIT, MT_HEADER); if (m == NULL) goto freeit; #ifdef MAC @@ -193,11 +193,31 @@ icmp_error(n, type, code, dest, mtu) * Calculate length to quote from original packet and * prevent the ICMP mbuf from overflowing. */ - icmplen = min(oiplen + max(8, icmp_quotelen), oip->ip_len); - icmplen = min(icmplen, M_TRAILINGSPACE(m) - - (ICMP_MINLEN + sizeof(struct ip))); + if (oip->ip_p == IPPROTO_TCP) { + struct tcphdr *th; + int tcphlen; + + if (n->m_len < oiplen + sizeof(struct tcphdr) && + ((n = m_pullup(n, oiplen + sizeof(struct tcphdr))) == NULL)) + goto freeit; + th = (struct tcphdr *)((caddr_t)oip + oiplen); + tcphlen = th->th_off << 2; + if (tcphlen < sizeof(struct tcphdr)) + goto freeit; + if (oip->ip_len < oiplen + tcphlen) + goto freeit; + if (n->m_len < oiplen + tcphlen && + ((n = m_pullup(n, oiplen + tcphlen)) == NULL)) + goto freeit; + icmplen = max(oiplen + tcphlen, min(icmp_quotelen, oip->ip_len)); + } else + icmplen = min(oiplen + max(8, icmp_quotelen), oip->ip_len); if (icmplen < sizeof(struct ip)) panic("icmp_error: bad length"); + if (icmplen + ICMP_MINLEN + sizeof(struct ip) > MHLEN) + MCLGET(m, M_DONTWAIT); + if (!(m->m_flags & M_EXT)) + goto freeit; m->m_len = icmplen + ICMP_MINLEN; MH_ALIGN(m, m->m_len); icp = mtod(m, struct icmp *);