Subject: kern/11915: IPv6 patches for if_tun.c
To: None <gnats-bugs@gnats.netbsd.org>
From: Michael Richardson <mcr@sandelman.ottawa.on.ca>
List: netbsd-bugs
Date: 01/07/2001 21:23:17
>Number:         11915
>Category:       kern
>Synopsis:       IPv6 patches for if_tun.c
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Sun Jan 07 21:23:01 PST 2001
>Closed-Date:
>Last-Modified:
>Originator:     Michael Richardson
>Release:        NetBSD 1.5_ALPHA2
>Organization:
Sandelman Software Works
>Environment:
	
System: NetBSD marajade.sandelman.ottawa.on.ca 1.5_ALPHA2 NetBSD 1.5_ALPHA2 (XTERM) #24: Sun Jan 7 23:58:45 EST 2001 mcr@marajade.sandelman.ottawa.on.ca:/mara/mcr/corp/network/kernels/compile-current/XTERM i386
Architecture: i386

>Description:
	tun0 does not support IPv6

>How-To-Repeat:
>Fix:

Index: if_tun.c
===================================================================
RCS file: /cvsroot/syssrc/sys/net/if_tun.c,v
retrieving revision 1.39
diff -u -r1.39 if_tun.c
--- if_tun.c	2000/03/30 09:45:37	1.39
+++ if_tun.c	2001/01/08 05:16:06
@@ -94,7 +94,7 @@
 		ifp->if_mtu = TUNMTU;
 		ifp->if_ioctl = tun_ioctl;
 		ifp->if_output = tun_output;
-		ifp->if_flags = IFF_POINTOPOINT;
+		ifp->if_flags = IFF_POINTOPOINT|IFF_MULTICAST;
 		ifp->if_snd.ifq_maxlen = ifqmaxlen;
 		ifp->if_collisions = 0;
 		ifp->if_ierrors = 0;
@@ -221,6 +221,21 @@
 			}
 		}
 #endif
+#ifdef INET6
+		if (ifa->ifa_addr->sa_family == AF_INET6) {
+			struct sockaddr_in6 *sin6;
+
+			sin6 = satosin6(ifa->ifa_addr);
+			if (sin6 && !IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
+				tp->tun_flags |= TUN_IASET;
+
+			if (ifp->if_flags & IFF_POINTOPOINT) {
+				sin6 = satosin6(ifa->ifa_dstaddr);
+				if (sin6 && !IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
+					tp->tun_flags |= TUN_DSTADDR;
+			}
+		}
+#endif
 	}
 
 	return;
@@ -335,8 +350,13 @@
 #endif
 
 	switch(dst->sa_family) {
+#ifdef INET6
+	case AF_INET6:
+#endif
 #ifdef INET
 	case AF_INET:
+#endif
+#if defined(INET) || defined(INET6)
 		if (tp->tun_flags & TUN_PREPADDR) {
 			/* Simple link-layer header */
 			M_PREPEND(m0, dst->sa_len, M_DONTWAIT);
@@ -347,6 +367,8 @@
 			bcopy(dst, mtod(m0, char *), dst->sa_len);
 		}
 		/* FALLTHROUGH */
+#endif
+#if defined(INET) || defined(INET6)
 	case AF_UNSPEC:
 		s = splimp();
 		if (IF_QFULL(&ifp->if_snd)) {
@@ -361,6 +383,8 @@
 		ifp->if_opackets++;
 		break;
 #endif
+	  
+
 	default:
 		m_freem(m0);
 		return (EAFNOSUPPORT);
@@ -413,7 +437,7 @@
 				return (EBUSY);
 			}
 			tp->tun_if.if_flags &=
-				~(IFF_BROADCAST|IFF_POINTOPOINT|IFF_MULTICAST);
+				~(IFF_BROADCAST|IFF_POINTOPOINT);
 			tp->tun_if.if_flags |= *(int *)data;
 			splx(s);
 			break;
@@ -541,10 +565,14 @@
 	struct mbuf	*top, **mp, *m;
 	struct ifqueue	*ifq;
 	struct sockaddr	dst;
+	unsigned char   type;
+	int             usedtype;
 	int		isr, error=0, s, tlen, mlen;
 
 	TUNDEBUG("%s: tunwrite\n", ifp->if_xname);
 
+	usedtype = 0;
+
 	if (tp->tun_flags & TUN_PREPADDR) {
 		if (uio->uio_resid < sizeof(dst))
 			return (EIO);
@@ -558,8 +586,35 @@
 					return (error);
 		}
 	} else {
-#ifdef INET
-		dst.sa_family = AF_INET;
+#if defined(INET) || defined(INET6)
+	  size_t saveme_res;
+	  off_t  saveme_off;
+
+	  saveme_res = uio->uio_resid;
+	  saveme_off = uio->uio_offset;
+
+	  /* assume IPx, look at first byte */
+	  if(uio->uio_resid < 1) {
+	    return(EIO);
+	  }
+
+	  error = uiomove((caddr_t)&type, 1, uio);
+
+	  uio->uio_resid = saveme_res;
+	  uio->uio_offset= saveme_off;
+
+	  switch(type & 0xf0) {
+	  case 0x40:
+	    dst.sa_family = AF_INET;
+	    break;
+
+	  case 0x60:
+	    dst.sa_family = AF_INET6;
+	    break;
+	    
+	  default:
+	    return EIO;
+	  }
 #endif
 	}
 
@@ -574,6 +629,12 @@
 	case AF_INET:
 		ifq = &ipintrq;
 		isr = NETISR_IP;
+		break;
+#endif
+#ifdef INET
+	case AF_INET6:
+		ifq = &ip6intrq;
+		isr = NETISR_IPV6;
 		break;
 #endif
 	default:

>Release-Note:
>Audit-Trail:
>Unformatted: