Subject: kern/29150: patch for IPv6-over-GRE
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: None <gert@greenie.muc.de>
List: netbsd-bugs
Date: 01/28/2005 21:29:00
>Number:         29150
>Category:       kern
>Synopsis:       enhancement: patch for IPv6-over-GRE
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Fri Jan 28 21:29:00 +0000 2005
>Originator:     Gert Doering
>Release:        NetBSD 2.99.15
>Organization:
	
>Environment:
	
	
System: NetBSD scotty.greenie.muc.de 2.99.15 NetBSD 2.99.15 (SCOTTY-IPSEC) #24: Thu Jan 27 11:03:11 CET 2005 gert@scotty.greenie.muc.de:/home/sparc64.current/obj/usr/src-current/sys/arch/sparc64/compile/SCOTTY-IPSEC sparc64
Architecture: sparc64
Machine: sparc64
>Description:
	here's a patch to add IPv6 support for GRE tunneling.
	IPv6-over-IPv4 (proto-41, gif) is not always possible due to 
	external circumstances, and GRE might work there.  Also it might
	be useful if one needs to do IPv4+IPv6 tunneling over a single
	tunnel to a Cisco - Cisco can only do multiprotocol over GRE.
	In addition, there's a bugfix for NS/XEROX tunneling - the current
	code references ip->ip_tos with "ip == NULL".
>How-To-Repeat:
	not a bugfix :)
>Fix:
	here's the patch.  

	It certainly needs review to make sure that I didn't overlook anything.

	Index: net/if_gre.c
	===================================================================
	RCS file: /cvsroot/src/sys/net/if_gre.c,v
	retrieving revision 1.54
	diff -u -r1.54 if_gre.c
	--- net/if_gre.c	6 Dec 2004 02:59:23 -0000	1.54
	+++ net/if_gre.c	25 Jan 2005 22:28:26 -0000
	@@ -7,6 +7,8 @@
	  * This code is derived from software contributed to The NetBSD Foundation
	  * by Heiko W.Rupp <hwr@pilhuhn.de>
	  *
	+ * IPv6-over-GRE contributed by Gert Doering <gert@greenie.muc.de>
	+ *
	  * Redistribution and use in source and binary forms, with or without
	  * modification, are permitted provided that the following conditions
	  * are met:
	@@ -180,6 +182,7 @@
		struct gre_softc *sc = ifp->if_softc;
		struct greip *gh;
		struct ip *ip;
	+	u_int8_t ip_tos = 0;
		u_int16_t etype = 0;
		struct mobile_h mob_h;
	 
	@@ -263,9 +266,14 @@
				goto end;
			}
		} else if (sc->g_proto == IPPROTO_GRE) {
	+#ifdef GRE_DEBUG
	+		printf( "start gre_output/GRE, dst->sa_family=%d\n", 
	+		         dst->sa_family );
	+#endif
			switch (dst->sa_family) {
			case AF_INET:
				ip = mtod(m, struct ip *);
	+		        ip_tos = ip->ip_tos;
				etype = ETHERTYPE_IP;
				break;
	 #ifdef NETATALK
	@@ -278,6 +286,11 @@
				etype = ETHERTYPE_NS;
				break;
	 #endif
	+#ifdef INET6
	+		case AF_INET6:
	+			etype = ETHERTYPE_IPV6;
	+			break;
	+#endif
			default:
				IF_DROP(&ifp->if_snd);
				m_freem(m);
	@@ -312,7 +325,7 @@
			gh->gi_dst = sc->g_dst;
			((struct ip*)gh)->ip_hl = (sizeof(struct ip)) >> 2;
			((struct ip*)gh)->ip_ttl = ip_gre_ttl;
	-		((struct ip*)gh)->ip_tos = ip->ip_tos;
	+		((struct ip*)gh)->ip_tos = ip_tos;
			gh->gi_len = htons(m->m_pkthdr.len);
		}
	 
	@@ -381,6 +394,10 @@
			case AF_INET:
				break;
	 #endif
	+#ifdef INET6
	+		case AF_INET6:
	+			break;
	+#endif
			default:
				error = EAFNOSUPPORT;
				break;
	Index: netinet/ip_gre.c
	===================================================================
	RCS file: /cvsroot/src/sys/netinet/ip_gre.c,v
	retrieving revision 1.30
	diff -u -r1.30 ip_gre.c
	--- netinet/ip_gre.c	26 Apr 2004 01:31:56 -0000	1.30
	+++ netinet/ip_gre.c	25 Jan 2005 22:28:27 -0000
	@@ -7,6 +7,8 @@
	  * This code is derived from software contributed to The NetBSD Foundation
	  * by Heiko W.Rupp <hwr@pilhuhn.de>
	  *
	+ * IPv6-over-GRE contributed by Gert Doering <gert@greenie.muc.de>
	+ *
	  * Redistribution and use in source and binary forms, with or without
	  * modification, are permitted provided that the following conditions
	  * are met:
	@@ -145,7 +147,7 @@
	 gre_input2(struct mbuf *m, int hlen, u_char proto)
	 {
		struct greip *gip;
	-	int s;
	+	int s, isr;
		struct ifqueue *ifq;
		struct gre_softc *sc;
		u_int16_t flags;
	@@ -186,22 +188,31 @@
			switch (ntohs(gip->gi_ptype)) { /* ethertypes */
			case ETHERTYPE_IP: /* shouldn't need a schednetisr(), as */
				ifq = &ipintrq;          /* we are in ip_input */
	+			isr = NETISR_IP;
				break;
	 #ifdef NS
			case ETHERTYPE_NS:
				ifq = &nsintrq;
	-			schednetisr(NETISR_NS);
	+			isr = NETISR_NS;
				break;
	 #endif
	 #ifdef NETATALK
			case ETHERTYPE_ATALK:
				ifq = &atintrq1;
	-			schednetisr(NETISR_ATALK);
	+			isr = NETISR_ATALK;
				break;
	 #endif
	+#ifdef INET6
			case ETHERTYPE_IPV6:
	-			/* FALLTHROUGH */
	+#ifdef GRE_DEBUG
	+			printf( "ip_gre.c/gre_input2: IPv6 packet\n" );
	+#endif
	+			ifq = &ip6intrq;
	+			isr = NETISR_IPV6;
	+			break;
	+#endif
			default:	   /* others not yet supported */
	+			printf( "ip_gre.c/gre_input2: unhandled ethertype 0x%04x\n", (int) ntohs(gip->gi_ptype) );
				return (0);
			}
			break;
	@@ -239,6 +250,8 @@
		} else {
			IF_ENQUEUE(ifq, m);
		}
	+	/* we need schednetisr since the address family may change */
	+	schednetisr(isr);
		splx(s);
	 
		return (1);	/* packet is done, no further processing needed */