From nobody@FreeBSD.org  Wed Jul 18 23:51:04 2007
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52])
	by hub.freebsd.org (Postfix) with ESMTP id 68F0B16A406
	for <freebsd-gnats-submit@FreeBSD.org>; Wed, 18 Jul 2007 23:51:04 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (groups.freebsd.org [69.147.83.33])
	by mx1.freebsd.org (Postfix) with ESMTP id 4AAA513C48E
	for <freebsd-gnats-submit@FreeBSD.org>; Wed, 18 Jul 2007 23:51:04 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.14.1/8.14.1) with ESMTP id l6INp4dC066746
	for <freebsd-gnats-submit@FreeBSD.org>; Wed, 18 Jul 2007 23:51:04 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.14.1/8.14.1/Submit) id l6INp4aa066745;
	Wed, 18 Jul 2007 23:51:04 GMT
	(envelope-from nobody)
Message-Id: <200707182351.l6INp4aa066745@www.freebsd.org>
Date: Wed, 18 Jul 2007 23:51:04 GMT
From: Cristian KLEIN <cristi@net.utcluj.ro>
To: freebsd-gnats-submit@FreeBSD.org
Subject: [gre][patch] gre(4) is not MPSAFE and does not support keys
X-Send-Pr-Version: www-3.0

>Number:         114714
>Category:       kern
>Synopsis:       [gre] [patch] gre(4) is not MPSAFE and does not support keys
>Confidential:   no
>Severity:       serious
>Priority:       low
>Responsible:    bz
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Jul 19 00:00:09 GMT 2007
>Closed-Date:    Sat Feb 11 16:58:09 UTC 2012
>Last-Modified:  Sat Feb 11 16:58:09 UTC 2012
>Originator:     Cristian KLEIN
>Release:        7.0-CURRENT
>Organization:
Technical University of Cluj-Napoca
>Environment:
FreeBSD hades.local 7.0-CURRENT FreeBSD 7.0-CURRENT #11: Tue Jul 17 04:08:17 EEST 2007     cristi@hades.local:/usr/obj/usr/src/sys/GENERIC  i386

>Description:
The first problem is that gre(4) uses a softc variable to check for loop prevention (sc->called). This is not MPSAFE, since multiple processors might use that variable at the same time. The patch below is adapted from gif(4) and uses mbuf_tags(9), which is MPSAFE.

Second, gre(4) does not support keys. The below patch contains all necessary modifications to man pages and code, to properly place keys on outbound. It has been successfully tested with a Cisco box.
>How-To-Repeat:
The first problem could be trigger by a high packet-per-second gre-encapsulated packets on a SMP machine.

For the second problem do the following on a Cisco box:

interface Tun 0
  tunnel key 1234

Or for a Linux box:

ip tunnel ... key 1234 ...

>Fix:
The below patch solves both problems.

Patch attached with submission follows:

diff -ur src/sbin/ifconfig/ifconfig.8 src.new/sbin/ifconfig/ifconfig.8
--- sbin/ifconfig/ifconfig.8	2007-07-09 18:39:58.000000000 +0300
+++ sbin/ifconfig/ifconfig.8	2007-07-19 02:12:24.255339155 +0300
@@ -1646,6 +1646,16 @@
 parameter.
 .El
 .Pp
+The following parameters are specific to GRE tunnel interfaces,
+.Xr gre 4 :
+.Bl -tag -width indent
+.It Cm grekey Ar key
+Configure the GRE key to be used for outgoing packets. Note that
+.Xr gre 4 will always accept GRE packets with invalid or absent keys.
+Also note that this command will change the MTU of the interface
+(currently 1476 without key, 1472 with key).
+.El
+.Pp
 The following parameters are specific to
 .Xr pfsync 4
 interfaces:
diff -ur src/sbin/ifconfig/ifconfig.c src.new/sbin/ifconfig/ifconfig.c
--- sbin/ifconfig/ifconfig.c	2007-06-13 21:07:59.000000000 +0300
+++ sbin/ifconfig/ifconfig.c	2007-07-18 22:01:21.000000000 +0300
@@ -51,6 +51,7 @@
 
 #include <net/ethernet.h>
 #include <net/if.h>
+#include <net/if_gre.h>
 #include <net/if_var.h>
 #include <net/if_dl.h>
 #include <net/if_types.h>
@@ -719,6 +719,19 @@
 }
 
 static void
+setifgrekey(const char *val, int dummy __unused, int s, 
+    const struct afswtch *afp)
+{
+	uint32_t grekey = atol(val);
+
+	strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
+	ifr.ifr_data = (caddr_t)&grekey;
+	if (ioctl(s, GRESKEY, (caddr_t)&ifr) < 0)
+		warn("ioctl (set grekey)");
+}
+
+
+static void
 setifname(const char *val, int dummy __unused, int s, 
     const struct afswtch *afp)
 {
@@ -833,6 +846,12 @@
 	if (ioctl(s, SIOCGIFSTATUS, &ifs) == 0) 
 		printf("%s", ifs.ascii);
 
+	int grekey = 0;
+	ifr.ifr_data = (caddr_t)&grekey;
+	if (ioctl(s, GREGKEY, &ifr) == 0)
+		if (grekey != 0)
+			printf("\tgrekey: %d\n", grekey);
+
 	close(s);
 	return;
 }
@@ -989,6 +1008,7 @@
 	DEF_CMD("noicmp",	IFF_LINK1,	setifflags),
 	DEF_CMD_ARG("mtu",			setifmtu),
 	DEF_CMD_ARG("name",			setifname),
+	DEF_CMD_ARG("grekey",		setifgrekey),
 };
 
 static __constructor void
diff -ur src/share/man/man4/gre.4 src.new/share/man/man4/gre.4
--- share/man/man4/gre.4	2006-10-19 10:41:47.000000000 +0300
+++ share/man/man4/gre.4	2007-07-19 02:11:28.909767302 +0300
@@ -167,6 +167,12 @@
 section below.
 .It Dv GREGPROTO
 Query operation mode.
+.It Dv GRESKEY
+Set the GRE key used for outgoing packets (ifr_data must point to an uint32_t).
+A value of 0 disables the key option.
+.It Dv GREGKEY
+Get the GRE key currently used for outgoing packets (ifr_data must point to an 
+uint32_t). 0 means no outgoing key.
 .El
 .Pp
 Note that the IP addresses of the tunnel endpoints may be the same as the
@@ -263,7 +269,8 @@
 .Sh NOTES
 The MTU of
 .Nm
