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>
This commit is contained in:
parent
3e8bea9634
commit
90fcbbd635
@ -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:
|
||||
|
@ -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) &&
|
||||
@ -1149,6 +1166,20 @@ tcp_drop_syn_sent(inp, errno)
|
||||
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)
|
||||
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,
|
||||
|
@ -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) &&
|
||||
@ -1149,6 +1166,20 @@ tcp_drop_syn_sent(inp, errno)
|
||||
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)
|
||||
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,
|
||||
|
@ -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 *));
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user