diff options
author | phk <phk@FreeBSD.org> | 2001-02-18 09:34:55 +0000 |
---|---|---|
committer | phk <phk@FreeBSD.org> | 2001-02-18 09:34:55 +0000 |
commit | e33961c592de488d19f161d134c40f24205322d3 (patch) | |
tree | ca2f52b1634e8f34bb68044a57bd942bc45098fb | |
parent | 15fc7bce144d9639f026ee520c9e1b67f6b926ad (diff) | |
download | FreeBSD-src-e33961c592de488d19f161d134c40f24205322d3.zip FreeBSD-src-e33961c592de488d19f161d134c40f24205322d3.tar.gz |
Remove unneeded loop increment in src/sys/netinet/in_pcb.c:in_pcbnotify
Add new PRC_UNREACH_ADMIN_PROHIB in sys/sys/protosw.h
Remove condition on TCP in src/sys/netinet/ip_icmp.c:icmp_input
In src/sys/netinet/ip_icmp.c:icmp_input set code = PRC_UNREACH_ADMIN_PROHIB
or PRC_UNREACH_HOST for all unreachables except ICMP_UNREACH_NEEDFRAG
Rename sysctl icmp_admin_prohib_like_rst to icmp_unreach_like_rst
to reflect the fact that we also react on ICMP unreachables that
are not administrative prohibited. Also update the comments to
reflect this.
In sys/netinet/tcp_subr.c:tcp_ctlinput add code to treat
PRC_UNREACH_ADMIN_PROHIB and PRC_UNREACH_HOST different.
PR: 23986
Submitted by: Jesper Skriver <jesper@skriver.dk>
-rw-r--r-- | sys/netinet/ip_icmp.c | 48 | ||||
-rw-r--r-- | sys/netinet/tcp_subr.c | 55 | ||||
-rw-r--r-- | sys/netinet/tcp_timewait.c | 55 | ||||
-rw-r--r-- | sys/netinet/tcp_var.h | 1 | ||||
-rw-r--r-- | sys/sys/protosw.h | 5 |
5 files changed, 123 insertions, 41 deletions
diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c index 6a277aa..1ca4c30 100644 --- a/sys/netinet/ip_icmp.c +++ b/sys/netinet/ip_icmp.c @@ -315,11 +315,23 @@ 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_NET; + code = PRC_UNREACH_HOST; break; case ICMP_UNREACH_NEEDFRAG: @@ -327,37 +339,43 @@ icmp_input(m, off, proto) break; case ICMP_UNREACH_NET_UNKNOWN: + code = PRC_UNREACH_HOST; + break; + case ICMP_UNREACH_NET_PROHIB: - if (icp->icmp_ip.ip_p == IPPROTO_TCP) { - code = PRC_UNREACH_PORT; - break; - } + code = PRC_UNREACH_ADMIN_PROHIB; + break; case ICMP_UNREACH_TOSNET: - code = PRC_UNREACH_NET; + 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_HOST_PROHIB: - if (icp->icmp_ip.ip_p == IPPROTO_TCP) { - code = PRC_UNREACH_PORT; - break; - } + code = PRC_UNREACH_ADMIN_PROHIB; + 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; - } + code = PRC_UNREACH_ADMIN_PROHIB; + break; case ICMP_UNREACH_HOST_PRECEDENCE: + code = PRC_UNREACH_HOST; + break; + case ICMP_UNREACH_PRECEDENCE_CUTOFF: - code = PRC_UNREACH_PORT; + code = PRC_UNREACH_HOST; break; default: diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index 0da8440..6541014 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -135,24 +135,31 @@ 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 + * 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_admin_prohib_like_rst = 1; -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 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"); /* - * When icmp_admin_prohib_like_rst is enabled, only act on - * sessions in SYN-SENT state + * 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_admin_prohib_like_rst is enabled, only act on sessions in SYN-SENT state"); + "When icmp_unreach_like_rst is enabled, only act on sessions in SYN-SENT state"); static void tcp_cleartaocache __P((void)); static void tcp_notify __P((struct inpcb *, int)); @@ -983,17 +990,27 @@ 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) && ((IP_VHL_HL(ip->ip_vhl) << 2) == sizeof(struct ip))) { + 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. */ tcp_seq_check = 1; - notify = tcp_drop_syn_sent; + if (cmd == PRC_UNREACH_ADMIN_PROHIB) { + notify = tcp_drop_all_states; + } else { + notify = tcp_drop_syn_sent; + } } else if (cmd == PRC_MSGSIZE) notify = tcp_mtudisc; else if (!PRC_IS_REDIRECT(cmd) && @@ -1150,6 +1167,20 @@ tcp_drop_syn_sent(inp, 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) + 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 0da8440..6541014 100644 --- a/sys/netinet/tcp_timewait.c +++ b/sys/netinet/tcp_timewait.c @@ -135,24 +135,31 @@ 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 + * 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_admin_prohib_like_rst = 1; -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 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"); /* - * When icmp_admin_prohib_like_rst is enabled, only act on - * sessions in SYN-SENT state + * 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_admin_prohib_like_rst is enabled, only act on sessions in SYN-SENT state"); + "When icmp_unreach_like_rst is enabled, only act on sessions in SYN-SENT state"); static void tcp_cleartaocache __P((void)); static void tcp_notify __P((struct inpcb *, int)); @@ -983,17 +990,27 @@ 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) && ((IP_VHL_HL(ip->ip_vhl) << 2) == sizeof(struct ip))) { + 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. */ tcp_seq_check = 1; - notify = tcp_drop_syn_sent; + if (cmd == PRC_UNREACH_ADMIN_PROHIB) { + notify = tcp_drop_all_states; + } else { + notify = tcp_drop_syn_sent; + } } else if (cmd == PRC_MSGSIZE) notify = tcp_mtudisc; else if (!PRC_IS_REDIRECT(cmd) && @@ -1150,6 +1167,20 @@ tcp_drop_syn_sent(inp, 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) + 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 dc69d3e..3b3f851 100644 --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -388,6 +388,7 @@ 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_drop_all_states __P((struct inpcb *, int)); void tcp_mtudisc __P((struct inpcb *, int)); struct tcpcb * tcp_newtcpcb __P((struct inpcb *)); diff --git a/sys/sys/protosw.h b/sys/sys/protosw.h index 4f88105..6742f7a 100644 --- a/sys/sys/protosw.h +++ b/sys/sys/protosw.h @@ -275,8 +275,9 @@ int pru_sense_null __P((struct socket *so, struct stat *sb)); #define PRC_TIMXCEED_INTRANS 18 /* packet lifetime expired in transit */ #define PRC_TIMXCEED_REASS 19 /* lifetime expired on reass q */ #define PRC_PARAMPROB 20 /* header incorrect */ +#define PRC_UNREACH_ADMIN_PROHIB 21 /* packet administrativly prohibited */ -#define PRC_NCMDS 21 +#define PRC_NCMDS 22 #define PRC_IS_REDIRECT(cmd) \ ((cmd) >= PRC_REDIRECT_NET && (cmd) <= PRC_REDIRECT_TOSHOST) @@ -288,7 +289,7 @@ char *prcrequests[] = { "NET-UNREACH", "HOST-UNREACH", "PROTO-UNREACH", "PORT-UNREACH", "#12", "SRCFAIL-UNREACH", "NET-REDIRECT", "HOST-REDIRECT", "TOSNET-REDIRECT", "TOSHOST-REDIRECT", "TX-INTRANS", "TX-REASS", - "PARAMPROB" + "PARAMPROB", "ADMIN-UNREACH" }; #endif |