-interfaces is set to 1476 by default, to match the value used by Cisco routers.
+interfaces is set to 1476 by default (except when setting grekey, in which
+case the MTU is 1472), so packets fit inside an Ethernet frame.
 This may not be an optimal value, depending on the link between the two tunnel
 endpoints.
 It can be adjusted via
@@ -291,10 +298,6 @@
 .Cm up
 must be given last on its command line.
 .Pp
-The kernel must be set to forward datagrams by setting the
-.Va net.inet.ip.forwarding
-.Xr sysctl 8
-variable to non-zero.
 .Sh SEE ALSO
 .\" Xr atalk 4 ,
 .Xr gif 4 ,
@@ -332,4 +335,10 @@
 .Nm
 interface itself.
 .Pp
-The GRE RFCs are not yet fully implemented (no GRE options).
+The current implementation uses the key only for outgoing packets.
+Incomming packets with a different key or without a key will be treated as if they
+would belong to this interface. There is currently little interest in implementing
+strict key checking because they are deprecated in RFC2784.
+.Pp
+RFC1701 is not fully supported, however all unsupported features have been
+deprecated in RFC2784. 
diff -ur src/sys/net/if_gre.c src.new/sys/net/if_gre.c
--- sys/net/if_gre.c	2007-06-27 02:01:01.000000000 +0300
+++ sys/net/if_gre.c	2007-07-19 02:02:28.662034699 +0300
@@ -200,10 +200,11 @@
 	sc->g_proto = IPPROTO_GRE;
 	GRE2IFP(sc)->if_flags |= IFF_LINK0;
 	sc->encap = NULL;
-	sc->called = 0;
 	sc->wccp_ver = WCCP_V1;
+	sc->key = 0;
 	if_attach(GRE2IFP(sc));
 	bpfattach(GRE2IFP(sc), DLT_NULL, sizeof(u_int32_t));
+	
 	mtx_lock(&gre_mtx);
 	LIST_INSERT_HEAD(&gre_softc_list, sc, sc_list);
 	mtx_unlock(&gre_mtx);
@@ -247,18 +248,47 @@
 	u_int16_t etype = 0;
 	struct mobile_h mob_h;
 	u_int32_t af;
+	int gre_called;
+	struct m_tag *mtag;
 
 	/*
 	 * gre may cause infinite recursion calls when misconfigured.
+	 * We'll prevent this by detecting loops.
+	 *
+	 * High nesting level may cause stack exhaustion.
 	 * We'll prevent this by introducing upper limit.
 	 */
-	if (++(sc->called) > max_gre_nesting) {
-		printf("%s: gre_output: recursively called too many "
-		       "times(%d)\n", if_name(GRE2IFP(sc)), sc->called);
+	gre_called = 1;
+	mtag = m_tag_locate(m, MTAG_GRE, MTAG_GRE_CALLED, NULL);
+	while (mtag != NULL) {
+		if (*(struct ifnet **)(mtag + 1) == ifp) {
+			printf(
+			    "gre_output: loop detected on %s\n",
+			    (*(struct ifnet **)(mtag + 1))->if_xname);
+			m_freem(m);
+			error = EIO;	/* is there better errno? */
+			goto end;
+		}
+		mtag = m_tag_locate(m, MTAG_GRE, MTAG_GRE_CALLED, mtag);
+		gre_called++;
+	}
+	if (gre_called > max_gre_nesting) {
+		printf(
+		    "gre_output: recursively called too many times (%d)\n",
+		    gre_called);
+		m_freem(m);
+		error = EIO;	/* is there better errno? */
+		goto end;
+	}
+	mtag = m_tag_alloc(MTAG_GRE, MTAG_GRE_CALLED, sizeof(struct ifnet *),
+	    M_NOWAIT);
+	if (mtag == NULL) {
 		m_freem(m);
-		error = EIO;    /* is there better errno? */
+		error = ENOMEM;
 		goto end;
 	}
+	*(struct ifnet **)(mtag + 1) = ifp;
+	m_tag_prepend(m, mtag);
 
 	if (!((ifp->if_flags & IFF_UP) &&
 	    (ifp->if_drv_flags & IFF_DRV_RUNNING)) ||
@@ -381,7 +411,12 @@
 			error = EAFNOSUPPORT;
 			goto end;
 		}
-		M_PREPEND(m, sizeof(struct greip), M_DONTWAIT);
+			
+		/* Reserve space for GRE header + optional GRE key */
+		int hdrlen = sizeof(struct greip);
+		if (sc->key)
+			hdrlen += sizeof(uint32_t);
+		M_PREPEND(m, hdrlen, M_DONTWAIT);
 	} else {
 		_IF_DROP(&ifp->if_snd);
 		m_freem(m);
@@ -397,9 +432,18 @@
 
 	gh = mtod(m, struct greip *);
 	if (sc->g_proto == IPPROTO_GRE) {
-		/* we don't have any GRE flags for now */
+		uint32_t *options = gh->gi_options;
+	
 		memset((void *)gh, 0, sizeof(struct greip));
 		gh->gi_ptype = htons(etype);
+		gh->gi_flags = 0;
+		
+		/* Add key option */
+		if (sc->key)
+		{
+			gh->gi_flags |= htons(GRE_KP);
+			*(options++) = htonl(sc->key);
+		}
 	}
 
 	gh->gi_pr = sc->g_proto;
@@ -424,7 +468,6 @@
 	error = ip_output(m, NULL, &sc->route, IP_FORWARDING,
 	    (struct ip_moptions *)NULL, (struct inpcb *)NULL);
   end:
-	sc->called = 0;
 	if (error)
 		ifp->if_oerrors++;
 	return (error);
@@ -437,7 +480,6 @@
 	struct if_laddrreq *lifr = (struct if_laddrreq *)data;
 	struct in_aliasreq *aifr = (struct in_aliasreq *)data;
 	struct gre_softc *sc = ifp->if_softc;
-	int s;
 	struct sockaddr_in si;
 	struct sockaddr *sa = NULL;
 	int error;
@@ -445,7 +487,6 @@
 
 	error = 0;
 
-	s = splnet();
 	switch (cmd) {
 	case SIOCSIFADDR:
 		ifp->if_flags |= IFF_UP;
@@ -718,12 +759,22 @@
 		si.sin_addr.s_addr = sc->g_dst.s_addr;
 		bcopy(&si, &ifr->ifr_addr, sizeof(ifr->ifr_addr));
 		break;
+	case GRESKEY:
+		sc->key = fuword(ifr->ifr_data);
+		if (sc->key == 0)
+			ifp->if_mtu = GREMTU;
+		else
+			ifp->if_mtu = GREMTU - 4;
+		break;
+	case GREGKEY:
+		suword(ifr->ifr_data, sc->key);
+		break;
+
 	default:
 		error = EINVAL;
 		break;
 	}
 
-	splx(s);
 	return (error);
 }
 
