diff -ru src/sys/net/if_tun.c /usr/src/sys/net/if_tun.c
--- src/sys/net/if_tun.c	2005-01-24 22:25:09.000000000 +0100
+++ /usr/src/sys/net/if_tun.c	2006-09-17 15:25:20.000000000 +0200
@@ -101,7 +101,7 @@
 
 const struct cdevsw tun_cdevsw = {
 	tunopen, tunclose, tunread, tunwrite, tunioctl,
-	nostop, notty, tunpoll, nommap, tunkqfilter,
+	nostop, notty, tunpoll, nommap, tunkqfilter, D_OTHER,
 };
 
 void
@@ -209,7 +209,7 @@
 #ifdef ALTQ
 	ifp->if_start = tunstart;
 #endif
-	ifp->if_flags = IFF_POINTOPOINT;
+	ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
 	ifp->if_type = IFT_TUNNEL;
 	ifp->if_snd.ifq_maxlen = ifqmaxlen;
 	ifp->if_collisions = 0;
@@ -357,8 +357,10 @@
 			/* find internet addresses and delete routes */
 			struct ifaddr *ifa;
 			IFADDR_FOREACH(ifa, ifp) {
-#ifdef INET
-				if (ifa->ifa_addr->sa_family == AF_INET) {
+#if defined(INET) || defined(INET6)
+				
+				if (ifa->ifa_addr->sa_family == AF_INET ||
+				    ifa->ifa_addr->sa_family == AF_INET6 ) {
 					rtinit(ifa, (int)RTM_DELETE,
 					       tp->tun_flags & TUN_DSTADDR
 							? RTF_HOST
@@ -409,6 +411,24 @@
 			}
 		}
 #endif
+#ifdef INET6
+	if( ifa->ifa_addr->sa_family == AF_INET6 ) {
+		struct sockaddr_in6 *sin;
+
+		sin = (struct sockaddr_in6 *)ifa->ifa_addr;
+		if( !IN6_IS_ADDR_UNSPECIFIED(&sin->sin6_addr) )
+			tp->tun_flags |= TUN_IASET;
+
+		if( ifp->if_flags & IFF_POINTOPOINT ) {
+			sin = (struct sockaddr_in6 *)ifa->ifa_dstaddr;
+			if( 	sin
+			    &&	!IN6_IS_ADDR_UNSPECIFIED( &sin->sin6_addr) )
+				tp->tun_flags |= TUN_DSTADDR;
+		} else
+			tp->tun_flags &= ~TUN_DSTADDR;
+	}
+
+#endif /* INET6 */
 	}
 
 	return;
@@ -463,6 +483,10 @@
 		case AF_INET:
 			break;
 #endif
+#ifdef INET6
+		case AF_INET6:
+			break;
+#endif
 		default:
 			error = EAFNOSUPPORT;
 			break;
@@ -493,8 +517,9 @@
 	struct tun_softc *tp = ifp->if_softc;
 	int		s;
 	int		error;
-#ifdef INET
+#if defined(INET) || defined(INET6)
 	int		mlen;
+	uint32_t	*af;
 #endif
 	ALTQ_DECL(struct altq_pktattr pktattr;)
 
@@ -522,8 +547,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);
@@ -533,6 +563,27 @@
 				goto out;
 			}
 			bcopy(dst, mtod(m0, char *), dst->sa_len);
+		} 
+
+		if( tp->tun_flags & TUN_IFHEAD ) {
+			/* Prepend the adress family */
+			M_PREPEND( m0, sizeof(*af), M_DONTWAIT);
+			if(m0 == NULL ) {
+				IF_DROP(&ifp->if_snd);
+				error = ENOBUFS;
+				goto out;
+			}
+			af = mtod(m0,uint32_t *);
+			*af = htonl(dst->sa_family);
+		} else {
+#ifdef INET
+			if( dst->sa_family != AF_INET )
+#endif
+			{
+				m_freem(m0);
+				error = EAFNOSUPPORT;
+				goto out;
+			}
 		}
 		/* FALLTHROUGH */
 	case AF_UNSPEC:
