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