Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 20 Nov 2000 22:41:41 +0100
From:      Jesper Skriver <jesper@skriver.dk>
To:        "Louis A. Mamakos" <louie@TransSys.COM>
Cc:        hackers@FreeBSD.ORG
Subject:   Re: React to ICMP administratively prohibited ?
Message-ID:  <20001120224141.A80979@skriver.dk>
In-Reply-To: <200011192301.eAJN15714300@whizzo.transsys.com>; from louie@TransSys.COM on Sun, Nov 19, 2000 at 06:01:05PM -0500
References:  <20001118155446.A81075@skriver.dk> <Pine.BSF.4.21.0011181102540.52996-100000@achilles.silby.com> <20001118183632.A99512@skriver.dk> <20001119215357.A41281@skriver.dk> <200011192103.eAJL34713541@whizzo.transsys.com> <20001119220451.B41281@skriver.dk> <20001119223818.A79237@skriver.dk> <200011192301.eAJN15714300@whizzo.transsys.com>

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

--IJpNTDwzlM2Ie8A6
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Sun, Nov 19, 2000 at 06:01:05PM -0500, Louis A. Mamakos wrote:
> 
> It would seem more appropriate, somehow, to push the response to the
> ICMP message up into the protocols where they can take the appropriate
> action.  Of course, the problem is that the PRC_* abstracted codes may
> not be rich enough to express all the semantics you'd wish to convey.
> 
> So one goal might be to see if this sort of process could get pushed into
> netinet/tcp_sub.c:tcp_ctlinput().   Personally, I don't really like the
> idea of the icmp_input() function reaching into TCP's private state and
> doing stuff.  

So what you propose is to let netinet/ip_icmp.c all alone, and do something 
like the below in netinet/tcp_sub.c:tcp_ctlinput()

       else if ((icmp_admin_prohib_like_rst == 1) && ((cmd == ICMP_UNREACH_NET_PROHIB) ||
			(cmd == ICMP_UNREACH_HOST_PROHIB) || (cmd == ICMP_UNREACH_FILTER_PROHIB)) && (ip))
               notify = tcp_drop_syn_sent;

instead of

       else if ((icmp_admin_prohib_like_rst == 1) && (cmd == PRC_UNREACH_PORT) && (ip))
               notify = tcp_drop_syn_sent;

correct ?

Is this ok - from my vague understanding of this part of the code, I
thought I had to use the PRC_* abstracted codes ...

> There's too many potential interactions (e.g., what about
> IPSEC security associations?) 

Dunno, know very little of IPsec ...

Latest diff attached, this implement a sysctl,
'net.inet.tcp.icmp_admin_prohib_like_rst' which default to being
disabled.

/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.

--IJpNTDwzlM2Ie8A6
Content-Type: text/plain; charset=us-ascii
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	Mon Nov 20 22:33:48 2000
@@ -134,6 +134,14 @@
 SYSCTL_INT(_net_inet_tcp, OID_AUTO, pcbcount, CTLFLAG_RD, 
     &tcbinfo.ipi_count, 0, "Number of active PCBs");
 
+/*
+ * React to ICMP administratively prohibited
+ */
+ 
+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.");
+
 static void	tcp_cleartaocache __P((void));
 static void	tcp_notify __P((struct inpcb *, int));
 
@@ -961,6 +969,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 +1081,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 *));

--IJpNTDwzlM2Ie8A6--


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?20001120224141.A80979>