diff -ur src/sys/net/if_gre.h src.new/sys/net/if_gre.h
--- sys/net/if_gre.h	2005-06-10 19:49:18.000000000 +0300
+++ sys/net/if_gre.h	2007-07-18 22:39:29.000000000 +0300
@@ -44,6 +44,10 @@
 #ifdef _KERNEL
 #include <sys/queue.h>
 
+/* mbuf_tags(9) for recursion prevention */
+#define	MTAG_GRE	1184786929
+#define	MTAG_GRE_CALLED	0
+
 /*
  * Version of the WCCP, need to be configured manually since
  * header for version 2 is the same but IP payload is prepended
@@ -67,7 +71,8 @@
 
 	const struct encaptab *encap;	/* encapsulation cookie */
 
-	int called;		/* infinite recursion preventer */
+	uint32_t key;		/* key included in outgoing GRE packets */
+				/* zero means none */
 
 	wccp_ver_t wccp_ver;	/* version of the WCCP */
 };
@@ -78,6 +83,7 @@
 	u_int16_t flags;	/* GRE flags */
 	u_int16_t ptype;	/* protocol type of payload typically
 				   Ether protocol type*/
+	uint32_t options[];	/* optional options */
 /*
  *  from here on: fields are optional, presence indicated by flags
  *
@@ -110,6 +116,7 @@
 #define gi_dst		gi_i.ip_dst
 #define gi_ptype	gi_g.ptype
 #define gi_flags	gi_g.flags
+#define gi_options	gi_g.options
 
 #define GRE_CP		0x8000  /* Checksum Present */
 #define GRE_RP		0x4000  /* Routing Present */
@@ -174,6 +181,8 @@
 #define GREGADDRD	_IOWR('i', 104, struct ifreq)
 #define GRESPROTO	_IOW('i' , 105, struct ifreq)
 #define GREGPROTO	_IOWR('i', 106, struct ifreq)
+#define GREGKEY		_IOWR('i', 107, struct ifreq)
+#define GRESKEY		_IOW('i', 108, struct ifreq)
 
 #ifdef _KERNEL
 LIST_HEAD(gre_softc_head, gre_softc);


>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->freebsd-net 
Responsible-Changed-By: remko 
Responsible-Changed-When: Wed Jul 25 05:58:21 UTC 2007 
Responsible-Changed-Why:  
This looks something more networking specific, reassign. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=114714 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/114714: commit references a PR
Date: Fri, 20 Jun 2008 17:30:14 +0000 (UTC)

 thompsa     2008-06-20 17:26:34 UTC
 
   FreeBSD src repository
 
   Modified files:
     sbin/ifconfig        ifconfig.8 ifconfig.c 
     share/man/man4       gre.4 
     sys/net              if_gre.c if_gre.h 
   Log:
   SVN rev 179894 on 2008-06-20 17:26:34Z by thompsa
   
   Add support for the optional key in the GRE header.
   
   PR:             kern/114714
   Submitted by:   Cristian KLEIN
   
   Revision  Changes    Path
   1.148     +11 -1     src/sbin/ifconfig/ifconfig.8
   1.137     +20 -0     src/sbin/ifconfig/ifconfig.c
   1.8       +14 -2     src/share/man/man4/gre.4
   1.49      +44 -3     src/sys/net/if_gre.c
   1.15      +7 -0      src/sys/net/if_gre.h
 _______________________________________________
 cvs-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/cvs-all
 To unsubscribe, send any mail to "cvs-all-unsubscribe@freebsd.org"
 

From: Wooseog Choi <ben_choi@hotmail.com>
To: <bug-followup@freebsd.org>, <cristi@net.utcluj.ro>
Cc:  
Subject: Re: kern/114714: [gre][patch] gre(4) is not MPSAFE and does not
 support keys
Date: Thu, 31 Jul 2008 14:28:13 -0700

 --_6b0f6d37-847d-4140-98e8-949ced352c50_
 Content-Type: text/plain; charset="iso-8859-1"
 Content-Transfer-Encoding: quoted-printable
 
 
 Hi=2C
 =20
 My name is Ben Choi=2C working for Sandvine=2C Waterloo=2C ON=2C Canada.
 I had experienced similar issue=2C which was displaying many gre_out() cons=
 ole messages.
 At that moment=2C I could not access console at all.
 After applying the fix of MPSAFE codes only=2C it works fine.=20
 No error messages on console at all.
 The benefit of this fix is two-fold.
 One=2C By removing all annoying messages=2C the console becomes accessible.
 Two=2C no gre packets are dropped by this incorrect error messages.
 =20
 As the result=2C I think this code is worth to merge into official build.
 =20
 Kind regards=2C
 =20
 Ben Choi
 _________________________________________________________________
 Keep your kids safer online with Windows Live Family Safety.
 http://www.windowslive.com/family_safety/overview.html?ocid=3DTXT_TAGLM_WL_=
 family_safety_072008=
 
 --_6b0f6d37-847d-4140-98e8-949ced352c50_--

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/114714: commit references a PR
Date: Fri, 22 Aug 2008 04:04:05 +0000 (UTC)

 thompsa     2008-08-22 03:55:37 UTC
 
   FreeBSD src repository
 
   Modified files:        (Branch: RELENG_7)
     sbin/ifconfig        Makefile ifconfig.8 
     share/man/man4       gre.4 
     sys/net              if_gre.c if_gre.h 
   Added files:           (Branch: RELENG_7)
     sbin/ifconfig        ifgre.c 
   Log:
   SVN rev 181991 on 2008-08-22 03:55:37Z by thompsa
   
   MFC r179894, r181224
   
    Add support for the optional key in the GRE header.
   
    PR:            kern/114714
    Submitted by:  Cristian KLEIN
   
   Revision   Changes    Path
   1.33.2.1   +1 -0      src/sbin/ifconfig/Makefile
   1.142.2.6  +11 -1     src/sbin/ifconfig/ifconfig.8
   1.1.2.1    +98 -0     src/sbin/ifconfig/ifgre.c (new)
   1.7.2.1    +14 -2     src/share/man/man4/gre.4
   1.46.2.5   +44 -3     src/sys/net/if_gre.c
   1.13.10.2  +7 -0      src/sys/net/if_gre.h
 _______________________________________________
 cvs-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/cvs-all
 To unsubscribe, send any mail to "cvs-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: open->closed 
