summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>2001-02-18 09:34:55 +0000
committerphk <phk@FreeBSD.org>2001-02-18 09:34:55 +0000
commite33961c592de488d19f161d134c40f24205322d3 (patch)
treeca2f52b1634e8f34bb68044a57bd942bc45098fb
parent15fc7bce144d9639f026ee520c9e1b67f6b926ad (diff)
downloadFreeBSD-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.c48
-rw-r--r--sys/netinet/tcp_subr.c55
-rw-r--r--sys/netinet/tcp_timewait.c55
-rw-r--r--sys/netinet/tcp_var.h1
-rw-r--r--sys/sys/protosw.h5
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
OpenPOWER on IntegriCloud