mirror of
https://github.com/freebsd/freebsd-src.git
synced 2024-12-02 04:13:39 +00:00
Add the tap driver.
The tap driver is used to present a virtual Ethernet interface to the system. Packets presented by the network stack to the interface are made available to a character device in /dev. With tap and the bridge code, you can make remote bridge configurations where both sides of the bridge are separated by userland daemons. This driver also has a special naming hack to allow it to serve a similar purpose to the vmware port. Submitted by: myevmenkin@att.com, vsilyaev@mindspring.com
This commit is contained in:
parent
5f4796c0db
commit
a5213f145a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=63670
12
etc/MAKEDEV
12
etc/MAKEDEV
@ -128,6 +128,7 @@
|
||||
# gsc Genius GS-4500 hand scanner
|
||||
# joy pc joystick
|
||||
# tun* Tunneling IP device
|
||||
# tap* Ethernet Tunneling device
|
||||
# snp* tty snoop devices
|
||||
# spigot Video Spigot video acquisition card
|
||||
# ctx* Cortex-I video acquisition card
|
||||
@ -256,6 +257,7 @@ all)
|
||||
sh MAKEDEV urio0 # cdev, USB devices too
|
||||
sh MAKEDEV bpf0 bpf1 bpf2 bpf3 # cdev, network
|
||||
sh MAKEDEV ipl tun0 tun1 tun2 tun3 # cdev, network
|
||||
sh MAKEDEV tap0 tap1 tap2 tap3 # cdev, network
|
||||
sh MAKEDEV ch0 perfmon tw0 # cdev, miscellaneous
|
||||
sh MAKEDEV apm apmctl card0 card1 card2 card3 # cdev, laptop
|
||||
sh MAKEDEV pass4 xpt2 # cdev, CAM
|
||||
@ -290,6 +292,7 @@ fixit)
|
||||
sh MAKEDEV smb0 # cdev, SMBus device
|
||||
sh MAKEDEV ums0 # cdev, USB devices
|
||||
sh MAKEDEV tun0 # cdev, network
|
||||
sh MAKEDEV tap0 # cdev, network
|
||||
sh MAKEDEV ch0 # cdev, miscellaneous
|
||||
sh MAKEDEV apm apmctl card0 # cdev, laptop
|
||||
sh MAKEDEV pass1 xpt1 # cdev, CAM
|
||||
@ -1441,6 +1444,15 @@ tun*)
|
||||
done
|
||||
;;
|
||||
|
||||
tap*)
|
||||
ntap=`expr $i : 'tap\(.*\)$'`
|
||||
unit=0
|
||||
while [ $unit -le $ntap ]; do
|
||||
mknod tap$unit c 149 $unit root:network
|
||||
unit=$(($unit + 1))
|
||||
done
|
||||
;;
|
||||
|
||||
sysmouse)
|
||||
mknod sysmouse c 12 128
|
||||
mknod consolectl c 12 255
|
||||
|
217
share/man/man4/tap.4
Normal file
217
share/man/man4/tap.4
Normal file
@ -0,0 +1,217 @@
|
||||
.\" $FreeBSD$
|
||||
.\" Based on PR#2411
|
||||
.\"
|
||||
.Dd July 9, 2000
|
||||
.Os
|
||||
.Dt TAP 4
|
||||
.Sh NAME
|
||||
.Nm tap
|
||||
.Nd Ethernet tunnel software network interface
|
||||
.Sh SYNOPSIS
|
||||
.Cd pseudo-device tap
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm tap
|
||||
interface is a software loopback mechanism that can be loosely
|
||||
described as the network interface analog of the
|
||||
.Xr pty 4 ,
|
||||
that is,
|
||||
.Nm tap
|
||||
does for network interfaces what the
|
||||
.Nm pty
|
||||
driver does for terminals.
|
||||
.Pp
|
||||
The
|
||||
.Nm tap
|
||||
driver, like the
|
||||
.Nm pty
|
||||
driver, provides two interfaces: an interface like the usual facility
|
||||
it is simulating
|
||||
.Po
|
||||
an Ethernet network interface in the case of
|
||||
.Nm tap ,
|
||||
or a terminal for
|
||||
.Nm pty
|
||||
.Pc ,
|
||||
and a character-special device
|
||||
.Dq control
|
||||
interface.
|
||||
.Pp
|
||||
The network interfaces are named
|
||||
.Sy tap Ns Ar 0 ,
|
||||
.Sy tap Ns Ar 1 ,
|
||||
etc, as many as were made by
|
||||
.Xr MAKEDEV 8 .
|
||||
Each one supports the usual Ethernet network-interface
|
||||
.Xr ioctl 2 Ns s ,
|
||||
such as
|
||||
.Dv SIOCSIFADDR
|
||||
and
|
||||
.Dv SIOCSIFNETMASK ,
|
||||
and thus can be used with
|
||||
.Xr ifconfig 8
|
||||
like any other Ethernet interface. When the system chooses to transmit
|
||||
an Ethernet frame on the network interface, the frame can be read from
|
||||
the control device
|
||||
.Po
|
||||
it appears as
|
||||
.Dq input
|
||||
there
|
||||
.Pc ;
|
||||
writing an Ethernet frame to the control device generates an input frame on
|
||||
the network interface, as if the
|
||||
.Pq non-existent
|
||||
hardware had just received it.
|
||||
.Pp
|
||||
The Ethernet tunnel device, normally
|
||||
.Pa /dev/tap Ns Sy N ,
|
||||
is exclusive-open
|
||||
.Po
|
||||
it cannot be opened if it is already open
|
||||
.Pc
|
||||
and is restricted to the super-user.
|
||||
A
|
||||
.Fn read
|
||||
call will return an error
|
||||
.Pq Er EHOSTDOWN
|
||||
if the interface is not
|
||||
.Dq ready .
|
||||
Once the interface is ready,
|
||||
.Fn read
|
||||
will return an Ethernet frame if one is available; if not, it will
|
||||
either block until one is or return
|
||||
.Er EWOULDBLOCK ,
|
||||
depending on whether non-blocking I/O has been enabled. If the frame
|
||||
is longer than is allowed for in the buffer passed to
|
||||
.Fn read ,
|
||||
the extra data will be silently dropped.
|
||||
.Pp
|
||||
A
|
||||
.Xr write 2
|
||||
call passes an Ethernet frame in to be
|
||||
.Dq received
|
||||
on the pseudo-interface. Each
|
||||
.Fn write
|
||||
call supplies exactly one frame; the frame length is taken from the
|
||||
amount of data provided to
|
||||
.Fn write .
|
||||
Writes will not block; if the frame cannot be accepted
|
||||
for a transient reason
|
||||
.Pq e.g., no buffer space available ,
|
||||
it is silently dropped; if the reason is not transient
|
||||
.Pq e.g., frame too large ,
|
||||
an error is returned.
|
||||
The following
|
||||
.Xr ioctl 2
|
||||
calls are supported
|
||||
.Pq defined in Aq Pa net/if_tap.h Ns :
|
||||
.Bl -tag -width VMIO_SIOCSETMACADDR
|
||||
.It Dv TAPSDEBUG
|
||||
The argument should be a pointer to an
|
||||
.Va int ;
|
||||
this sets the internal debugging variable to that value. What, if
|
||||
anything, this variable controls is not documented here; see the source
|
||||
code.
|
||||
.It Dv TAPGDEBUG
|
||||
The argument should be a pointer to an
|
||||
.Va int ;
|
||||
this stores the internal debugging variable's value into it.
|
||||
.It Dv FIONBIO
|
||||
Turn non-blocking I/O for reads off or on, according as the argument
|
||||
.Va int Ns 's
|
||||
value is or isn't zero
|
||||
.Pq Writes are always nonblocking .
|
||||
.It Dv FIOASYNC
|
||||
Turn asynchronous I/O for reads
|
||||
.Po
|
||||
i.e., generation of
|
||||
.Dv SIGIO
|
||||
when data is available to be read
|
||||
.Pc
|
||||
off or on, according as the argument
|
||||
.Va int Ns 's
|
||||
value is or isn't zero.
|
||||
.It Dv FIONREAD
|
||||
If any frames are queued to be read, store the size of the first one into the argument
|
||||
.Va int ;
|
||||
otherwise, store zero.
|
||||
.It Dv TIOCSPGRP
|
||||
Set the process group to receive
|
||||
.Dv SIGIO
|
||||
signals, when asynchronous I/O is enabled, to the argument
|
||||
.Va int
|
||||
value.
|
||||
.It Dv TIOCGPGRP
|
||||
Retrieve the process group value for
|
||||
.Dv SIGIO
|
||||
signals into the argument
|
||||
.Va int
|
||||
value.
|
||||
.It SIOCGIFADDR
|
||||
Retrieve the Media Access Control
|
||||
.Pq MAC
|
||||
address. This command should be executed on descriptor, associated with
|
||||
control device
|
||||
.Pq Pa /dev/tap Ns Sy N .
|
||||
The
|
||||
.Va buffer ,
|
||||
which is passed as argument, is expected to have enought space to store
|
||||
.Pq MAC
|
||||
address.
|
||||
.It SIOCSIFADDR
|
||||
Set the Media Access Control
|
||||
.Pq MAC
|
||||
address. This command should be executed on a descriptor, associated with
|
||||
control device
|
||||
.Pq Pa /dev/tap Ns Sy N .
|
||||
.El
|
||||
.Pp
|
||||
The control device also supports
|
||||
.Xr select 2
|
||||
for read; selecting for write is pointless, and always succeeds, since
|
||||
writes are always non-blocking.
|
||||
.Pp
|
||||
On the last close of the data device, by default, the interface is
|
||||
brought down
|
||||
.Po
|
||||
as if with
|
||||
.Dq ifconfig tap Ns Sy N No down
|
||||
.Pc .
|
||||
All queued frames are thrown away. If the interface is up when the data
|
||||
device is not open output frames are always thrown away rather than
|
||||
letting them pile up.
|
||||
.Pp
|
||||
The
|
||||
.Nm tap
|
||||
device is also can be used with VMware port as a replacement
|
||||
of VMnet device driver. The driver uses minor number to select between
|
||||
.Nm tap
|
||||
and
|
||||
.Nm vmnet
|
||||
devices. VMnet minor numbering is
|
||||
.Va 0x10000
|
||||
+
|
||||
.Va N .
|
||||
Where
|
||||
.Va N
|
||||
is a VMnet unit number. In this case control device is expected to be
|
||||
.Pa /dev/vmnet Ns Sy N ,
|
||||
and network interface will be
|
||||
.Sy vmnet Ns Ar N .
|
||||
Everything else is the same.
|
||||
.Pp
|
||||
In addition to mentioned above
|
||||
.Xr ioctl 2
|
||||
there are additional one for VMware port.
|
||||
.Bl -tag -width VMIO_SIOCSETMACADDR
|
||||
.It VMIO_SIOCSIFFLAGS
|
||||
VMware
|
||||
.Dv SIOCSIFFLAGS .
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr inet 4 ,
|
||||
.Xr intro 4
|
||||
.\" .Sh BUGS
|
||||
.Sh AUTHORS
|
||||
This man page has been obtained from
|
||||
.Bx Free .
|
@ -581,6 +581,7 @@ net/if_sl.c optional sl
|
||||
net/if_spppsubr.c optional sppp
|
||||
net/if_stf.c count stf
|
||||
net/if_tun.c optional tun
|
||||
net/if_tap.c optional tap
|
||||
net/if_vlan.c count vlan
|
||||
net/intrq.c standard
|
||||
net/net_osdep.c standard
|
||||
|
785
sys/net/if_tap.c
Normal file
785
sys/net/if_tap.c
Normal file
@ -0,0 +1,785 @@
|
||||
/*
|
||||
* Copyright (C) 1999-2000 by Maksim Yevmenkin <m_evmenkin@yahoo.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* BASED ON:
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk>
|
||||
* Nottingham University 1987.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $FreeBSD$
|
||||
* $Id: if_tap.c,v 0.19 2000/07/20 02:32:27 max Exp $
|
||||
*/
|
||||
|
||||
#include "opt_inet.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/filedesc.h>
|
||||
#include <sys/filio.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/signalvar.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/ttycom.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/vnode.h>
|
||||
|
||||
#include <net/bpf.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_arp.h>
|
||||
#include <net/route.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <net/if_tapvar.h>
|
||||
#include <net/if_tap.h>
|
||||
|
||||
|
||||
#define CDEV_NAME "tap"
|
||||
#define CDEV_MAJOR 149
|
||||
#define TAPDEBUG if (tapdebug) printf
|
||||
|
||||
#define TAP "tap"
|
||||
#define VMNET "vmnet"
|
||||
#define VMNET_DEV_MASK 0x00010000
|
||||
|
||||
/* module */
|
||||
static int tapmodevent __P((module_t, int, void *));
|
||||
|
||||
/* device */
|
||||
static void tapcreate __P((dev_t));
|
||||
|
||||
/* network interface */
|
||||
static void tapifstart __P((struct ifnet *));
|
||||
static int tapifioctl __P((struct ifnet *, u_long, caddr_t));
|
||||
static void tapifinit __P((void *));
|
||||
|
||||
/* character device */
|
||||
static d_open_t tapopen;
|
||||
static d_close_t tapclose;
|
||||
static d_read_t tapread;
|
||||
static d_write_t tapwrite;
|
||||
static d_ioctl_t tapioctl;
|
||||
static d_poll_t tappoll;
|
||||
|
||||
static struct cdevsw tap_cdevsw = {
|
||||
/* open */ tapopen,
|
||||
/* close */ tapclose,
|
||||
/* read */ tapread,
|
||||
/* write */ tapwrite,
|
||||
/* ioctl */ tapioctl,
|
||||
/* poll */ tappoll,
|
||||
/* mmap */ nommap,
|
||||
/* startegy */ nostrategy,
|
||||
/* dev name */ CDEV_NAME,
|
||||
/* dev major */ CDEV_MAJOR,
|
||||
/* dump */ nodump,
|
||||
/* psize */ nopsize,
|
||||
/* flags */ 0,
|
||||
/* bmaj */ -1
|
||||
};
|
||||
|
||||
static int taprefcnt = 0; /* module ref. counter */
|
||||
static int taplastunit = -1; /* max. open unit number */
|
||||
static int tapdebug = 0; /* debug flag */
|
||||
|
||||
MALLOC_DECLARE(M_TAP);
|
||||
MALLOC_DEFINE(M_TAP, CDEV_NAME, "Ethernet tunnel interface");
|
||||
SYSCTL_INT(_debug, OID_AUTO, if_tap_debug, CTLFLAG_RW, &tapdebug, 0, "");
|
||||
DEV_MODULE(if_tap, tapmodevent, NULL);
|
||||
|
||||
/*
|
||||
* tapmodevent
|
||||
*
|
||||
* module event handler
|
||||
*/
|
||||
static int
|
||||
tapmodevent(mod, type, data)
|
||||
module_t mod;
|
||||
int type;
|
||||
void *data;
|
||||
{
|
||||
static int attached = 0;
|
||||
struct ifnet *ifp = NULL;
|
||||
int unit, s;
|
||||
|
||||
switch (type) {
|
||||
case MOD_LOAD:
|
||||
if (attached)
|
||||
return (EEXIST);
|
||||
|
||||
cdevsw_add(&tap_cdevsw);
|
||||
attached = 1;
|
||||
break;
|
||||
|
||||
case MOD_UNLOAD:
|
||||
if (taprefcnt > 0)
|
||||
return (EBUSY);
|
||||
|
||||
cdevsw_remove(&tap_cdevsw);
|
||||
|
||||
unit = 0;
|
||||
while (unit <= taplastunit) {
|
||||
s = splimp();
|
||||
TAILQ_FOREACH(ifp, &ifnet, if_link)
|
||||
if ((strcmp(ifp->if_name, TAP) == 0) ||
|
||||
(strcmp(ifp->if_name, VMNET) == 0))
|
||||
if (ifp->if_unit == unit)
|
||||
break;
|
||||
splx(s);
|
||||
|
||||
if (ifp != NULL) {
|
||||
struct tap_softc *tp = ifp->if_softc;
|
||||
|
||||
TAPDEBUG("detaching %s%d. taplastunit = %d\n",
|
||||
ifp->if_name, unit, taplastunit);
|
||||
|
||||
ether_ifdetach(ifp, 1);
|
||||
destroy_dev(tp->tap_dev);
|
||||
FREE(tp, M_TAP);
|
||||
}
|
||||
else
|
||||
unit ++;
|
||||
}
|
||||
|
||||
attached = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
return (0);
|
||||
} /* tapmodevent */
|
||||
|
||||
|
||||
/*
|
||||
* tapcreate
|
||||
*
|
||||
* to create interface
|
||||
*/
|
||||
static void
|
||||
tapcreate(dev)
|
||||
dev_t dev;
|
||||
{
|
||||
struct ifnet *ifp = NULL;
|
||||
struct tap_softc *tp = NULL;
|
||||
unsigned short macaddr_hi;
|
||||
int unit;
|
||||
char *name = NULL;
|
||||
|
||||
/* allocate driver storage and create device */
|
||||
MALLOC(tp, struct tap_softc *, sizeof(*tp), M_TAP, M_WAITOK);
|
||||
bzero(tp, sizeof(*tp));
|
||||
|
||||
/* select device: tap or vmnet */
|
||||
if (minor(dev) & VMNET_DEV_MASK) {
|
||||
name = VMNET;
|
||||
unit = lminor(dev) & 0xff;
|
||||
}
|
||||
else {
|
||||
name = TAP;
|
||||
unit = lminor(dev);
|
||||
}
|
||||
|
||||
tp->tap_dev = make_dev(&tap_cdevsw, minor(dev), UID_UUCP, GID_DIALER,
|
||||
0600, "%s%d", name, unit);
|
||||
tp->tap_dev->si_drv1 = dev->si_drv1 = tp;
|
||||
|
||||
/* generate fake MAC address: 00 bd xx xx xx unit_no */
|
||||
macaddr_hi = htons(0x00bd);
|
||||
bcopy(&macaddr_hi, &tp->arpcom.ac_enaddr[0], sizeof(short));
|
||||
bcopy(&ticks, &tp->arpcom.ac_enaddr[2], sizeof(long));
|
||||
tp->arpcom.ac_enaddr[5] = (u_char)unit;
|
||||
|
||||
/* fill the rest and attach interface */
|
||||
ifp = &tp->tap_if;
|
||||
ifp->if_softc = tp;
|
||||
|
||||
ifp->if_unit = unit;
|
||||
if (unit > taplastunit)
|
||||
taplastunit = unit;
|
||||
|
||||
ifp->if_name = name;
|
||||
ifp->if_init = tapifinit;
|
||||
ifp->if_output = ether_output;
|
||||
ifp->if_start = tapifstart;
|
||||
ifp->if_ioctl = tapifioctl;
|
||||
ifp->if_mtu = ETHERMTU;
|
||||
ifp->if_flags = (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST);
|
||||
ifp->if_snd.ifq_maxlen = ifqmaxlen;
|
||||
|
||||
ether_ifattach(ifp, 1);
|
||||
|
||||
tp->tap_flags = TAP_INITED;
|
||||
} /* tapcreate */
|
||||
|
||||
|
||||
/*
|
||||
* tapopen
|
||||
*
|
||||
* to open tunnel. must be superuser
|
||||
*/
|
||||
static int
|
||||
tapopen(dev, flag, mode, p)
|
||||
dev_t dev;
|
||||
int flag;
|
||||
int mode;
|
||||
struct proc *p;
|
||||
{
|
||||
struct tap_softc *tp = NULL;
|
||||
int error;
|
||||
|
||||
if ((error = suser(p)) != 0)
|
||||
return (error);
|
||||
|
||||
tp = dev->si_drv1;
|
||||
if (tp == NULL) {
|
||||
tapcreate(dev);
|
||||
tp = dev->si_drv1;
|
||||
}
|
||||
|
||||
if (tp->tap_flags & TAP_OPEN)
|
||||
return (EBUSY);
|
||||
|
||||
tp->tap_pid = p->p_pid;
|
||||
tp->tap_flags |= TAP_OPEN;
|
||||
taprefcnt ++;
|
||||
|
||||
TAPDEBUG("%s%d is open. refcnt = %d, taplastunit = %d\n",
|
||||
tp->tap_if.if_name, tp->tap_if.if_unit, taprefcnt, taplastunit);
|
||||
|
||||
return (0);
|
||||
} /* tapopen */
|
||||
|
||||
|
||||
/*
|
||||
* tapclose
|
||||
*
|
||||
* close the device - mark i/f down & delete routing info
|
||||
*/
|
||||
static int
|
||||
tapclose(dev, foo, bar, p)
|
||||
dev_t dev;
|
||||
int foo;
|
||||
int bar;
|
||||
struct proc *p;
|
||||
{
|
||||
int s;
|
||||
struct tap_softc *tp = dev->si_drv1;
|
||||
struct ifnet *ifp = &tp->tap_if;
|
||||
struct mbuf *m = NULL;
|
||||
|
||||
/* junk all pending output */
|
||||
|
||||
s = splimp();
|
||||
do {
|
||||
IF_DEQUEUE(&ifp->if_snd, m);
|
||||
if (m != NULL)
|
||||
m_freem(m);
|
||||
} while (m != NULL);
|
||||
splx(s);
|
||||
|
||||
if (ifp->if_flags & IFF_UP) {
|
||||
s = splimp();
|
||||
if_down(ifp);
|
||||
if (ifp->if_flags & IFF_RUNNING) {
|
||||
/* find internet addresses and delete routes */
|
||||
struct ifaddr *ifa = NULL;
|
||||
|
||||
for (ifa = ifp->if_addrhead.tqh_first; ifa;
|
||||
ifa = ifa->ifa_link.tqe_next) {
|
||||
if (ifa->ifa_addr->sa_family == AF_INET) {
|
||||
rtinit(ifa, (int)RTM_DELETE, 0);
|
||||
|
||||
/* remove address from interface */
|
||||
bzero(ifa->ifa_addr,
|
||||
sizeof(*(ifa->ifa_addr)));
|
||||
bzero(ifa->ifa_dstaddr,
|
||||
sizeof(*(ifa->ifa_dstaddr)));
|
||||
bzero(ifa->ifa_netmask,
|
||||
sizeof(*(ifa->ifa_netmask)));
|
||||
}
|
||||
}
|
||||
|
||||
ifp->if_flags &= ~IFF_RUNNING;
|
||||
}
|
||||
splx(s);
|
||||
}
|
||||
|
||||
funsetown(tp->tap_sigio);
|
||||
selwakeup(&tp->tap_rsel);
|
||||
|
||||
tp->tap_flags &= ~TAP_OPEN;
|
||||
tp->tap_pid = 0;
|
||||
|
||||
taprefcnt --;
|
||||
if (taprefcnt < 0) {
|
||||
taprefcnt = 0;
|
||||
printf("%s%d refcnt = %d is out of sync. set refcnt to 0\n",
|
||||
ifp->if_name, ifp->if_unit, taprefcnt);
|
||||
}
|
||||
|
||||
TAPDEBUG("%s%d is closed. refcnt = %d, taplastunit = %d\n",
|
||||
ifp->if_name, ifp->if_unit, taprefcnt, taplastunit);
|
||||
|
||||
return (0);
|
||||
} /* tapclose */
|
||||
|
||||
|
||||
/*
|
||||
* tapifinit
|
||||
*
|
||||
* network interface initialization function
|
||||
*/
|
||||
static void
|
||||
tapifinit(xtp)
|
||||
void *xtp;
|
||||
{
|
||||
struct tap_softc *tp = (struct tap_softc *)xtp;
|
||||
struct ifnet *ifp = &tp->tap_if;
|
||||
|
||||
TAPDEBUG("initializing %s%d\n", ifp->if_name, ifp->if_unit);
|
||||
|
||||
ifp->if_flags |= IFF_RUNNING;
|
||||
ifp->if_flags &= ~IFF_OACTIVE;
|
||||
|
||||
/* attempt to start output */
|
||||
tapifstart(ifp);
|
||||
} /* tapifinit */
|
||||
|
||||
|
||||
/*
|
||||
* tapifioctl
|
||||
*
|
||||
* Process an ioctl request on network interface
|
||||
*/
|
||||
int
|
||||
tapifioctl(ifp, cmd, data)
|
||||
struct ifnet *ifp;
|
||||
u_long cmd;
|
||||
caddr_t data;
|
||||
{
|
||||
struct tap_softc *tp = (struct tap_softc *)(ifp->if_softc);
|
||||
struct ifstat *ifs = NULL;
|
||||
int s, dummy;
|
||||
|
||||
switch (cmd) {
|
||||
case SIOCSIFADDR:
|
||||
case SIOCGIFADDR:
|
||||
case SIOCSIFMTU:
|
||||
s = splimp();
|
||||
dummy = ether_ioctl(ifp, cmd, data);
|
||||
splx(s);
|
||||
return (dummy);
|
||||
|
||||
case SIOCSIFFLAGS: /* XXX -- just like vmnet does */
|
||||
case SIOCADDMULTI:
|
||||
case SIOCDELMULTI:
|
||||
break;
|
||||
|
||||
case SIOCGIFSTATUS:
|
||||
s = splimp();
|
||||
ifs = (struct ifstat *)data;
|
||||
dummy = strlen(ifs->ascii);
|
||||
if (tp->tap_pid != 0 && dummy < sizeof(ifs->ascii))
|
||||
snprintf(ifs->ascii + dummy,
|
||||
sizeof(ifs->ascii) - dummy,
|
||||
"\tOpened by PID %d\n", tp->tap_pid);
|
||||
splx(s);
|
||||
break;
|
||||
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
return (0);
|
||||
} /* tapifioctl */
|
||||
|
||||
|
||||
/*
|
||||
* tapifstart
|
||||
*
|
||||
* queue packets from higher level ready to put out
|
||||
*/
|
||||
static void
|
||||
tapifstart(ifp)
|
||||
struct ifnet *ifp;
|
||||
{
|
||||
struct tap_softc *tp = ifp->if_softc;
|
||||
int s;
|
||||
|
||||
TAPDEBUG("%s%d starting\n", ifp->if_name, ifp->if_unit);
|
||||
|
||||
if ((tp->tap_flags & TAP_READY) != TAP_READY) {
|
||||
struct mbuf *m = NULL;
|
||||
|
||||
TAPDEBUG("%s%d not ready. tap_flags = 0x%x\n",
|
||||
ifp->if_name, ifp->if_unit, tp->tap_flags);
|
||||
|
||||
s = splimp();
|
||||
do {
|
||||
IF_DEQUEUE(&ifp->if_snd, m);
|
||||
if (m != NULL)
|
||||
m_freem(m);
|
||||
ifp->if_oerrors ++;
|
||||
} while (m != NULL);
|
||||
splx(s);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
s = splimp();
|
||||
ifp->if_flags |= IFF_OACTIVE;
|
||||
|
||||
if (ifp->if_snd.ifq_len != 0) {
|
||||
if (tp->tap_flags & TAP_RWAIT) {
|
||||
tp->tap_flags &= ~TAP_RWAIT;
|
||||
wakeup((caddr_t)tp);
|
||||
}
|
||||
|
||||
if ((tp->tap_flags & TAP_ASYNC) && (tp->tap_sigio != NULL))
|
||||
pgsigio(tp->tap_sigio, SIGIO, 0);
|
||||
|
||||
selwakeup(&tp->tap_rsel);
|
||||
ifp->if_opackets ++; /* obytes are counted in ether_output */
|
||||
}
|
||||
|
||||
ifp->if_flags &= ~IFF_OACTIVE;
|
||||
splx(s);
|
||||
} /* tapifstart */
|
||||
|
||||
|
||||
/*
|
||||
* tapioctl
|
||||
*
|
||||
* the cdevsw interface is now pretty minimal
|
||||
*/
|
||||
static int
|
||||
tapioctl(dev, cmd, data, flag, p)
|
||||
dev_t dev;
|
||||
u_long cmd;
|
||||
caddr_t data;
|
||||
int flag;
|
||||
struct proc *p;
|
||||
{
|
||||
struct tap_softc *tp = dev->si_drv1;
|
||||
struct ifnet *ifp = &tp->tap_if;
|
||||
struct tapinfo *tapp = NULL;
|
||||
int s;
|
||||
|
||||
switch (cmd) {
|
||||
case TAPSIFINFO:
|
||||
s = splimp();
|
||||
tapp = (struct tapinfo *)data;
|
||||
ifp->if_mtu = tapp->mtu;
|
||||
ifp->if_type = tapp->type;
|
||||
ifp->if_baudrate = tapp->baudrate;
|
||||
splx(s);
|
||||
break;
|
||||
|
||||
case TAPGIFINFO:
|
||||
tapp = (struct tapinfo *)data;
|
||||
tapp->mtu = ifp->if_mtu;
|
||||
tapp->type = ifp->if_type;
|
||||
tapp->baudrate = ifp->if_baudrate;
|
||||
break;
|
||||
|
||||
case TAPSDEBUG:
|
||||
tapdebug = *(int *)data;
|
||||
break;
|
||||
|
||||
case TAPGDEBUG:
|
||||
*(int *)data = tapdebug;
|
||||
break;
|
||||
|
||||
case FIONBIO:
|
||||
break;
|
||||
|
||||
case FIOASYNC:
|
||||
if (*(int *)data)
|
||||
tp->tap_flags |= TAP_ASYNC;
|
||||
else
|
||||
tp->tap_flags &= ~TAP_ASYNC;
|
||||
break;
|
||||
|
||||
case FIONREAD:
|
||||
s = splimp();
|
||||
if (ifp->if_snd.ifq_head) {
|
||||
struct mbuf *mb = ifp->if_snd.ifq_head;
|
||||
|
||||
for(*(int *)data = 0; mb != 0; mb = mb->m_next)
|
||||
*(int *)data += mb->m_len;
|
||||
}
|
||||
else
|
||||
*(int *)data = 0;
|
||||
splx(s);
|
||||
break;
|
||||
|
||||
case FIOSETOWN:
|
||||
return (fsetown(*(int *)data, &tp->tap_sigio));
|
||||
|
||||
case FIOGETOWN:
|
||||
*(int *)data = fgetown(tp->tap_sigio);
|
||||
return (0);
|
||||
|
||||
/* this is deprecated, FIOSETOWN should be used instead */
|
||||
case TIOCSPGRP:
|
||||
return (fsetown(-(*(int *)data), &tp->tap_sigio));
|
||||
|
||||
/* this is deprecated, FIOGETOWN should be used instead */
|
||||
case TIOCGPGRP:
|
||||
*(int *)data = -fgetown(tp->tap_sigio);
|
||||
return (0);
|
||||
|
||||
/* VMware/VMnet port ioctl's */
|
||||
|
||||
case SIOCGIFFLAGS: /* get ifnet flags */
|
||||
bcopy(&ifp->if_flags, data, sizeof(ifp->if_flags));
|
||||
break;
|
||||
|
||||
case VMIO_SIOCSIFFLAGS: { /* VMware/VMnet SIOCSIFFLAGS */
|
||||
short f = *(short *)data;
|
||||
|
||||
f &= 0x0fff;
|
||||
f &= ~IFF_CANTCHANGE;
|
||||
f |= IFF_UP;
|
||||
|
||||
s = splimp();
|
||||
ifp->if_flags = f | (ifp->if_flags & IFF_CANTCHANGE);
|
||||
splx(s);
|
||||
} break;
|
||||
|
||||
case OSIOCGIFADDR: /* get MAC address */
|
||||
case SIOCGIFADDR:
|
||||
bcopy(tp->arpcom.ac_enaddr, data, ETHER_ADDR_LEN);
|
||||
break;
|
||||
|
||||
case SIOCSIFADDR: /* set MAC address */
|
||||
s = splimp();
|
||||
bcopy(data, tp->arpcom.ac_enaddr, ETHER_ADDR_LEN);
|
||||
splx(s);
|
||||
break;
|
||||
|
||||
default:
|
||||
return (ENOTTY);
|
||||
}
|
||||
return (0);
|
||||
} /* tapioctl */
|
||||
|
||||
|
||||
/*
|
||||
* tapread
|
||||
*
|
||||
* the cdevsw read interface - reads a packet at a time, or at
|
||||
* least as much of a packet as can be read
|
||||
*/
|
||||
static int
|
||||
tapread(dev, uio, flag)
|
||||
dev_t dev;
|
||||
struct uio *uio;
|
||||
int flag;
|
||||
{
|
||||
struct tap_softc *tp = dev->si_drv1;
|
||||
struct ifnet *ifp = &tp->tap_if;
|
||||
struct mbuf *m = NULL, *m0 = NULL;
|
||||
int error = 0, len, s;
|
||||
|
||||
TAPDEBUG("%s%d reading\n", ifp->if_name, ifp->if_unit);
|
||||
|
||||
if ((tp->tap_flags & TAP_READY) != TAP_READY) {
|
||||
TAPDEBUG("%s%d not ready. tap_flags = 0x%x\n",
|
||||
ifp->if_name, ifp->if_unit, tp->tap_flags);
|
||||
return (EHOSTDOWN);
|
||||
}
|
||||
|
||||
tp->tap_flags &= ~TAP_RWAIT;
|
||||
|
||||
/* sleep until we get a packet */
|
||||
do {
|
||||
s = splimp();
|
||||
IF_DEQUEUE(&ifp->if_snd, m0);
|
||||
splx(s);
|
||||
|
||||
if (m0 == NULL) {
|
||||
if (flag & IO_NDELAY)
|
||||
return (EWOULDBLOCK);
|
||||
|
||||
tp->tap_flags |= TAP_RWAIT;
|
||||
error = tsleep((caddr_t)tp,PCATCH|(PZERO+1),"taprd",0);
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
} while (m0 == 0);
|
||||
|
||||
/* feed packet to bpf */
|
||||
if (ifp->if_bpf != NULL)
|
||||
bpf_mtap(ifp, m0);
|
||||
|
||||
/* xfer packet to user space */
|
||||
while ((m0 != NULL) && (uio->uio_resid > 0) && (error == 0)) {
|
||||
len = min(uio->uio_resid, m0->m_len);
|
||||
if (len == 0)
|
||||
break;
|
||||
|
||||
error = uiomove(mtod(m0, caddr_t), len, uio);
|
||||
MFREE(m0, m);
|
||||
m0 = m;
|
||||
}
|
||||
|
||||
if (m0 != NULL) {
|
||||
TAPDEBUG("%s%d dropping mbuf\n", ifp->if_name, ifp->if_unit);
|
||||
m_freem(m0);
|
||||
}
|
||||
|
||||
return (error);
|
||||
} /* tapread */
|
||||
|
||||
|
||||
/*
|
||||
* tapwrite
|
||||
*
|
||||
* the cdevsw write interface - an atomic write is a packet - or else!
|
||||
*/
|
||||
static int
|
||||
tapwrite(dev, uio, flag)
|
||||
dev_t dev;
|
||||
struct uio *uio;
|
||||
int flag;
|
||||
{
|
||||
struct tap_softc *tp = dev->si_drv1;
|
||||
struct ifnet *ifp = &tp->tap_if;
|
||||
struct mbuf *top = NULL, **mp = NULL, *m = NULL;
|
||||
struct ether_header *eh = NULL;
|
||||
int error = 0, tlen, mlen;
|
||||
|
||||
TAPDEBUG("%s%d writting\n", ifp->if_name, ifp->if_unit);
|
||||
|
||||
if (uio->uio_resid == 0)
|
||||
return (0);
|
||||
|
||||
if ((uio->uio_resid < 0) || (uio->uio_resid > TAPMRU)) {
|
||||
TAPDEBUG("%s%d invalid packet len = %d\n",
|
||||
ifp->if_name, ifp->if_unit, uio->uio_resid);
|
||||
return (EIO);
|
||||
}
|
||||
tlen = uio->uio_resid;
|
||||
|
||||
/* get a header mbuf */
|
||||
MGETHDR(m, M_DONTWAIT, MT_DATA);
|
||||
if (m == NULL)
|
||||
return (ENOBUFS);
|
||||
mlen = MHLEN;
|
||||
|
||||
top = 0;
|
||||
mp = ⊤
|
||||
while ((error == 0) && (uio->uio_resid > 0)) {
|
||||
m->m_len = min(mlen, uio->uio_resid);
|
||||
error = uiomove(mtod(m, caddr_t), m->m_len, uio);
|
||||
*mp = m;
|
||||
mp = &m->m_next;
|
||||
if (uio->uio_resid > 0) {
|
||||
MGET(m, M_DONTWAIT, MT_DATA);
|
||||
if (m == 0) {
|
||||
error = ENOBUFS;
|
||||
break;
|
||||
}
|
||||
mlen = MLEN;
|
||||
}
|
||||
}
|
||||
if (error) {
|
||||
ifp->if_ierrors ++;
|
||||
if (top)
|
||||
m_freem(top);
|
||||
return (error);
|
||||
}
|
||||
|
||||
top->m_pkthdr.len = tlen;
|
||||
top->m_pkthdr.rcvif = ifp;
|
||||
|
||||
/*
|
||||
* Ethernet bridge and bpf are handled in ether_input
|
||||
*
|
||||
* adjust mbuf and give packet to the ether_input
|
||||
*/
|
||||
|
||||
eh = mtod(top, struct ether_header *);
|
||||
m_adj(top, sizeof(struct ether_header));
|
||||
ether_input(ifp, eh, top);
|
||||
ifp->if_ipackets ++; /* ibytes are counted in ether_input */
|
||||
|
||||
return (0);
|
||||
} /* tapwrite */
|
||||
|
||||
|
||||
/*
|
||||
* tappoll
|
||||
*
|
||||
* the poll interface, this is only useful on reads
|
||||
* really. the write detect always returns true, write never blocks
|
||||
* anyway, it either accepts the packet or drops it
|
||||
*/
|
||||
static int
|
||||
tappoll(dev, events, p)
|
||||
dev_t dev;
|
||||
int events;
|
||||
struct proc *p;
|
||||
{
|
||||
struct tap_softc *tp = dev->si_drv1;
|
||||
struct ifnet *ifp = &tp->tap_if;
|
||||
int s, revents = 0;
|
||||
|
||||
TAPDEBUG("%s%d polling\n", ifp->if_name, ifp->if_unit);
|
||||
|
||||
s = splimp();
|
||||
if (events & (POLLIN | POLLRDNORM)) {
|
||||
if (ifp->if_snd.ifq_len > 0) {
|
||||
TAPDEBUG("%s%d have data in queue. len = %d\n",
|
||||
ifp->if_name,ifp->if_unit, ifp->if_snd.ifq_len);
|
||||
revents |= (events & (POLLIN | POLLRDNORM));
|
||||
}
|
||||
else {
|
||||
TAPDEBUG("%s%d waiting for data\n",
|
||||
ifp->if_name, ifp->if_unit);
|
||||
selrecord(p, &tp->tap_rsel);
|
||||
}
|
||||
}
|
||||
|
||||
if (events & (POLLOUT | POLLWRNORM))
|
||||
revents |= (events & (POLLOUT | POLLWRNORM));
|
||||
|
||||
splx(s);
|
||||
return (revents);
|
||||
} /* tappoll */
|
73
sys/net/if_tap.h
Normal file
73
sys/net/if_tap.h
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (C) 1999-2000 by Maksim Yevmenkin <m_evmenkin@yahoo.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* BASED ON:
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk>
|
||||
* Nottingham University 1987.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $FreeBSD$
|
||||
* $Id: if_tap.h,v 0.7 2000/07/12 04:12:51 max Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NET_IF_TAP_H_
|
||||
#define _NET_IF_TAP_H_
|
||||
|
||||
/* refer to if_tapvar.h for the softc stuff */
|
||||
|
||||
/* maximum receive packet size (hard limit) */
|
||||
#define TAPMRU 16384
|
||||
|
||||
struct tapinfo {
|
||||
int baudrate; /* linespeed */
|
||||
short mtu; /* maximum transmission unit */
|
||||
u_char type; /* ethernet, tokenring, etc. */
|
||||
u_char dummy; /* place holder */
|
||||
};
|
||||
|
||||
/* ioctl's for get/set debug */
|
||||
#define TAPSDEBUG _IOW('t', 90, int)
|
||||
#define TAPGDEBUG _IOR('t', 89, int)
|
||||
#define TAPSIFINFO _IOW('t', 91, struct tapinfo)
|
||||
#define TAPGIFINFO _IOR('t', 92, struct tapinfo)
|
||||
|
||||
/* VMware ioctl's */
|
||||
#define VMIO_SIOCSIFFLAGS _IO('V', 0)
|
||||
#define VMIO_SIOCSKEEP _IO('V', 1)
|
||||
#define VMIO_SIOCSIFBR _IO('V', 2)
|
||||
#define VMIO_SIOCSLADRF _IO('V', 3)
|
||||
|
||||
/* XXX -- unimplemented */
|
||||
#define VMIO_SIOCSETMACADDR _IO('V', 4)
|
||||
|
||||
/* XXX -- not used? */
|
||||
#define VMIO_SIOCPORT _IO('V', 5)
|
||||
#define VMIO_SIOCBRIDGE _IO('V', 6)
|
||||
#define VMIO_SIOCNETIF _IO('V', 7)
|
||||
|
||||
#endif /* !_NET_IF_TAP_H_ */
|
61
sys/net/if_tapvar.h
Normal file
61
sys/net/if_tapvar.h
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (C) 1999-2000 by Maksim Yevmenkin <m_evmenkin@yahoo.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* BASED ON:
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 1998 Brian Somers <brian@Awfulhak.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk>
|
||||
* Nottingham University 1987.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $FreeBSD$
|
||||
* $Id: if_tapvar.h,v 0.6 2000/07/11 02:16:08 max Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NET_IF_TAPVAR_H_
|
||||
#define _NET_IF_TAPVAR_H_
|
||||
|
||||
struct tap_softc {
|
||||
struct arpcom arpcom; /* ethernet common data */
|
||||
#define tap_if arpcom.ac_if
|
||||
dev_t tap_dev; /* device */
|
||||
|
||||
u_short tap_flags; /* misc flags */
|
||||
#define TAP_OPEN (1 << 0)
|
||||
#define TAP_INITED (1 << 1)
|
||||
#define TAP_RWAIT (1 << 2)
|
||||
#define TAP_ASYNC (1 << 3)
|
||||
#define TAP_READY (TAP_OPEN|TAP_INITED)
|
||||
|
||||
pid_t tap_pid; /* PID of process to open */
|
||||
struct sigio *tap_sigio; /* information for async I/O */
|
||||
struct selinfo tap_rsel; /* read select */
|
||||
};
|
||||
|
||||
#endif /* !_NET_IF_TAPVAR_H_ */
|
Loading…
Reference in New Issue
Block a user