State-Changed-By: gavin 
State-Changed-When: Tue Mar 24 15:06:19 UTC 2009 
State-Changed-Why:  
Patch in PR was committed and MFC'd in mid 2008 


Responsible-Changed-From-To: freebsd-net->thompsa 
Responsible-Changed-By: gavin 
Responsible-Changed-When: Tue Mar 24 15:06:19 UTC 2009 
Responsible-Changed-Why:  
thompsa@ committed this 

http://www.freebsd.org/cgi/query-pr.cgi?pr=114714 
State-Changed-From-To: closed->open 
State-Changed-By: emaste 
State-Changed-When: Thu Jun 11 19:08:51 UTC 2009 
State-Changed-Why:  
The patch addresses only 1/2 of this PR. 


http://www.freebsd.org/cgi/query-pr.cgi?pr=114714 
Responsible-Changed-From-To: thompsa->bz 
Responsible-Changed-By: bz 
Responsible-Changed-When: Mon Jun 13 12:36:25 UTC 2011 
Responsible-Changed-Why:  
Take to handle the 2nd part. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=114714 

From: "Bjoern A. Zeeb" <bz@FreeBSD.org>
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/114714: [gre] [patch] gre(4) is not MPSAFE and does not
 support keys
Date: Fri, 17 Jun 2011 10:54:41 +0000 (UTC)

 Hi,
 
 I have an updated patch for the second part of the PR.  Could you
 review or test and give me feedback?
 
 I have tested multiple parallel fpings which before easily triggered
 the secondary issue of the bogus logging.  Testing the real nesting/
 recursion prevention was harder.  As it turned out gre over gre or
 gre over X over gre (with X=gif or similar virtual interfaces)
 currently does not work given how gre_compute_route() works and I had
 to instrument the code to check that this still works as expected.
 
 Regards,
 Bjoern
 
 !
 ! gre(4) was using a field in the softc to detect possible recursion.
 ! On MP systems this is not a usable solution anymore and could easily
 ! lead to false positives triggering enough logging that even  using
 ! the console was no longer usable.
 ! 
 ! Switch to the suggested solution of using mbuf tags to carry per
 ! packet state between gre_output() invocations.  Contrary to the
 ! proposed solution modelled after gif(4) only allocate one mbuf tag
 ! per packet rather than per packet and per gre_output() pass through.
 !
 ! As the sysctl to control the possible nestings (gre in gre) does no
 ! sanity checks, make sure to always allocate space in the mbuf tag
 ! for at least one, and at most 255 possible gre interfaces to detect
 ! loops in addition to the counter.
 !
 ! Submitted by:	Cristian KLEIN (cristi net.utcluj.ro) (original version)
 ! PR:		kern/114714
 ! Reviewed by:
 ! Sponsored by:	Sandvine Incorporated
 ! MFC after:	1 week
 !
 Index: sys/net/if_gre.h
 ===================================================================
 --- sys/net/if_gre.h	(revision 223011)
 +++ sys/net/if_gre.h	(working copy)
 @@ -61,8 +61,6 @@ struct gre_softc {
 
   	const struct encaptab *encap;	/* encapsulation cookie */
 
 -	int called;		/* infinite recursion preventer */
 -
   	uint32_t key;		/* key included in outgoing GRE packets */
   				/* zero means none */
 
 Index: sys/net/if_gre.c
 ===================================================================
 --- sys/net/if_gre.c	(revision 223011)
 +++ sys/net/if_gre.c	(working copy)
 @@ -48,6 +48,7 @@
   #include <sys/param.h>
   #include <sys/jail.h>
   #include <sys/kernel.h>
 +#include <sys/libkern.h>
   #include <sys/malloc.h>
   #include <sys/module.h>
   #include <sys/mbuf.h>
 @@ -91,6 +92,14 @@
 
   #define GRENAME	"gre"
 
 +#define	MTAG_COOKIE_GRE		1307983903
 +#define	MTAG_GRE_NESTING	1
 +struct mtag_gre_nesting {
 +	uint16_t	count;
 +	uint16_t	max;
 +	struct ifnet	*ifp[];
 +};
 +
   /*
    * gre_mtx protects all global variables in if_gre.c.
    * XXX: gre_softc data not protected yet.
 @@ -196,7 +205,6 @@ gre_clone_create(ifc, unit, params)
   	sc->g_proto = IPPROTO_GRE;
   	GRE2IFP(sc)->if_flags |= IFF_LINK0;
   	sc->encap = NULL;
 -	sc->called = 0;
   	sc->gre_fibnum = curthread->td_proc->p_fibnum;
   	sc->wccp_ver = WCCP_V1;
   	sc->key = 0;
 @@ -240,23 +248,77 @@ gre_output(struct ifnet *ifp, struct mbuf *m, stru
   	struct gre_softc *sc = ifp->if_softc;
   	struct greip *gh;
   	struct ip *ip;
 +	struct m_tag *mtag;
 +	struct mtag_gre_nesting *gt;
 +	size_t len;
   	u_short gre_ip_id = 0;
   	uint8_t gre_ip_tos = 0;
   	u_int16_t etype = 0;
   	struct mobile_h mob_h;
   	u_int32_t af;
 -	int extra = 0;
 +	int extra = 0, max;
 
   	/*
 -	 * gre may cause infinite recursion calls when misconfigured.
 -	 * We'll prevent this by introducing upper limit.
 +	 * gre may cause infinite recursion calls when misconfigured.  High
 +	 * nesting level may cause stack exhaustion.  We'll prevent this by
 +	 * detecting loops and by introducing upper limit.
   	 */
 -	if (++(sc->called) > max_gre_nesting) {
 -		printf("%s: gre_output: recursively called too many "
 -		       "times(%d)\n", if_name(GRE2IFP(sc)), sc->called);
 -		m_freem(m);
 -		error = EIO;    /* is there better errno? */
 -		goto end;
 +	mtag = m_tag_locate(m, MTAG_COOKIE_GRE, MTAG_GRE_NESTING, NULL);
 +	if (mtag != NULL) {
 +		struct ifnet **ifp2;
 +
 +		gt = (struct mtag_gre_nesting *)(mtag + 1);
 +		gt->count++;
 +		if (gt->count > min(gt->max,max_gre_nesting)) {
 +			printf("%s: hit maximum recursion limit %u on %s\n",
 +				__func__, gt->count - 1, ifp->if_xname);
 +			m_freem(m);
 +			error = EIO;	/* is there better errno? */
 +			goto end;
 +		}
 +
 +		ifp2 = gt->ifp;
 +		for (max = gt->count - 1; max > 0; max--) {
 +			if (*ifp2 == ifp)
 +				break;
 +			ifp2++;
 +		}
 +		if (*ifp2 == ifp) {
 +			printf("%s: detected loop with nexting %u on %s\n",
 +				__func__, gt->count-1, ifp->if_xname);
 +			m_freem(m);
 +			error = EIO;	/* is there better errno? */
 +			goto end;
 +		}
 +		*ifp2 = ifp;
 +
 +	} else {
 +		/*
 +		 * Given that people should NOT increase max_gre_nesting beyond
 +		 * their real needs, we allocate once per packet rather than
 +		 * allocating an mtag once per passing through gre.
 +		 *
 +		 * Note: the sysctl does not actually check for saneness, so we
 +		 * limit the maximum numbers of possible recursions here.
 +		 */
 +		max = imin(max_gre_nesting, 256);
 +		/* If someone sets the sysctl <= 0, we want at least 1. */
 +		max = imax(max, 1);
 +		len = sizeof(struct mtag_gre_nesting) +
 +		    max * sizeof(struct ifnet *);
 +		mtag = m_tag_alloc(MTAG_COOKIE_GRE, MTAG_GRE_NESTING, len,
 +		    M_NOWAIT);
 +		if (mtag == NULL) {
 +			m_freem(m);
 +			error = ENOMEM;
 +			goto end;
 +		}
 +		gt = (struct mtag_gre_nesting *)(mtag + 1);
 +		bzero(gt, len);
 +		gt->count = 1;
 +		gt->max = max;
 +		*gt->ifp = ifp;
 +		m_tag_prepend(m, mtag);
   	}
 
   	if (!((ifp->if_flags & IFF_UP) &&
 @@ -444,7 +506,6 @@ gre_output(struct ifnet *ifp, struct mbuf *m, stru
   	error = ip_output(m, NULL, &sc->route, IP_FORWARDING,
   	    (struct ip_moptions *)NULL, (struct inpcb *)NULL);
     end:
 -	sc->called = 0;
   	if (error)
   		ifp->if_oerrors++;
   	return (error);
 
 -- 
 Bjoern A. Zeeb                                 You have to have visions!
           Stop bit received. Insert coin for new address family.

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/114714: commit references a PR
Date: Sat, 18 Jun 2011 09:34:13 +0000 (UTC)

 Author: bz
 Date: Sat Jun 18 09:34:03 2011
 New Revision: 223223
 URL: http://svn.freebsd.org/changeset/base/223223
 
 Log:
   gre(4) was using a field in the softc to detect possible recursion.
   On MP systems this is not a usable solution anymore and could easily
   lead to false positives triggering enough logging that even  using
   the console was no longer usable (multiple parallel ping -f can do).
   
   Switch to the suggested solution of using mbuf tags to carry per
   packet state between gre_output() invocations.  Contrary to the
   proposed solution modelled after gif(4) only allocate one mbuf tag
   per packet rather than per packet and per gre_output() pass through.
   
   As the sysctl to control the possible valid (gre in gre) nestings does
   no sanity checks, make sure to always allocate space in the mbuf tag
   for at least one, and at most 255 possible gre interfaces to detect
   loops in addition to the counter.
   
   Submitted by:	Cristian KLEIN (cristi net.utcluj.ro) (original version)
   PR:		kern/114714
   Reviewed by:	Cristian KLEIN (cristi net.utcluj.ro)
   Reviewed bu:	Wooseog Choi (ben_choi hotmail.com)
   Sponsored by:	Sandvine Incorporated
   MFC after:	1 week
 
 Modified:
   head/sys/net/if_gre.c
   head/sys/net/if_gre.h
 
 Modified: head/sys/net/if_gre.c
 ==============================================================================
 --- head/sys/net/if_gre.c	Sat Jun 18 07:47:15 2011	(r223222)
 +++ head/sys/net/if_gre.c	Sat Jun 18 09:34:03 2011	(r223223)
 @@ -48,6 +48,7 @@
  #include <sys/param.h>
  #include <sys/jail.h>
  #include <sys/kernel.h>
 +#include <sys/libkern.h>
  #include <sys/malloc.h>
  #include <sys/module.h>
  #include <sys/mbuf.h>
 @@ -91,6 +92,14 @@
  
  #define GRENAME	"gre"
  
 +#define	MTAG_COOKIE_GRE		1307983903
 +#define	MTAG_GRE_NESTING	1
 +struct mtag_gre_nesting {
 +	uint16_t	count;
 +	uint16_t	max;
 +	struct ifnet	*ifp[];
 +};
 +
  /*
   * gre_mtx protects all global variables in if_gre.c.
   * XXX: gre_softc data not protected yet.
 @@ -196,7 +205,6 @@ gre_clone_create(ifc, unit, params)
  	sc->g_proto = IPPROTO_GRE;
  	GRE2IFP(sc)->if_flags |= IFF_LINK0;
  	sc->encap = NULL;
 -	sc->called = 0;
  	sc->gre_fibnum = curthread->td_proc->p_fibnum;
  	sc->wccp_ver = WCCP_V1;
  	sc->key = 0;
 @@ -240,23 +248,77 @@ gre_output(struct ifnet *ifp, struct mbu
  	struct gre_softc *sc = ifp->if_softc;
  	struct greip *gh;
  	struct ip *ip;
 +	struct m_tag *mtag;
 +	struct mtag_gre_nesting *gt;
 +	size_t len;
  	u_short gre_ip_id = 0;
  	uint8_t gre_ip_tos = 0;
  	u_int16_t etype = 0;
  	struct mobile_h mob_h;
  	u_int32_t af;
 -	int extra = 0;
 +	int extra = 0, max;
  
  	/*
 -	 * gre may cause infinite recursion calls when misconfigured.
 -	 * We'll prevent this by introducing upper limit.
 +	 * gre may cause infinite recursion calls when misconfigured.  High
 +	 * nesting level may cause stack exhaustion.  We'll prevent this by
 +	 * detecting loops and by introducing upper limit.
  	 */
 -	if (++(sc->called) > max_gre_nesting) {
 -		printf("%s: gre_output: recursively called too many "
 -		       "times(%d)\n", if_name(GRE2IFP(sc)), sc->called);
 -		m_freem(m);
 -		error = EIO;    /* is there better errno? */
 -		goto end;
 +	mtag = m_tag_locate(m, MTAG_COOKIE_GRE, MTAG_GRE_NESTING, NULL);
 +	if (mtag != NULL) {
 +		struct ifnet **ifp2;
 +
 +		gt = (struct mtag_gre_nesting *)(mtag + 1);
 +		gt->count++;
 +		if (gt->count > min(gt->max,max_gre_nesting)) {
 +			printf("%s: hit maximum recursion limit %u on %s\n",
 +				__func__, gt->count - 1, ifp->if_xname);
 +			m_freem(m);
 +			error = EIO;	/* is there better errno? */
 +			goto end;
 +		}
 +
 +		ifp2 = gt->ifp;
 +		for (max = gt->count - 1; max > 0; max--) {
 +			if (*ifp2 == ifp)
 +				break;
 +			ifp2++;
 +		}
 +		if (*ifp2 == ifp) {
 +			printf("%s: detected loop with nexting %u on %s\n",
 +				__func__, gt->count-1, ifp->if_xname);
 +			m_freem(m);
 +			error = EIO;	/* is there better errno? */
 +			goto end;
 +		}
 +		*ifp2 = ifp;
 +
 +	} else {
 +		/*
 +		 * Given that people should NOT increase max_gre_nesting beyond
 +		 * their real needs, we allocate once per packet rather than
 +		 * allocating an mtag once per passing through gre.
 +		 *
 +		 * Note: the sysctl does not actually check for saneness, so we
 +		 * limit the maximum numbers of possible recursions here.
 +		 */
 +		max = imin(max_gre_nesting, 256);
 +		/* If someone sets the sysctl <= 0, we want at least 1. */
 +		max = imax(max, 1);
 +		len = sizeof(struct mtag_gre_nesting) +
 +		    max * sizeof(struct ifnet *);
 +		mtag = m_tag_alloc(MTAG_COOKIE_GRE, MTAG_GRE_NESTING, len,
 +		    M_NOWAIT);
 +		if (mtag == NULL) {
 +			m_freem(m);
 +			error = ENOMEM;
 +			goto end;
 +		}
 +		gt = (struct mtag_gre_nesting *)(mtag + 1);
 +		bzero(gt, len);
 +		gt->count = 1;
 +		gt->max = max;
 +		*gt->ifp = ifp;
 +		m_tag_prepend(m, mtag);
  	}
  
  	if (!((ifp->if_flags & IFF_UP) &&
 @@ -444,7 +506,6 @@ gre_output(struct ifnet *ifp, struct mbu
  	error = ip_output(m, NULL, &sc->route, IP_FORWARDING,
  	    (struct ip_moptions *)NULL, (struct inpcb *)NULL);
    end:
 -	sc->called = 0;
  	if (error)
  		ifp->if_oerrors++;
  	return (error);
 
 Modified: head/sys/net/if_gre.h
 ==============================================================================
 --- head/sys/net/if_gre.h	Sat Jun 18 07:47:15 2011	(r223222)
 +++ head/sys/net/if_gre.h	Sat Jun 18 09:34:03 2011	(r223223)
 @@ -61,8 +61,6 @@ struct gre_softc {
  
  	const struct encaptab *encap;	/* encapsulation cookie */
  
 -	int called;		/* infinite recursion preventer */
 -
  	uint32_t key;		/* key included in outgoing GRE packets */
  				/* zero means none */
  
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: open->patched 
State-Changed-By: bz 
State-Changed-When: Sat Jun 18 09:41:55 UTC 2011 
State-Changed-Why:  
Change committed to HEAD, MFC in a week. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=114714 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/114714: commit references a PR
Date: Mon, 27 Jun 2011 11:11:37 +0000 (UTC)

 Author: bz
 Date: Mon Jun 27 11:10:15 2011
 New Revision: 223588
 URL: http://svn.freebsd.org/changeset/base/223588
 
 Log:
   MFC r223223:
   
    gre(4) was using a field in the softc to detect possible recursion.
    On MP systems this is not a usable solution anymore and could easily
    lead to false positives triggering enough logging that even  using
    the console was no longer usable (multiple parallel ping -f can do).
   
    Switch to the suggested solution of using mbuf tags to carry per
    packet state between gre_output() invocations.  Contrary to the
    proposed solution modelled after gif(4) only allocate one mbuf tag
    per packet rather than per packet and per gre_output() pass through.
   
    As the sysctl to control the possible valid (gre in gre) nestings does
    no sanity checks, make sure to always allocate space in the mbuf tag
    for at least one, and at most 255 possible gre interfaces to detect
    loops in addition to the counter.
   
    Submitted by:	Cristian KLEIN (cristi net.utcluj.ro) (original version)
   PR:		kern/114714
    Reviewed by:	Cristian KLEIN (cristi net.utcluj.ro)
    Reviewed bu:	Wooseog Choi (ben_choi hotmail.com)
   Sponsored by:	Sandvine Incorporated
 
 Modified:
   stable/8/sys/net/if_gre.c
   stable/8/sys/net/if_gre.h
 Directory Properties:
   stable/8/sys/   (props changed)
   stable/8/sys/amd64/include/xen/   (props changed)
   stable/8/sys/cddl/contrib/opensolaris/   (props changed)
   stable/8/sys/contrib/dev/acpica/   (props changed)
   stable/8/sys/contrib/pf/   (props changed)
 
 Modified: stable/8/sys/net/if_gre.c
 ==============================================================================
 --- stable/8/sys/net/if_gre.c	Mon Jun 27 10:42:06 2011	(r223587)
 +++ stable/8/sys/net/if_gre.c	Mon Jun 27 11:10:15 2011	(r223588)
 @@ -55,6 +55,7 @@
  #include <sys/param.h>
  #include <sys/jail.h>
  #include <sys/kernel.h>
 +#include <sys/libkern.h>
  #include <sys/malloc.h>
  #include <sys/module.h>
  #include <sys/mbuf.h>
 @@ -98,6 +99,14 @@
  
  #define GRENAME	"gre"
  
 +#define	MTAG_COOKIE_GRE		1307983903
 +#define	MTAG_GRE_NESTING	1
 +struct mtag_gre_nesting {
 +	uint16_t	count;
 +	uint16_t	max;
 +	struct ifnet	*ifp[];
 +};
 +
  /*
   * gre_mtx protects all global variables in if_gre.c.
   * XXX: gre_softc data not protected yet.
 @@ -203,7 +212,6 @@ gre_clone_create(ifc, unit, params)
  	sc->g_proto = IPPROTO_GRE;
  	GRE2IFP(sc)->if_flags |= IFF_LINK0;
  	sc->encap = NULL;
 -	sc->called = 0;
  	sc->gre_fibnum = curthread->td_proc->p_fibnum;
  	sc->wccp_ver = WCCP_V1;
  	sc->key = 0;
 @@ -247,23 +255,77 @@ gre_output(struct ifnet *ifp, struct mbu
  	struct gre_softc *sc = ifp->if_softc;
  	struct greip *gh;
  	struct ip *ip;
 +	struct m_tag *mtag;
 +	struct mtag_gre_nesting *gt;
 +	size_t len;
  	u_short gre_ip_id = 0;
  	uint8_t gre_ip_tos = 0;
  	u_int16_t etype = 0;
  	struct mobile_h mob_h;
  	u_int32_t af;
 -	int extra = 0;
 +	int extra = 0, max;
  
  	/*
 -	 * gre may cause infinite recursion calls when misconfigured.
 -	 * We'll prevent this by introducing upper limit.
 +	 * gre may cause infinite recursion calls when misconfigured.  High
 +	 * nesting level may cause stack exhaustion.  We'll prevent this by
 +	 * detecting loops and by introducing upper limit.
  	 */
 -	if (++(sc->called) > max_gre_nesting) {
 -		printf("%s: gre_output: recursively called too many "
 -		       "times(%d)\n", if_name(GRE2IFP(sc)), sc->called);
 -		m_freem(m);
 -		error = EIO;    /* is there better errno? */
 -		goto end;
 +	mtag = m_tag_locate(m, MTAG_COOKIE_GRE, MTAG_GRE_NESTING, NULL);
 +	if (mtag != NULL) {
 +		struct ifnet **ifp2;
 +
 +		gt = (struct mtag_gre_nesting *)(mtag + 1);
 +		gt->count++;
 +		if (gt->count > min(gt->max,max_gre_nesting)) {
 +			printf("%s: hit maximum recursion limit %u on %s\n",
 +				__func__, gt->count - 1, ifp->if_xname);
 +			m_freem(m);
 +			error = EIO;	/* is there better errno? */
 +			goto end;
 +		}
 +
 +		ifp2 = gt->ifp;
 +		for (max = gt->count - 1; max > 0; max--) {
 +			if (*ifp2 == ifp)
 +				break;
 +			ifp2++;
 +		}
 +		if (*ifp2 == ifp) {
 +			printf("%s: detected loop with nexting %u on %s\n",
 +				__func__, gt->count-1, ifp->if_xname);
 +			m_freem(m);
 +			error = EIO;	/* is there better errno? */
 +			goto end;
 +		}
 +		*ifp2 = ifp;
 +
 +	} else {
 +		/*
 +		 * Given that people should NOT increase max_gre_nesting beyond
 +		 * their real needs, we allocate once per packet rather than
 +		 * allocating an mtag once per passing through gre.
 +		 *
 +		 * Note: the sysctl does not actually check for saneness, so we
 +		 * limit the maximum numbers of possible recursions here.
 +		 */
 +		max = imin(max_gre_nesting, 256);
 +		/* If someone sets the sysctl <= 0, we want at least 1. */
 +		max = imax(max, 1);
 +		len = sizeof(struct mtag_gre_nesting) +
 +		    max * sizeof(struct ifnet *);
 +		mtag = m_tag_alloc(MTAG_COOKIE_GRE, MTAG_GRE_NESTING, len,
 +		    M_NOWAIT);
 +		if (mtag == NULL) {
 +			m_freem(m);
 +			error = ENOMEM;
 +			goto end;
 +		}
 +		gt = (struct mtag_gre_nesting *)(mtag + 1);
 +		bzero(gt, len);
 +		gt->count = 1;
 +		gt->max = max;
 +		*gt->ifp = ifp;
 +		m_tag_prepend(m, mtag);
  	}
  
  	if (!((ifp->if_flags & IFF_UP) &&
 @@ -451,7 +513,6 @@ gre_output(struct ifnet *ifp, struct mbu
  	error = ip_output(m, NULL, &sc->route, IP_FORWARDING,
  	    (struct ip_moptions *)NULL, (struct inpcb *)NULL);
    end:
 -	sc->called = 0;
  	if (error)
  		ifp->if_oerrors++;
  	return (error);
 
 Modified: stable/8/sys/net/if_gre.h
 ==============================================================================
 --- stable/8/sys/net/if_gre.h	Mon Jun 27 10:42:06 2011	(r223587)
 +++ stable/8/sys/net/if_gre.h	Mon Jun 27 11:10:15 2011	(r223588)
 @@ -68,8 +68,6 @@ struct gre_softc {
  
  	const struct encaptab *encap;	/* encapsulation cookie */
  
 -	int called;		/* infinite recursion preventer */
 -
  	uint32_t key;		/* key included in outgoing GRE packets */
  				/* zero means none */
  
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/114714: commit references a PR
Date: Mon, 27 Jun 2011 11:11:56 +0000 (UTC)

 Author: bz
 Date: Mon Jun 27 11:11:19 2011
 New Revision: 223589
 URL: http://svn.freebsd.org/changeset/base/223589
 
 Log:
   MFC r223223:
   
    gre(4) was using a field in the softc to detect possible recursion.
    On MP systems this is not a usable solution anymore and could easily
    lead to false positives triggering enough logging that even  using
    the console was no longer usable (multiple parallel ping -f can do).
   
    Switch to the suggested solution of using mbuf tags to carry per
    packet state between gre_output() invocations.  Contrary to the
    proposed solution modelled after gif(4) only allocate one mbuf tag
    per packet rather than per packet and per gre_output() pass through.
   
    As the sysctl to control the possible valid (gre in gre) nestings does
    no sanity checks, make sure to always allocate space in the mbuf tag
    for at least one, and at most 255 possible gre interfaces to detect
    loops in addition to the counter.
   
    Submitted by:	Cristian KLEIN (cristi net.utcluj.ro) (original version)
   PR:		kern/114714
    Reviewed by:	Cristian KLEIN (cristi net.utcluj.ro)
    Reviewed bu:	Wooseog Choi (ben_choi hotmail.com)
   Sponsored by:	Sandvine Incorporated
 
 Modified:
   stable/7/sys/net/if_gre.c
   stable/7/sys/net/if_gre.h
 Directory Properties:
   stable/7/sys/   (props changed)
   stable/7/sys/cddl/contrib/opensolaris/   (props changed)
   stable/7/sys/contrib/dev/acpica/   (props changed)
   stable/7/sys/contrib/pf/   (props changed)
 
 Modified: stable/7/sys/net/if_gre.c
 ==============================================================================
 --- stable/7/sys/net/if_gre.c	Mon Jun 27 11:10:15 2011	(r223588)
 +++ stable/7/sys/net/if_gre.c	Mon Jun 27 11:11:19 2011	(r223589)
 @@ -55,6 +55,7 @@
  #include <sys/param.h>
  #include <sys/jail.h>
  #include <sys/kernel.h>
 +#include <sys/libkern.h>
  #include <sys/malloc.h>
  #include <sys/module.h>
  #include <sys/mbuf.h>
 @@ -97,6 +98,14 @@
  
  #define GRENAME	"gre"
  
 +#define	MTAG_COOKIE_GRE		1307983903
 +#define	MTAG_GRE_NESTING	1
 +struct mtag_gre_nesting {
 +	uint16_t	count;
 +	uint16_t	max;
 +	struct ifnet	*ifp[];
 +};
 +
  /*
   * gre_mtx protects all global variables in if_gre.c.
   * XXX: gre_softc data not protected yet.
 @@ -202,7 +211,6 @@ gre_clone_create(ifc, unit, params)
  	sc->g_proto = IPPROTO_GRE;
  	GRE2IFP(sc)->if_flags |= IFF_LINK0;
  	sc->encap = NULL;
 -	sc->called = 0;
  	sc->gre_fibnum = curthread->td_proc->p_fibnum;
  	sc->wccp_ver = WCCP_V1;
  	sc->key = 0;
 @@ -246,23 +254,77 @@ gre_output(struct ifnet *ifp, struct mbu
  	struct gre_softc *sc = ifp->if_softc;
  	struct greip *gh;
  	struct ip *ip;
 +	struct m_tag *mtag;
 +	struct mtag_gre_nesting *gt;
 +	size_t len;
  	u_short gre_ip_id = 0;
  	uint8_t gre_ip_tos = 0;
  	u_int16_t etype = 0;
  	struct mobile_h mob_h;
  	u_int32_t af;
 -	int extra = 0;
 +	int extra = 0, max;
  
  	/*
 -	 * gre may cause infinite recursion calls when misconfigured.
 -	 * We'll prevent this by introducing upper limit.
 +	 * gre may cause infinite recursion calls when misconfigured.  High
 +	 * nesting level may cause stack exhaustion.  We'll prevent this by
 +	 * detecting loops and by introducing upper limit.
  	 */
 -	if (++(sc->called) > max_gre_nesting) {
 -		printf("%s: gre_output: recursively called too many "
 -		       "times(%d)\n", if_name(GRE2IFP(sc)), sc->called);
 -		m_freem(m);
 -		error = EIO;    /* is there better errno? */
 -		goto end;
 +	mtag = m_tag_locate(m, MTAG_COOKIE_GRE, MTAG_GRE_NESTING, NULL);
 +	if (mtag != NULL) {
 +		struct ifnet **ifp2;
 +
 +		gt = (struct mtag_gre_nesting *)(mtag + 1);
 +		gt->count++;
 +		if (gt->count > min(gt->max,max_gre_nesting)) {
 +			printf("%s: hit maximum recursion limit %u on %s\n",
 +				__func__, gt->count - 1, ifp->if_xname);
 +			m_freem(m);
 +			error = EIO;	/* is there better errno? */
 +			goto end;
 +		}
 +
 +		ifp2 = gt->ifp;
 +		for (max = gt->count - 1; max > 0; max--) {
 +			if (*ifp2 == ifp)
 +				break;
 +			ifp2++;
 +		}
 +		if (*ifp2 == ifp) {
 +			printf("%s: detected loop with nexting %u on %s\n",
 +				__func__, gt->count-1, ifp->if_xname);
 +			m_freem(m);
 +			error = EIO;	/* is there better errno? */
 +			goto end;
 +		}
 +		*ifp2 = ifp;
 +
 +	} else {
 +		/*
 +		 * Given that people should NOT increase max_gre_nesting beyond
 +		 * their real needs, we allocate once per packet rather than
 +		 * allocating an mtag once per passing through gre.
 +		 *
 +		 * Note: the sysctl does not actually check for saneness, so we
 +		 * limit the maximum numbers of possible recursions here.
 +		 */
 +		max = imin(max_gre_nesting, 256);
 +		/* If someone sets the sysctl <= 0, we want at least 1. */
 +		max = imax(max, 1);
 +		len = sizeof(struct mtag_gre_nesting) +
 +		    max * sizeof(struct ifnet *);
 +		mtag = m_tag_alloc(MTAG_COOKIE_GRE, MTAG_GRE_NESTING, len,
 +		    M_NOWAIT);
 +		if (mtag == NULL) {
 +			m_freem(m);
 +			error = ENOMEM;
 +			goto end;
 +		}
 +		gt = (struct mtag_gre_nesting *)(mtag + 1);
 +		bzero(gt, len);
 +		gt->count = 1;
 +		gt->max = max;
 +		*gt->ifp = ifp;
 +		m_tag_prepend(m, mtag);
  	}
  
  	if (!((ifp->if_flags & IFF_UP) &&
 @@ -450,7 +512,6 @@ gre_output(struct ifnet *ifp, struct mbu
  	error = ip_output(m, NULL, &sc->route, IP_FORWARDING,
  	    (struct ip_moptions *)NULL, (struct inpcb *)NULL);
    end:
 -	sc->called = 0;
  	if (error)
  		ifp->if_oerrors++;
  	return (error);
 
 Modified: stable/7/sys/net/if_gre.h
 ==============================================================================
 --- stable/7/sys/net/if_gre.h	Mon Jun 27 11:10:15 2011	(r223588)
 +++ stable/7/sys/net/if_gre.h	Mon Jun 27 11:11:19 2011	(r223589)
 @@ -68,8 +68,6 @@ struct gre_softc {
  
  	const struct encaptab *encap;	/* encapsulation cookie */
  
 -	int called;		/* infinite recursion preventer */
 -
  	uint32_t key;		/* key included in outgoing GRE packets */
  				/* zero means none */
  
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: patched->closed 
State-Changed-By: bz 
State-Changed-When: Sat Feb 11 16:57:28 UTC 2012 
State-Changed-Why:  
It seems the MFCs have long happened but the PR was not closed. 

Thanksa  lot for the report! 

http://www.freebsd.org/cgi/query-pr.cgi?pr=114714 
>Unformatted:
