From 34a84acceeef772a5b9acdda87fdf6cc6581e62d Mon Sep 17 00:00:00 2001 From: andre Date: Thu, 21 Apr 2005 12:37:12 +0000 Subject: Ignore ICMP Source Quench messages for TCP sessions. Source Quench is ineffective, depreciated and can be abused to degrade the performance of active TCP sessions if spoofed. Replace a bogus call to tcp_quench() in tcp_output() with the direct equivalent tcpcb variable assignment. Security: draft-gont-tcpm-icmp-attacks-03.txt Section 7.1 MFC after: 3 days --- sys/netinet/tcp_output.c | 2 +- sys/netinet/tcp_subr.c | 35 +++++++++++------------------------ sys/netinet/tcp_timewait.c | 35 +++++++++++------------------------ sys/netinet/tcp_var.h | 2 -- 4 files changed, 23 insertions(+), 51 deletions(-) (limited to 'sys') diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c index fce9c9c..37a4ef1 100644 --- a/sys/netinet/tcp_output.c +++ b/sys/netinet/tcp_output.c @@ -1066,7 +1066,7 @@ out: !callout_active(tp->tt_persist)) callout_reset(tp->tt_rexmt, tp->t_rxtcur, tcp_timer_rexmt, tp); - tcp_quench(tp->t_inpcb, 0); + tp->snd_cwnd = tp->t_maxseg; return (0); } if (error == EMSGSIZE) { diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index 3516c74..02e753a 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -1117,19 +1117,22 @@ tcp_ctlinput(cmd, sa, vip) if (sa->sa_family != AF_INET || faddr.s_addr == INADDR_ANY) return; - if (cmd == PRC_QUENCH) - notify = tcp_quench; + if (cmd == PRC_MSGSIZE) + notify = tcp_mtudisc; else if (icmp_may_rst && (cmd == PRC_UNREACH_ADMIN_PROHIB || cmd == PRC_UNREACH_PORT || cmd == PRC_TIMXCEED_INTRANS) && ip) notify = tcp_drop_syn_sent; - else if (cmd == PRC_MSGSIZE) - notify = tcp_mtudisc; /* * Redirects don't need to be handled up here. */ else if (PRC_IS_REDIRECT(cmd)) return; /* + * Source quench is depreciated. + */ + else if (cmd == PRC_QUENCH) + return; + /* * Hostdead is ugly because it goes linearly through all PCBs. * XXX: We never get this from ICMP, otherwise it makes an * excellent DoS attack on machines with many connections. @@ -1197,13 +1200,14 @@ tcp6_ctlinput(cmd, sa, d) sa->sa_len != sizeof(struct sockaddr_in6)) return; - if (cmd == PRC_QUENCH) - notify = tcp_quench; - else if (cmd == PRC_MSGSIZE) + if (cmd == PRC_MSGSIZE) notify = tcp_mtudisc; else if (!PRC_IS_REDIRECT(cmd) && ((unsigned)cmd >= PRC_NCMDS || inet6ctlerrmap[cmd] == 0)) return; + /* Source quench is depreciated. */ + else if (cmd == PRC_QUENCH) + return; /* if the parameter is from icmp6, decode it. */ if (d != NULL) { @@ -1373,23 +1377,6 @@ tcp_isn_tick(xtp) } /* - * When a source quench is received, close congestion window - * to one segment. We will gradually open it again as we proceed. - */ -struct inpcb * -tcp_quench(inp, errno) - struct inpcb *inp; - int errno; -{ - struct tcpcb *tp = intotcpcb(inp); - - INP_LOCK_ASSERT(inp); - if (tp != NULL) - tp->snd_cwnd = tp->t_maxseg; - return (inp); -} - -/* * When a specific ICMP unreachable message is received and the * connection state is SYN-SENT, drop the connection. This behavior * is controlled by the icmp_may_rst sysctl. diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c index 3516c74..02e753a 100644 --- a/sys/netinet/tcp_timewait.c +++ b/sys/netinet/tcp_timewait.c @@ -1117,19 +1117,22 @@ tcp_ctlinput(cmd, sa, vip) if (sa->sa_family != AF_INET || faddr.s_addr == INADDR_ANY) return; - if (cmd == PRC_QUENCH) - notify = tcp_quench; + if (cmd == PRC_MSGSIZE) + notify = tcp_mtudisc; else if (icmp_may_rst && (cmd == PRC_UNREACH_ADMIN_PROHIB || cmd == PRC_UNREACH_PORT || cmd == PRC_TIMXCEED_INTRANS) && ip) notify = tcp_drop_syn_sent; - else if (cmd == PRC_MSGSIZE) - notify = tcp_mtudisc; /* * Redirects don't need to be handled up here. */ else if (PRC_IS_REDIRECT(cmd)) return; /* + * Source quench is depreciated. + */ + else if (cmd == PRC_QUENCH) + return; + /* * Hostdead is ugly because it goes linearly through all PCBs. * XXX: We never get this from ICMP, otherwise it makes an * excellent DoS attack on machines with many connections. @@ -1197,13 +1200,14 @@ tcp6_ctlinput(cmd, sa, d) sa->sa_len != sizeof(struct sockaddr_in6)) return; - if (cmd == PRC_QUENCH) - notify = tcp_quench; - else if (cmd == PRC_MSGSIZE) + if (cmd == PRC_MSGSIZE) notify = tcp_mtudisc; else if (!PRC_IS_REDIRECT(cmd) && ((unsigned)cmd >= PRC_NCMDS || inet6ctlerrmap[cmd] == 0)) return; + /* Source quench is depreciated. */ + else if (cmd == PRC_QUENCH) + return; /* if the parameter is from icmp6, decode it. */ if (d != NULL) { @@ -1373,23 +1377,6 @@ tcp_isn_tick(xtp) } /* - * When a source quench is received, close congestion window - * to one segment. We will gradually open it again as we proceed. - */ -struct inpcb * -tcp_quench(inp, errno) - struct inpcb *inp; - int errno; -{ - struct tcpcb *tp = intotcpcb(inp); - - INP_LOCK_ASSERT(inp); - if (tp != NULL) - tp->snd_cwnd = tp->t_maxseg; - return (inp); -} - -/* * When a specific ICMP unreachable message is received and the * connection state is SYN-SENT, drop the connection. This behavior * is controlled by the icmp_may_rst sysctl. diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h index 26e410e..2a727a0 100644 --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -534,8 +534,6 @@ struct inpcb * struct tcpcb * tcp_newtcpcb(struct inpcb *); int tcp_output(struct tcpcb *); -struct inpcb * - tcp_quench(struct inpcb *, int); void tcp_respond(struct tcpcb *, void *, struct tcphdr *, struct mbuf *, tcp_seq, tcp_seq, int); int tcp_twrespond(struct tcptw *, int); -- cgit v1.1