diff options
| -rw-r--r-- | sys/netinet/ip_icmp.c | 15 | ||||
| -rw-r--r-- | sys/netinet/tcp_subr.c | 25 | ||||
| -rw-r--r-- | sys/netinet/tcp_timewait.c | 25 | ||||
| -rw-r--r-- | sys/netinet/tcp_var.h | 1 |
4 files changed, 66 insertions, 0 deletions
diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c index 5a44807ad3b0..11cb500d3a5f 100644 --- a/sys/netinet/ip_icmp.c +++ b/sys/netinet/ip_icmp.c @@ -328,6 +328,11 @@ icmp_input(m, off, proto) case ICMP_UNREACH_NET_UNKNOWN: case ICMP_UNREACH_NET_PROHIB: + if (icp->icmp_ip.ip_p == IPPROTO_TCP) { + code = PRC_UNREACH_PORT; + break; + } + case ICMP_UNREACH_TOSNET: code = PRC_UNREACH_NET; break; @@ -335,11 +340,21 @@ icmp_input(m, off, proto) case ICMP_UNREACH_HOST_UNKNOWN: case ICMP_UNREACH_ISOLATED: case ICMP_UNREACH_HOST_PROHIB: + if (icp->icmp_ip.ip_p == IPPROTO_TCP) { + code = PRC_UNREACH_PORT; + break; + } + case ICMP_UNREACH_TOSHOST: code = PRC_UNREACH_HOST; break; case ICMP_UNREACH_FILTER_PROHIB: + if (icp->icmp_ip.ip_p == IPPROTO_TCP) { + code = PRC_UNREACH_PORT; + break; + } + case ICMP_UNREACH_HOST_PRECEDENCE: case ICMP_UNREACH_PRECEDENCE_CUTOFF: code = PRC_UNREACH_PORT; diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index 64302c6e17b0..fe00373414c9 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -134,6 +134,15 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, do_tcpdrain, CTLFLAG_RW, &do_tcpdrain, 0, SYSCTL_INT(_net_inet_tcp, OID_AUTO, pcbcount, CTLFLAG_RD, &tcbinfo.ipi_count, 0, "Number of active PCBs"); +/* + * Treat ICMP administratively prohibited like a TCP RST + * as required by rfc1122 section 3.2.2.1 + */ + +static int icmp_admin_prohib_like_rst = 0; +SYSCTL_INT(_net_inet_tcp, OID_AUTO, icmp_admin_prohib_like_rst, CTLFLAG_RW, + &icmp_admin_prohib_like_rst, 0, "Treat ICMP administratively prohibited messages like TCP RST, rfc1122 section 3.2.2.1"); + static void tcp_cleartaocache __P((void)); static void tcp_notify __P((struct inpcb *, int)); @@ -961,6 +970,8 @@ tcp_ctlinput(cmd, sa, vip) if (cmd == PRC_QUENCH) notify = tcp_quench; + else if ((icmp_admin_prohib_like_rst == 1) && (cmd == PRC_UNREACH_PORT) && (ip)) + notify = tcp_drop_syn_sent; else if (cmd == PRC_MSGSIZE) notify = tcp_mtudisc; else if (!PRC_IS_REDIRECT(cmd) && @@ -1074,6 +1085,20 @@ tcp_quench(inp, errno) } /* + * When a ICMP unreachable is recieved, drop the + * TCP connection, but only if in SYN_SENT + */ +void +tcp_drop_syn_sent(inp, errno) + struct inpcb *inp; + int errno; +{ + struct tcpcb *tp = intotcpcb(inp); + if((tp) && (tp->t_state == TCPS_SYN_SENT)) + tcp_drop(tp, errno); +} + +/* * When `need fragmentation' ICMP is received, update our idea of the MSS * based on the new value in the route. Also nudge TCP to send something, * since we know the packet we just sent was dropped. diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c index 64302c6e17b0..fe00373414c9 100644 --- a/sys/netinet/tcp_timewait.c +++ b/sys/netinet/tcp_timewait.c @@ -134,6 +134,15 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, do_tcpdrain, CTLFLAG_RW, &do_tcpdrain, 0, SYSCTL_INT(_net_inet_tcp, OID_AUTO, pcbcount, CTLFLAG_RD, &tcbinfo.ipi_count, 0, "Number of active PCBs"); +/* + * Treat ICMP administratively prohibited like a TCP RST + * as required by rfc1122 section 3.2.2.1 + */ + +static int icmp_admin_prohib_like_rst = 0; +SYSCTL_INT(_net_inet_tcp, OID_AUTO, icmp_admin_prohib_like_rst, CTLFLAG_RW, + &icmp_admin_prohib_like_rst, 0, "Treat ICMP administratively prohibited messages like TCP RST, rfc1122 section 3.2.2.1"); + static void tcp_cleartaocache __P((void)); static void tcp_notify __P((struct inpcb *, int)); @@ -961,6 +970,8 @@ tcp_ctlinput(cmd, sa, vip) if (cmd == PRC_QUENCH) notify = tcp_quench; + else if ((icmp_admin_prohib_like_rst == 1) && (cmd == PRC_UNREACH_PORT) && (ip)) + notify = tcp_drop_syn_sent; else if (cmd == PRC_MSGSIZE) notify = tcp_mtudisc; else if (!PRC_IS_REDIRECT(cmd) && @@ -1074,6 +1085,20 @@ tcp_quench(inp, errno) } /* + * When a ICMP unreachable is recieved, drop the + * TCP connection, but only if in SYN_SENT + */ +void +tcp_drop_syn_sent(inp, errno) + struct inpcb *inp; + int errno; +{ + struct tcpcb *tp = intotcpcb(inp); + if((tp) && (tp->t_state == TCPS_SYN_SENT)) + tcp_drop(tp, errno); +} + +/* * When `need fragmentation' ICMP is received, update our idea of the MSS * based on the new value in the route. Also nudge TCP to send something, * since we know the packet we just sent was dropped. diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h index af18c091c40d..e361caf57756 100644 --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -387,6 +387,7 @@ void tcp_init __P((void)); void tcp_input __P((struct mbuf *, int, int)); void tcp_mss __P((struct tcpcb *, int)); int tcp_mssopt __P((struct tcpcb *)); +void tcp_drop_syn_sent __P((struct inpcb *, int)); void tcp_mtudisc __P((struct inpcb *, int)); struct tcpcb * tcp_newtcpcb __P((struct inpcb *)); |