@@ -619,10 +670,23 @@
 		break;
 
 	case TUNSLMODE:
-		if (*(int *)data)
+		if (*(int *)data) {
 			tp->tun_flags |= TUN_PREPADDR;
-		else
+			tp->tun_flags &= ~TUN_IFHEAD;
+		} else
+			tp->tun_flags &= ~TUN_PREPADDR;
+		break;
+
+	case TUNSIFHEAD:
+		if( *(int *)data ) {
+			tp->tun_flags |= TUN_IFHEAD;
 			tp->tun_flags &= ~TUN_PREPADDR;
+		} else
+			tp->tun_flags &= ~TUN_IFHEAD;
+		break;
+
+	case TUNGIFHEAD:
+		*(int *)data = (tp->tun_flags & TUN_IFHEAD);
 		break;
 
 	case FIONBIO:
@@ -778,6 +842,7 @@
 	struct ifqueue	*ifq;
 	struct sockaddr	dst;
 	int		isr, error = 0, s, tlen, mlen;
+	uint32_t	family;
 
 	s = splnet();
 	tp = tun_find_unit(dev);
@@ -811,6 +876,13 @@
 					goto out0;
 				}
 		}
+	} else if( tp->tun_flags & TUN_IFHEAD ) {
+		if( uio->uio_resid < sizeof(family) ) {
+			error = EIO;
+			goto out;
+		}
+		error = uiomove( (caddr_t)&family, sizeof(family), uio );
+		dst.sa_family = ntohl( family );
 	} else {
 #ifdef INET
 		dst.sa_family = AF_INET;
@@ -831,6 +903,12 @@
 		isr = NETISR_IP;
 		break;
 #endif
+#ifdef INET6
+	case AF_INET6:
+		ifq = &ip6intrq;
+		isr = NETISR_IPV6;
+		break;
+#endif
 	default:
 		error = EAFNOSUPPORT;
 		goto out0;
@@ -874,7 +952,7 @@
 
 #if NBPFILTER > 0
 	if (ifp->if_bpf)
-		bpf_mtap_af(ifp->if_bpf, AF_INET, top);
+		bpf_mtap_af(ifp->if_bpf, dst.sa_family, top);
 #endif
 
 	s = splnet();
diff -ru src/sys/net/if_tun.h /usr/src/sys/net/if_tun.h
--- src/sys/net/if_tun.h	2005-02-26 23:45:09.000000000 +0100
+++ /usr/src/sys/net/if_tun.h	2006-09-16 13:42:03.000000000 +0200
@@ -33,6 +33,7 @@
 #define	TUN_ASYNC	0x0080
 #define	TUN_NBIO	0x0100
 #define	TUN_PREPADDR	0x0200
+#define TUN_IFHEAD	0x0400
 
 #define	TUN_READY	(TUN_OPEN | TUN_INITED | TUN_IASET)
 
@@ -53,5 +54,7 @@
 #define	TUNGDEBUG	_IOR('t', 89, int)
 #define	TUNSIFMODE	_IOW('t', 88, int)
 #define	TUNSLMODE	_IOW('t', 87, int)
+#define TUNSIFHEAD	_IOW('t', 86, int)
+#define TUNGIFHEAD	_IOW('t', 85, int)
 
 #endif /* !_NET_IF_TUN_H_ */
diff -ru src/sys/sys/conf.h /usr/src/sys/sys/conf.h
--- src/sys/sys/conf.h	2005-02-03 20:20:01.000000000 +0100
+++ /usr/src/sys/sys/conf.h	2006-09-16 14:05:42.000000000 +0200
@@ -53,6 +53,7 @@
 /*
  * Types for d_type
  */
+#define D_OTHER 0
 #define	D_TAPE	1
 #define	D_DISK	2
 #define	D_TTY	3

