summaryrefslogtreecommitdiffstats
path: root/sys/netinet/ip_icmp.c
diff options
context:
space:
mode:
authorandre <andre@FreeBSD.org>2005-08-22 14:12:18 +0000
committerandre <andre@FreeBSD.org>2005-08-22 14:12:18 +0000
commitef76245e903c6da9b4359edf312f385c9d1ab002 (patch)
tree6d02cf583643fd60d47a0eb7f6db6ec5bb608d94 /sys/netinet/ip_icmp.c
parent1afbca0a454d70fc5eb818a4eb3a654cdc571f72 (diff)
downloadFreeBSD-src-ef76245e903c6da9b4359edf312f385c9d1ab002.zip
FreeBSD-src-ef76245e903c6da9b4359edf312f385c9d1ab002.tar.gz
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
Diffstat (limited to 'sys/netinet/ip_icmp.c')
-rw-r--r--sys/netinet/ip_icmp.c28
1 files changed, 24 insertions, 4 deletions
diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c
index a6d04af..12ff814 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 *);
OpenPOWER on IntegriCloud