Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 21 Nov 2000 21:18:53 +0100
From:      Jesper Skriver <jesper@skriver.dk>
To:        hackers@FreeBSD.org
Subject:   Re: React to ICMP administratively prohibited ? - commit candidate ?
Message-ID:  <20001121211853.B84107@skriver.dk>
In-Reply-To: <20001117211013.C9227@skriver.dk>; from jesper@skriver.dk on Fri, Nov 17, 2000 at 09:10:13PM %2B0100
References:  <20001117211013.C9227@skriver.dk>

next in thread | previous in thread | raw e-mail | index | archive | help

--QKdGvSO+nmPlgiQ/
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Fri, Nov 17, 2000 at 09:10:13PM +0100, Jesper Skriver wrote:

As said before, I've not got this code working, when the sysctl 
'net.inet.tcp.icmp_admin_prohib_like_rst' is set to 1, we'll treat a
ICMP administratively prohibited (icmp type 3 code 9, 10 and 13) as if
we recived a TCP RST, but only if the TCP session is in SYN_SENT state.

This is actually required by rfc1122 (Requirements for Internet Hosts)
section 3.2.2.1

            A Destination Unreachable message that is received MUST be
            reported to the transport layer.  The transport layer SHOULD
            use the information appropriately; for example, see Sections
            4.1.3.3, 4.2.3.9, and 4.2.4 below.  A transport protocol
            that has its own mechanism for notifying the sender that a
            port is unreachable (e.g., TCP, which sends RST segments)
            MUST nevertheless accept an ICMP Port Unreachable for the
            same purpose.

Because of this, I suggest that we by default enable this feature, but
it would be a change of current behaviour, so if people prefer to leave
it disabled by default, at least for now, this would be ok for me, the
attached diff actually have the sysctl set to 0 by default.

The only difference from the attached diff, to the one I mailed
yesterday is comments.

Does anyone have any objections to this being committed ? If no, who
will do it ?

/Jesper

-- 
Jesper Skriver, jesper(at)skriver(dot)dk  -  CCIE #5456
Work:    Network manager @ AS3292 (Tele Danmark DataNetworks)
Private: Geek            @ AS2109 (A much smaller network ;-)

One Unix to rule them all, One Resolver to find them,
One IP to bring them all and in the zone to bind them.

--QKdGvSO+nmPlgiQ/
Content-Type: text/plain; charset=us-ascii
Content-Description: icmp_admin_prohib_like_rst.diff
Content-Disposition: attachment; filename="icmp_admin_prohib_like_rst.diff"

diff -ru sys/netinet.old/ip_icmp.c sys/netinet/ip_icmp.c
--- sys/netinet.old/ip_icmp.c	Thu Nov  2 10:46:23 2000
+++ sys/netinet/ip_icmp.c	Mon Nov 20 22:33:43 2000
@@ -328,6 +328,11 @@
 
 			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 @@
 			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 -ru sys/netinet.old/tcp_subr.c sys/netinet/tcp_subr.c
--- sys/netinet.old/tcp_subr.c	Fri Oct 27 13:45:41 2000
+++ sys/netinet/tcp_subr.c	Tue Nov 21 21:16:27 2000
@@ -134,6 +134,15 @@
 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 @@
 
 	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) &&
@@ -1071,6 +1082,20 @@
 
 	if (tp)
 		tp->snd_cwnd = tp->t_maxseg;
+}
+
+/*
+ * 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);
 }
 
 /*
diff -ru sys/netinet.old/tcp_var.h sys/netinet/tcp_var.h
--- sys/netinet.old/tcp_var.h	Sat Jul 22 01:26:37 2000
+++ sys/netinet/tcp_var.h	Sun Nov 19 21:17:55 2000
@@ -387,6 +387,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_mtudisc __P((struct inpcb *, int));
 struct tcpcb *
 	 tcp_newtcpcb __P((struct inpcb *));

--QKdGvSO+nmPlgiQ/--


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20001121211853.B84107>