diff options
-rw-r--r-- | sys/netinet/ip_icmp.c | 62 | ||||
-rw-r--r-- | sys/netinet/ip_input.c | 2 | ||||
-rw-r--r-- | sys/netinet/tcp_subr.c | 78 | ||||
-rw-r--r-- | sys/netinet/tcp_timewait.c | 78 |
4 files changed, 38 insertions, 182 deletions
diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c index 1ca4c30..5b9aa08 100644 --- a/sys/netinet/ip_icmp.c +++ b/sys/netinet/ip_icmp.c @@ -315,69 +315,37 @@ icmp_input(m, off, proto) case ICMP_UNREACH: switch (code) { case ICMP_UNREACH_NET: - code = PRC_UNREACH_HOST; - break; - case ICMP_UNREACH_HOST: - code = PRC_UNREACH_HOST; - break; - - case ICMP_UNREACH_PROTOCOL: - code = PRC_UNREACH_HOST; - break; - - case ICMP_UNREACH_PORT: - code = PRC_UNREACH_HOST; - break; - case ICMP_UNREACH_SRCFAIL: - code = PRC_UNREACH_HOST; + case ICMP_UNREACH_NET_UNKNOWN: + case ICMP_UNREACH_HOST_UNKNOWN: + case ICMP_UNREACH_ISOLATED: + case ICMP_UNREACH_TOSNET: + case ICMP_UNREACH_TOSHOST: + case ICMP_UNREACH_HOST_PRECEDENCE: + case ICMP_UNREACH_PRECEDENCE_CUTOFF: + code = PRC_UNREACH_NET; break; case ICMP_UNREACH_NEEDFRAG: code = PRC_MSGSIZE; break; - case ICMP_UNREACH_NET_UNKNOWN: - code = PRC_UNREACH_HOST; - break; - - case ICMP_UNREACH_NET_PROHIB: + /* + * RFC 1122, Sections 3.2.2.1 and 4.2.3.9. + * Treat subcodes 2,3 as immediate RST + */ + case ICMP_UNREACH_PROTOCOL: + case ICMP_UNREACH_PORT: code = PRC_UNREACH_ADMIN_PROHIB; break; - case ICMP_UNREACH_TOSNET: - code = PRC_UNREACH_HOST; - break; - - case ICMP_UNREACH_HOST_UNKNOWN: - code = PRC_UNREACH_HOST; - break; - - case ICMP_UNREACH_ISOLATED: - code = PRC_UNREACH_HOST; - break; - + case ICMP_UNREACH_NET_PROHIB: case ICMP_UNREACH_HOST_PROHIB: - code = PRC_UNREACH_ADMIN_PROHIB; - break; - - case ICMP_UNREACH_TOSHOST: - code = PRC_UNREACH_HOST; - break; - case ICMP_UNREACH_FILTER_PROHIB: code = PRC_UNREACH_ADMIN_PROHIB; break; - case ICMP_UNREACH_HOST_PRECEDENCE: - code = PRC_UNREACH_HOST; - break; - - case ICMP_UNREACH_PRECEDENCE_CUTOFF: - code = PRC_UNREACH_HOST; - break; - default: goto badcode; } diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index ca36031..7625a66 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -1429,7 +1429,7 @@ u_char inetctlerrmap[PRC_NCMDS] = { EHOSTUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED, EMSGSIZE, EHOSTUNREACH, 0, 0, 0, 0, 0, 0, - ENOPROTOOPT + ENOPROTOOPT, ENETRESET }; /* diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index 03b5870..b58005d 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -134,32 +134,9 @@ 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 unreachables like a TCP RST as required by rfc1122 section 3.2.2.1 - * - * Administatively prohibited kill's sessions regardless of - * their current state, other unreachable by default only kill - * sessions if they are in SYN-SENT state, this ensure temporary - * routing problems doesn't kill existing TCP sessions. - * This can be overridden by icmp_like_rst_syn_sent_only. - */ - -static int icmp_unreach_like_rst = 1; -SYSCTL_INT(_net_inet_tcp, OID_AUTO, icmp_unreach_like_rst, CTLFLAG_RW, - &icmp_unreach_like_rst, 0, - "Treat ICMP unreachable messages like TCP RST, rfc1122 section 3.2.2.1"); - -/* - * Control if ICMP unreachable messages other that administratively prohibited - * ones will kill sessions not in SYN-SENT state. - * - * Has no effect unless icmp_unreach_like_rst is enabled. - */ - -static int icmp_like_rst_syn_sent_only = 1; -SYSCTL_INT(_net_inet_tcp, OID_AUTO, icmp_like_rst_syn_sent_only, CTLFLAG_RW, - &icmp_like_rst_syn_sent_only, 0, - "When icmp_unreach_like_rst is enabled, only act on sessions in SYN-SENT state"); +static int icmp_may_rst = 1; +SYSCTL_INT(_net_inet_tcp, OID_AUTO, icmp_may_rst, CTLFLAG_RW, &icmp_may_rst, 0, + "Certain ICMP unreachable messages may abort connections in SYN_SENT"); static void tcp_cleartaocache __P((void)); static void tcp_notify __P((struct inpcb *, int)); @@ -993,35 +970,17 @@ tcp_ctlinput(cmd, sa, vip) struct sockaddr *sa; void *vip; { - register struct ip *ip = vip; - register struct tcphdr *th; + struct ip *ip = vip; + struct tcphdr *th; void (*notify) __P((struct inpcb *, int)) = tcp_notify; tcp_seq tcp_sequence = 0; int tcp_seq_check = 0; if (cmd == PRC_QUENCH) notify = tcp_quench; - else if ((icmp_unreach_like_rst == 1) && ((cmd == PRC_UNREACH_HOST) || - (cmd == PRC_UNREACH_ADMIN_PROHIB)) && (ip) && - ((IP_VHL_HL(ip->ip_vhl) << 2) == sizeof(struct ip))) { - /* - * Only go here if the length of the IP header in the ICMP packet - * is 20 bytes, that is it doesn't have options, if it does have - * options, we will not have the first 8 bytes of the TCP header, - * and thus we cannot match against TCP source/destination port - * numbers and TCP sequence number. - * - * If PRC_UNREACH_ADMIN_PROHIB drop session regardsless of current - * state, else we check the sysctl icmp_like_rst_syn_sent_only to - * see if we should drop the session only in SYN-SENT state, or - * in all states. - */ + else if (icmp_may_rst && cmd == PRC_UNREACH_ADMIN_PROHIB && ip) { tcp_seq_check = 1; - if (cmd == PRC_UNREACH_ADMIN_PROHIB) { - notify = tcp_drop_all_states; - } else { - notify = tcp_drop_syn_sent; - } + notify = tcp_drop_syn_sent; } else if (cmd == PRC_MSGSIZE) notify = tcp_mtudisc; else if (PRC_IS_REDIRECT(cmd)) { @@ -1173,10 +1132,9 @@ tcp_quench(inp, errno) } /* - * When a ICMP unreachable is recieved, drop the - * TCP connection, depending on the sysctl - * icmp_like_rst_syn_sent_only, it only drops - * the session if it's in SYN-SENT state + * 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. */ void tcp_drop_syn_sent(inp, errno) @@ -1184,22 +1142,8 @@ tcp_drop_syn_sent(inp, errno) int errno; { struct tcpcb *tp = intotcpcb(inp); - if((tp) && ((icmp_like_rst_syn_sent_only == 0) || - (tp->t_state == TCPS_SYN_SENT))) - tcp_drop(tp, errno); -} -/* - * When a ICMP unreachable is recieved, drop the - * TCP connection, regardless of the state. - */ -void -tcp_drop_all_states(inp, errno) - struct inpcb *inp; - int errno; -{ - struct tcpcb *tp = intotcpcb(inp); - if(tp) + if (tp && tp->t_state == TCPS_SYN_SENT) tcp_drop(tp, errno); } diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c index 03b5870..b58005d 100644 --- a/sys/netinet/tcp_timewait.c +++ b/sys/netinet/tcp_timewait.c @@ -134,32 +134,9 @@ 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 unreachables like a TCP RST as required by rfc1122 section 3.2.2.1 - * - * Administatively prohibited kill's sessions regardless of - * their current state, other unreachable by default only kill - * sessions if they are in SYN-SENT state, this ensure temporary - * routing problems doesn't kill existing TCP sessions. - * This can be overridden by icmp_like_rst_syn_sent_only. - */ - -static int icmp_unreach_like_rst = 1; -SYSCTL_INT(_net_inet_tcp, OID_AUTO, icmp_unreach_like_rst, CTLFLAG_RW, - &icmp_unreach_like_rst, 0, - "Treat ICMP unreachable messages like TCP RST, rfc1122 section 3.2.2.1"); - -/* - * Control if ICMP unreachable messages other that administratively prohibited - * ones will kill sessions not in SYN-SENT state. - * - * Has no effect unless icmp_unreach_like_rst is enabled. - */ - -static int icmp_like_rst_syn_sent_only = 1; -SYSCTL_INT(_net_inet_tcp, OID_AUTO, icmp_like_rst_syn_sent_only, CTLFLAG_RW, - &icmp_like_rst_syn_sent_only, 0, - "When icmp_unreach_like_rst is enabled, only act on sessions in SYN-SENT state"); +static int icmp_may_rst = 1; +SYSCTL_INT(_net_inet_tcp, OID_AUTO, icmp_may_rst, CTLFLAG_RW, &icmp_may_rst, 0, + "Certain ICMP unreachable messages may abort connections in SYN_SENT"); static void tcp_cleartaocache __P((void)); static void tcp_notify __P((struct inpcb *, int)); @@ -993,35 +970,17 @@ tcp_ctlinput(cmd, sa, vip) struct sockaddr *sa; void *vip; { - register struct ip *ip = vip; - register struct tcphdr *th; + struct ip *ip = vip; + struct tcphdr *th; void (*notify) __P((struct inpcb *, int)) = tcp_notify; tcp_seq tcp_sequence = 0; int tcp_seq_check = 0; if (cmd == PRC_QUENCH) notify = tcp_quench; - else if ((icmp_unreach_like_rst == 1) && ((cmd == PRC_UNREACH_HOST) || - (cmd == PRC_UNREACH_ADMIN_PROHIB)) && (ip) && - ((IP_VHL_HL(ip->ip_vhl) << 2) == sizeof(struct ip))) { - /* - * Only go here if the length of the IP header in the ICMP packet - * is 20 bytes, that is it doesn't have options, if it does have - * options, we will not have the first 8 bytes of the TCP header, - * and thus we cannot match against TCP source/destination port - * numbers and TCP sequence number. - * - * If PRC_UNREACH_ADMIN_PROHIB drop session regardsless of current - * state, else we check the sysctl icmp_like_rst_syn_sent_only to - * see if we should drop the session only in SYN-SENT state, or - * in all states. - */ + else if (icmp_may_rst && cmd == PRC_UNREACH_ADMIN_PROHIB && ip) { tcp_seq_check = 1; - if (cmd == PRC_UNREACH_ADMIN_PROHIB) { - notify = tcp_drop_all_states; - } else { - notify = tcp_drop_syn_sent; - } + notify = tcp_drop_syn_sent; } else if (cmd == PRC_MSGSIZE) notify = tcp_mtudisc; else if (PRC_IS_REDIRECT(cmd)) { @@ -1173,10 +1132,9 @@ tcp_quench(inp, errno) } /* - * When a ICMP unreachable is recieved, drop the - * TCP connection, depending on the sysctl - * icmp_like_rst_syn_sent_only, it only drops - * the session if it's in SYN-SENT state + * 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. */ void tcp_drop_syn_sent(inp, errno) @@ -1184,22 +1142,8 @@ tcp_drop_syn_sent(inp, errno) int errno; { struct tcpcb *tp = intotcpcb(inp); - if((tp) && ((icmp_like_rst_syn_sent_only == 0) || - (tp->t_state == TCPS_SYN_SENT))) - tcp_drop(tp, errno); -} -/* - * When a ICMP unreachable is recieved, drop the - * TCP connection, regardless of the state. - */ -void -tcp_drop_all_states(inp, errno) - struct inpcb *inp; - int errno; -{ - struct tcpcb *tp = intotcpcb(inp); - if(tp) + if (tp && tp->t_state == TCPS_SYN_SENT) tcp_drop(tp, errno); } |