diff options
author | Michael Shalayeff <mickey@cvs.openbsd.org> | 1996-02-20 14:34:02 +0000 |
---|---|---|
committer | Michael Shalayeff <mickey@cvs.openbsd.org> | 1996-02-20 14:34:02 +0000 |
commit | bdf1f6ab6543c39add36f4498e48a558acf2bfad (patch) | |
tree | 3d2b0bce318e1cc0fdd73890f60e2de447122dc0 /sys | |
parent | c758c67c5202e29d91113df836f508d9d62c561f (diff) |
bug fixes, speedups. multiple AFs support.
bpf fixes.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/net/if_tun.c | 211 | ||||
-rw-r--r-- | sys/net/if_tun.h | 25 |
2 files changed, 148 insertions, 88 deletions
diff --git a/sys/net/if_tun.c b/sys/net/if_tun.c index 0e096f1bf20..936a994be3f 100644 --- a/sys/net/if_tun.c +++ b/sys/net/if_tun.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_tun.c,v 1.19 1995/12/13 23:47:40 pk Exp $ */ +/* $OpenBSD: if_tun.c,v 1.3 1996/02/20 14:34:00 mickey Exp $ */ /* * Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk> @@ -17,7 +17,10 @@ #include "tun.h" #if NTUN > 0 +/* #define TUN_DEBUG 9 /* */ + #include <sys/param.h> +#include <sys/kernel.h> #include <sys/proc.h> #include <sys/systm.h> #include <sys/mbuf.h> @@ -29,10 +32,15 @@ #include <sys/syslog.h> #include <sys/select.h> #include <sys/file.h> +#include <sys/time.h> +#include <sys/device.h> +#include <sys/conf.h> +#include <sys/vnode.h> #include <machine/cpu.h> #include <net/if.h> +#include <net/if_types.h> #include <net/netisr.h> #include <net/route.h> @@ -41,7 +49,7 @@ #include <netinet/in_systm.h> #include <netinet/in_var.h> #include <netinet/ip.h> -#include <netinet/if_ether.h> +/* #include <netinet/if_ether.h> */ #endif #ifdef NS @@ -49,30 +57,37 @@ #include <netns/ns_if.h> #endif +#ifdef ISO +#include <netiso/iso.h> +#include <netiso/iso_var.h> +#endif + #include "bpfilter.h" #if NBPFILTER > 0 -#include <sys/time.h> #include <net/bpf.h> #endif #include <net/if_tun.h> +#ifdef TUN_DEBUG #define TUNDEBUG if (tundebug) printf -int tundebug = 0; +int tundebug = TUN_DEBUG; +#endif struct tun_softc tunctl[NTUN]; + extern int ifqmaxlen; -int tunopen __P((dev_t, int, int, struct proc *)); -int tunclose __P((dev_t, int)); -int tunoutput __P((struct ifnet *, struct mbuf *, struct sockaddr *, - struct rtentry *rt)); -int tunread __P((dev_t, struct uio *)); -int tunwrite __P((dev_t, struct uio *)); -int tuncioctl __P((dev_t, u_long, caddr_t, int, struct proc *)); -int tunioctl __P((struct ifnet *, u_long, caddr_t)); -int tunselect __P((dev_t, int)); -void tunattach __P((int)); +int tunopen __P((dev_t, int, int, struct proc *)); +int tunclose __P((dev_t, int, int, struct proc *)); +int tunoutput __P((struct ifnet *, struct mbuf *, struct sockaddr *, + struct rtentry *rt)); +int tunread __P((dev_t, struct uio *, int)); +int tunwrite __P((dev_t, struct uio *, int)); +int tunioctl __P((dev_t, u_long, caddr_t, int, struct proc *)); +int tunifioctl __P((struct ifnet *, u_long, caddr_t)); +int tunselect __P((dev_t, int, struct proc *)); +void tunattach __P((int)); static int tuninit __P((int)); @@ -91,10 +106,13 @@ tunattach(unused) ifp->if_unit = i; ifp->if_name = "tun"; ifp->if_mtu = TUNMTU; - ifp->if_ioctl = tunioctl; + ifp->if_ioctl = tunifioctl; ifp->if_output = tunoutput; ifp->if_flags = IFF_POINTOPOINT; + ifp->if_type = IFT_PROPVIRTUAL; ifp->if_snd.ifq_maxlen = ifqmaxlen; + ifp->if_hdrlen = sizeof(struct tunnel_header); + ifp->if_addrlen = 0; ifp->if_collisions = 0; ifp->if_ierrors = 0; ifp->if_oerrors = 0; @@ -102,7 +120,7 @@ tunattach(unused) ifp->if_opackets = 0; if_attach(ifp); #if NBPFILTER > 0 - bpfattach(&tunctl[i].tun_bpf, ifp, DLT_NULL, sizeof(u_int32_t)); + bpfattach(&ifp->if_bpf, ifp, DLT_NULL, sizeof(u_int32_t)); #endif } } @@ -140,9 +158,10 @@ tunopen(dev, flag, mode, p) * routing info */ int -tunclose(dev, flag) +tunclose(dev, flag, mode, p) dev_t dev; - int flag; + int flag,mode; + struct proc *p; { register int unit = minor(dev), s; struct tun_softc *tp = &tunctl[unit]; @@ -169,7 +188,7 @@ tunclose(dev, flag) /* find internet addresses and delete routes */ register struct ifaddr *ifa; for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; - ifa = ifa->ifa_list.tqe_next) { + ifa = ifa->ifa_list.tqe_next) { if (ifa->ifa_addr->sa_family == AF_INET) { rtinit(ifa, (int)RTM_DELETE, tp->tun_flags & TUN_DSTADDR ? RTF_HOST : 0); @@ -219,7 +238,7 @@ tuninit(unit) * Process an ioctl request. */ int -tunioctl(ifp, cmd, data) +tunifioctl(ifp, cmd, data) struct ifnet *ifp; u_long cmd; caddr_t data; @@ -268,47 +287,32 @@ tunoutput(ifp, m0, dst, rt) m_freem (m0); return EHOSTDOWN; } + ifp->if_lastchange = time; -#if NBPFILTER > 0 - if (tp->tun_bpf) { - /* - * We need to prepend the address family as - * a four byte field. Cons up a dummy header - * to pacify bpf. This is safe because bpf - * will only read from the mbuf (i.e., it won't - * try to free it or keep a pointer to it). - */ - struct mbuf m; - u_int32_t af = dst->sa_family; - - m.m_next = m0; - m.m_len = sizeof(af); - m.m_data = (char *)⁡ - - bpf_mtap(tp->tun_bpf, &m); + M_PREPEND( m0, sizeof(struct tunnel_header), M_DONTWAIT ); + { + struct tunnel_header *th = mtod( m0, struct tunnel_header * ); + th->tun_af = dst->sa_family; } -#endif - switch(dst->sa_family) { -#ifdef INET - case AF_INET: - s = splimp(); - if (IF_QFULL(&ifp->if_snd)) { - IF_DROP(&ifp->if_snd); - m_freem(m0); - splx(s); - ifp->if_collisions++; - return (ENOBUFS); - } - IF_ENQUEUE(&ifp->if_snd, m0); - splx(s); - ifp->if_opackets++; - break; +#if NBPFILTER > 0 + if (ifp->if_bpf) + bpf_mtap(ifp->if_bpf, m0); #endif - default: + + s = splimp(); + if (IF_QFULL(&ifp->if_snd)) { + IF_DROP(&ifp->if_snd); m_freem(m0); - return EAFNOSUPPORT; + splx(s); + ifp->if_collisions++; + return (ENOBUFS); } + IF_ENQUEUE(&ifp->if_snd, m0); + splx(s); + + ifp->if_opackets++; + ifp->if_obytes += m0->m_pkthdr.len + sizeof(struct tunnel_header); if (tp->tun_flags & TUN_RWAIT) { tp->tun_flags &= ~TUN_RWAIT; @@ -328,7 +332,7 @@ tunoutput(ifp, m0, dst, rt) * the cdevsw interface is now pretty minimal. */ int -tuncioctl(dev, cmd, data, flag, p) +tunioctl(dev, cmd, data, flag, p) dev_t dev; u_long cmd; caddr_t data; @@ -337,14 +341,29 @@ tuncioctl(dev, cmd, data, flag, p) { int unit = minor(dev), s; struct tun_softc *tp = &tunctl[unit]; + struct tuninfo *tunp; switch (cmd) { + case TUNSIFINFO: + tunp = (struct tuninfo *)data; + tp->tun_if.if_mtu = tunp->mtu; + tp->tun_if.if_type = tunp->type; + tp->tun_if.if_baudrate = tunp->baudrate; + break; + case TUNGIFINFO: + tunp = (struct tuninfo *)data; + tunp->mtu = tp->tun_if.if_mtu; + tunp->type = tp->tun_if.if_type; + tunp->baudrate = tp->tun_if.if_baudrate; + break; +#ifdef TUN_DEBUG case TUNSDEBUG: tundebug = *(int *)data; break; case TUNGDEBUG: *(int *)data = tundebug; break; +#endif case FIONBIO: if (*(int *)data) tp->tun_flags |= TUN_NBIO; @@ -382,9 +401,10 @@ tuncioctl(dev, cmd, data, flag, p) * least as much of a packet as can be read. */ int -tunread(dev, uio) +tunread(dev, uio,flags) dev_t dev; struct uio *uio; + int flags; { int unit = minor(dev); struct tun_softc *tp = &tunctl[unit]; @@ -405,7 +425,7 @@ tunread(dev, uio) do { IF_DEQUEUE(&ifp->if_snd, m0); if (m0 == 0) { - if (tp->tun_flags & TUN_NBIO) { + if (tp->tun_flags & TUN_NBIO && flags & IO_NDELAY) { splx(s); return EWOULDBLOCK; } @@ -430,6 +450,7 @@ tunread(dev, uio) } if (error) ifp->if_ierrors++; + return error; } @@ -437,13 +458,17 @@ tunread(dev, uio) * the cdevsw write interface - an atomic write is a packet - or else! */ int -tunwrite(dev, uio) +tunwrite(dev, uio, flags) dev_t dev; struct uio *uio; + int flags; { int unit = minor (dev); struct ifnet *ifp = &tunctl[unit].tun_if; + struct ifqueue *ifq; + struct tunnel_header *th; struct mbuf *top, **mp, *m; + int isr; int error=0, s, tlen, mlen; TUNDEBUG("%s%d: tunwrite\n", ifp->if_name, ifp->if_unit); @@ -488,37 +513,56 @@ tunwrite(dev, uio) top->m_pkthdr.rcvif = ifp; #if NBPFILTER > 0 - if (tunctl[unit].tun_bpf) { - /* - * We need to prepend the address family as - * a four byte field. Cons up a dummy header - * to pacify bpf. This is safe because bpf - * will only read from the mbuf (i.e., it won't - * try to free it or keep a pointer to it). - */ - struct mbuf m; - u_int32_t af = AF_INET; - - m.m_next = top; - m.m_len = sizeof(af); - m.m_data = (char *)⁡ - - bpf_mtap(tunctl[unit].tun_bpf, &m); - } + if (ifp->if_bpf) + bpf_mtap(ifp->if_bpf, top); #endif + th = mtod( top, struct tunnel_header * ); + /* strip the tunnel header */ + top->m_data += sizeof(*th); + top->m_len -= sizeof(*th); + top->m_pkthdr.len -= sizeof(*th); + + switch( th->tun_af ) + { +#ifdef INET + case AF_INET: + ifq = &ipintrq; + isr = NETISR_IP; + break; +#endif +#ifdef NS + case AF_NS: + ifq = &nsintrq; + isr = NETISR_NS; + break; +#endif +#ifdef ISO + case AF_ISO: + ifq = &clnlintrq; + isr = NETISR_ISO; + break; +#endif + default: + m_freem(top); + splx(s); + return EAFNOSUPPORT; + } + s = splimp(); - if (IF_QFULL (&ipintrq)) { - IF_DROP(&ipintrq); + if( IF_QFULL(ifq) ) + { + IF_DROP( ifq ); splx(s); ifp->if_collisions++; m_freem(top); return ENOBUFS; } - IF_ENQUEUE(&ipintrq, top); - splx(s); + IF_ENQUEUE( ifq, top ); + schednetisr( isr ); ifp->if_ipackets++; - schednetisr(NETISR_IP); + ifp->if_ibytes += m->m_pkthdr.len; + splx(s); return error; } @@ -528,9 +572,10 @@ tunwrite(dev, uio) * anyway, it either accepts the packet or drops it. */ int -tunselect(dev, rw) - dev_t dev; +tunselect(dev, rw, p) + dev_t dev; int rw; + struct proc *p; { int unit = minor(dev), s; struct tun_softc *tp = &tunctl[unit]; diff --git a/sys/net/if_tun.h b/sys/net/if_tun.h index 116c10d60b7..22720e40075 100644 --- a/sys/net/if_tun.h +++ b/sys/net/if_tun.h @@ -1,4 +1,4 @@ -/* $NetBSD: if_tun.h,v 1.5 1994/06/29 06:36:27 cgd Exp $ */ +/* $OpenBSD: if_tun.h,v 1.2 1996/02/20 14:34:01 mickey Exp $ */ /* * Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk> @@ -13,7 +13,7 @@ * UCL. This driver is based much more on read/write/select mode of * operation though. * - * : $Header: if_tnreg.h,v 1.1.2.1 1992/07/16 22:39:16 friedl Exp + * from: @Header: if_tnreg.h,v 1.1.2.1 1992/07/16 22:39:16 friedl Exp */ #ifndef _NET_IF_TUN_H_ @@ -41,11 +41,26 @@ struct tun_softc { #endif }; +struct tunnel_header +{ + u_char tun_af; /* adress family */ +}; + /* Maximum packet size */ -#define TUNMTU 1500 +#define TUNMTU 3000 /* ioctl's for get/set debug */ -#define TUNSDEBUG _IOW('t', 90, int) -#define TUNGDEBUG _IOR('t', 89, int) +#define TUNSDEBUG _IOW('t', 89, int) +#define TUNGDEBUG _IOR('t', 90, int) + +/* iface info */ +struct tuninfo +{ + u_int mtu; + u_short type; + u_int baudrate; +}; +#define TUNSIFINFO _IOW('t', 91, struct tuninfo) +#define TUNGIFINFO _IOR('t', 92, struct tuninfo) #endif /* !_NET_IF_TUN_H_ */ |