summaryrefslogtreecommitdiff
path: root/sys/netinet/tcp_subr.c
diff options
context:
space:
mode:
authorMarkus Friedl <markus@cvs.openbsd.org>2005-06-30 08:51:32 +0000
committerMarkus Friedl <markus@cvs.openbsd.org>2005-06-30 08:51:32 +0000
commitd0da6045c3473c63c2c5ebcb604695383312ac92 (patch)
tree47b24d0d2ccf633ec13c5ec6181e8098952eea3e /sys/netinet/tcp_subr.c
parent9a113f7cb87a9e2074ec670f5a343663a903c767 (diff)
implement PMTU checks from
http://www.gont.com.ar/drafts/icmp-attacks-against-tcp.html i.e. don't act on ICMP-need-frag immediately if adhoc checks on the advertised mtu fail. the mtu update is delayed until a tcp retransmit happens. initial patch by Fernando Gont, tested by many.
Diffstat (limited to 'sys/netinet/tcp_subr.c')
-rw-r--r--sys/netinet/tcp_subr.c43
1 files changed, 40 insertions, 3 deletions
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index 35964b0bf71..b39678cc7fb 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_subr.c,v 1.89 2005/05/24 00:02:37 fgont Exp $ */
+/* $OpenBSD: tcp_subr.c,v 1.90 2005/06/30 08:51:31 markus Exp $ */
/* $NetBSD: tcp_subr.c,v 1.22 1996/02/13 23:44:00 christos Exp $ */
/*
@@ -519,6 +519,10 @@ tcp_newtcpcb(struct inpcb *inp)
TCPTV_MIN, TCPTV_REXMTMAX);
tp->snd_cwnd = TCP_MAXWIN << TCP_MAX_WINSHIFT;
tp->snd_ssthresh = TCP_MAXWIN << TCP_MAX_WINSHIFT;
+
+ tp->t_pmtud_mtu_sent = 0;
+ tp->t_pmtud_mss_acked = 0;
+
#ifdef INET6
/* we disallow IPv4 mapped address completely. */
if ((inp->inp_flags & INP_IPV6) == 0)
@@ -829,6 +833,7 @@ tcp_ctlinput(cmd, sa, v)
struct inpcb *inp;
struct in_addr faddr;
tcp_seq seq;
+ u_int mtu;
extern int inetctlerrmap[];
void (*notify)(struct inpcb *, int) = tcp_notify;
int errno;
@@ -866,8 +871,40 @@ tcp_ctlinput(cmd, sa, v)
icp = (struct icmp *)((caddr_t)ip -
offsetof(struct icmp, icmp_ip));
- /* Calculate new mtu and create corresponding route */
- icmp_mtudisc(icp);
+ /*
+ * If the ICMP message advertises a Next-Hop MTU
+ * equal or larger than the maximum packet size we have
+ * ever sent, drop the message.
+ */
+ mtu = (u_int)ntohs(icp->icmp_nextmtu);
+ if (mtu >= tp->t_pmtud_mtu_sent)
+ return NULL;
+ if (mtu >= tcp_hdrsz(tp) + tp->t_pmtud_mss_acked) {
+ /*
+ * Calculate new MTU, and create corresponding
+ * route (traditional PMTUD).
+ */
+ tp->t_flags &= ~TF_PMTUD_PEND;
+ icmp_mtudisc(icp);
+ } else {
+ /*
+ * Record the information got in the ICMP
+ * message; act on it later.
+ * If we had already recorded an ICMP message,
+ * replace the old one only if the new message
+ * refers to an older TCP segment
+ */
+ if (tp->t_flags & TF_PMTUD_PEND) {
+ if (SEQ_LT(tp->t_pmtud_th_seq, seq))
+ return NULL;
+ } else
+ tp->t_flags |= TF_PMTUD_PEND;
+ tp->t_pmtud_th_seq = seq;
+ tp->t_pmtud_nextmtu = icp->icmp_nextmtu;
+ tp->t_pmtud_ip_len = icp->icmp_ip.ip_len;
+ tp->t_pmtud_ip_hl = icp->icmp_ip.ip_hl;
+ return NULL;
+ }
} else {
/* ignore if we don't have a matching connection */
return NULL;