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