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: