2 * Copyright (C) 1999-2000 by Maksim Yevmenkin <m_evmenkin@yahoo.com>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * -------------------------------------------------------------------------
29 * Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk>
30 * Nottingham University 1987.
34 * $FreeBSD: src/sys/net/if_tap.c,v 1.3.2.3 2002/04/14 21:41:48 luigi Exp $
35 * $Id: if_tap.c,v 0.21 2000/07/23 21:46:02 max Exp $
41 #include <sys/param.h>
43 #include <sys/device.h>
44 #include <sys/filedesc.h>
45 #include <sys/filio.h>
46 #include <sys/kernel.h>
47 #include <sys/malloc.h>
51 #include <sys/signalvar.h>
52 #include <sys/socket.h>
53 #include <sys/sockio.h>
54 #include <sys/sysctl.h>
55 #include <sys/systm.h>
56 #include <sys/ttycom.h>
58 #include <sys/vnode.h>
59 #include <sys/serialize.h>
61 #include <sys/thread2.h>
62 #include <sys/mplock2.h>
65 #include <net/ethernet.h>
67 #include <net/ifq_var.h>
68 #include <net/if_arp.h>
69 #include <net/if_clone.h>
70 #include <net/if_media.h>
71 #include <net/route.h>
72 #include <sys/devfs.h>
74 #include <netinet/in.h>
76 #include "if_tapvar.h"
79 #define TAP_IFFLAGS (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST)
82 #define TAP_PREALLOCATED_UNITS 4
84 #define TAP_PREALLOCATED_UNITS NTAP
87 #define CDEV_NAME "tap"
88 #define TAPDEBUG if (tapdebug) if_printf
92 #define VMNET_DEV_MASK 0x00010000
94 DEVFS_DEFINE_CLONE_BITMAP(tap
);
97 static int tapmodevent (module_t
, int, void *);
100 static struct tap_softc
*tapcreate(int, cdev_t
, int);
101 static void tapdestroy(struct tap_softc
*);
104 static int tap_clone_create(struct if_clone
*, int, caddr_t
);
105 static int tap_clone_destroy(struct ifnet
*);
108 /* network interface */
109 static void tapifstart (struct ifnet
*,
110 struct ifaltq_subque
*);
111 static int tapifioctl (struct ifnet
*, u_long
, caddr_t
,
113 static void tapifinit (void *);
114 static void tapifstop(struct tap_softc
*, int);
115 static void tapifflags(struct tap_softc
*);
118 /* character device */
119 static d_open_t tapopen
;
120 static d_clone_t tapclone
;
121 static d_close_t tapclose
;
122 static d_read_t tapread
;
123 static d_write_t tapwrite
;
124 static d_ioctl_t tapioctl
;
125 static d_kqfilter_t tapkqfilter
;
127 static struct dev_ops tap_ops
= {
134 .d_kqfilter
= tapkqfilter
137 static int taprefcnt
= 0; /* module ref. counter */
138 static int taplastunit
= -1; /* max. open unit number */
139 static int tapdebug
= 0; /* debug flag */
140 static int tapuopen
= 0; /* all user open() */
141 static int tapuponopen
= 0; /* IFF_UP */
143 MALLOC_DECLARE(M_TAP
);
144 MALLOC_DEFINE(M_TAP
, CDEV_NAME
, "Ethernet tunnel interface");
145 struct if_clone tap_cloner
= IF_CLONE_INITIALIZER("tap",
146 tap_clone_create
, tap_clone_destroy
,
148 static SLIST_HEAD(,tap_softc
) tap_listhead
=
149 SLIST_HEAD_INITIALIZER(&tap_listhead
);
151 SYSCTL_INT(_debug
, OID_AUTO
, if_tap_debug
, CTLFLAG_RW
, &tapdebug
, 0, "");
152 SYSCTL_DECL(_net_link
);
153 SYSCTL_NODE(_net_link
, OID_AUTO
, tap
, CTLFLAG_RW
, 0,
154 "Ethernet tunnel software network interface");
155 SYSCTL_INT(_net_link_tap
, OID_AUTO
, user_open
, CTLFLAG_RW
, &tapuopen
, 0,
156 "Allow user to open /dev/tap (based on node permissions)");
157 SYSCTL_INT(_net_link_tap
, OID_AUTO
, up_on_open
, CTLFLAG_RW
, &tapuponopen
, 0,
158 "Bring interface up when /dev/tap is opened");
159 SYSCTL_INT(_net_link_tap
, OID_AUTO
, debug
, CTLFLAG_RW
, &tapdebug
, 0, "");
161 DEV_MODULE(if_tap
, tapmodevent
, NULL
);
166 * module event handler
169 tapmodevent(module_t mod
, int type
, void *data
)
171 static int attached
= 0;
172 struct tap_softc
*tp
, *ntp
;
180 make_autoclone_dev(&tap_ops
, &DEVFS_CLONE_BITMAP(tap
), tapclone
,
181 UID_ROOT
, GID_WHEEL
, 0600, "tap");
182 SLIST_INIT(&tap_listhead
);
183 if_clone_attach(&tap_cloner
);
185 for (i
= 0; i
< TAP_PREALLOCATED_UNITS
; ++i
) {
186 make_dev(&tap_ops
, i
, UID_ROOT
, GID_WHEEL
,
188 devfs_clone_bitmap_set(&DEVFS_CLONE_BITMAP(tap
), i
);
198 if_clone_detach(&tap_cloner
);
200 /* Maintain tap ifs in a local list */
201 SLIST_FOREACH_MUTABLE(tp
, &tap_listhead
, tap_link
, ntp
)
206 devfs_clone_handler_del("tap");
207 dev_ops_remove_all(&tap_ops
);
208 devfs_clone_bitmap_uninit(&DEVFS_CLONE_BITMAP(tap
));
220 * tapcreate - create or clone an interface
222 static struct tap_softc
*
223 tapcreate(int unit
, cdev_t dev
, int flags
)
225 const char *name
= TAP
;
227 struct tap_softc
*tp
;
228 uint8_t ether_addr
[ETHER_ADDR_LEN
];
230 tp
= kmalloc(sizeof(*tp
), M_TAP
, M_WAITOK
| M_ZERO
);
234 tp
->tap_flags
|= flags
;
236 reference_dev(dev
); /* tp association */
238 /* generate fake MAC address: 00 bd xx xx xx unit_no */
239 ether_addr
[0] = 0x00;
240 ether_addr
[1] = 0xbd;
241 bcopy(&ticks
, ðer_addr
[2], 3);
242 ether_addr
[5] = (u_char
)unit
;
244 /* fill the rest and attach interface */
248 if_initname(ifp
, name
, unit
);
249 if (unit
> taplastunit
)
252 ifp
->if_init
= tapifinit
;
253 ifp
->if_start
= tapifstart
;
254 ifp
->if_ioctl
= tapifioctl
;
255 ifp
->if_mtu
= ETHERMTU
;
256 ifp
->if_flags
= TAP_IFFLAGS
;
257 ifq_set_maxlen(&ifp
->if_snd
, ifqmaxlen
);
258 ifq_set_ready(&ifp
->if_snd
);
260 ether_ifattach(ifp
, ether_addr
, NULL
);
262 tp
->tap_flags
|= TAP_INITED
;
263 tp
->tap_devq
.ifq_maxlen
= ifqmaxlen
;
265 SLIST_INSERT_HEAD(&tap_listhead
, tp
, tap_link
);
267 TAPDEBUG(ifp
, "created. minor = %#x\n", minor(dev
));
275 struct tap_softc
*tp
;
277 SLIST_FOREACH(tp
, &tap_listhead
, tap_link
) {
278 if (tp
->tap_unit
== unit
)
287 * Create a new tap instance via ifconfig.
290 tap_clone_create(struct if_clone
*ifc __unused
, int unit
,
291 caddr_t param __unused
)
293 struct tap_softc
*tp
;
298 if (!devfs_clone_bitmap_chk(&DEVFS_CLONE_BITMAP(tap
), unit
)) {
299 devfs_clone_bitmap_set(&DEVFS_CLONE_BITMAP(tap
), unit
);
300 dev
= make_dev(&tap_ops
, unit
, UID_ROOT
, GID_WHEEL
,
301 0600, "%s%d", TAP
, unit
);
303 dev
= devfs_find_device_by_name("%s%d", TAP
, unit
);
306 KKASSERT(dev
!= NULL
);
307 tp
= tapcreate(unit
, dev
, TAP_MANUALMAKE
);
309 tp
->tap_flags
|= TAP_CLONE
;
310 TAPDEBUG(&tp
->tap_if
, "clone created. minor = %#x tap_flags = 0x%x\n",
311 minor(tp
->tap_dev
), tp
->tap_flags
);
319 * to open tunnel. must be superuser
322 tapopen(struct dev_open_args
*ap
)
325 struct tap_softc
*tp
= NULL
;
326 struct ifnet
*ifp
= NULL
;
330 (error
= priv_check_cred(ap
->a_cred
, PRIV_ROOT
, 0)) != 0)
334 dev
= ap
->a_head
.a_dev
;
337 tp
= tapcreate(minor(dev
), dev
, TAP_MANUALMAKE
);
338 if (tp
->tap_flags
& TAP_OPEN
) {
342 ifp
= &tp
->arpcom
.ac_if
;
344 if ((tp
->tap_flags
& TAP_CLONE
) == 0) {
345 EVENTHANDLER_INVOKE(ifnet_attach_event
, ifp
);
347 /* Announce the return of the interface. */
348 rt_ifannouncemsg(ifp
, IFAN_ARRIVAL
);
351 bcopy(tp
->arpcom
.ac_enaddr
, tp
->ether_addr
, sizeof(tp
->ether_addr
));
353 if (curthread
->td_proc
)
354 fsetown(curthread
->td_proc
->p_pid
, &tp
->tap_sigtd
);
355 tp
->tap_flags
|= TAP_OPEN
;
358 if (tapuponopen
&& (ifp
->if_flags
& IFF_UP
) == 0) {
363 ifnet_serialize_all(ifp
);
365 ifnet_deserialize_all(ifp
);
367 tp
->tap_flags
|= TAP_CLOSEDOWN
;
370 TAPDEBUG(ifp
, "opened. minor = %#x, refcnt = %d, taplastunit = %d\n",
371 minor(tp
->tap_dev
), taprefcnt
, taplastunit
);
378 tapclone(struct dev_clone_args
*ap
)
382 unit
= devfs_clone_bitmap_get(&DEVFS_CLONE_BITMAP(tap
), 0);
383 ap
->a_dev
= make_only_dev(&tap_ops
, unit
, UID_ROOT
, GID_WHEEL
,
384 0600, "%s%d", TAP
, unit
);
385 tapcreate(unit
, ap
->a_dev
, 0);
392 * close the device - mark i/f down & delete routing info
395 tapclose(struct dev_close_args
*ap
)
397 cdev_t dev
= ap
->a_head
.a_dev
;
398 struct tap_softc
*tp
= dev
->si_drv1
;
399 struct ifnet
*ifp
= &tp
->tap_if
;
404 /* Junk all pending output */
405 ifq_purge_all(&ifp
->if_snd
);
408 * Do not bring the interface down, and do not anything with
409 * interface, if we are in VMnet mode. just close the device.
411 * If the interface is not cloned, we always bring it down.
413 * If the interface is cloned, then we bring it down during
414 * closing only if it was brought up during opening.
416 if ((tp
->tap_flags
& TAP_VMNET
) == 0 &&
417 ((tp
->tap_flags
& TAP_CLONE
) == 0 ||
418 (tp
->tap_flags
& TAP_CLOSEDOWN
))) {
419 if (ifp
->if_flags
& IFF_UP
)
423 ifnet_serialize_all(ifp
);
424 tapifstop(tp
, clear_flags
);
425 ifnet_deserialize_all(ifp
);
427 if ((tp
->tap_flags
& TAP_CLONE
) == 0) {
428 if_purgeaddrs_nolink(ifp
);
430 EVENTHANDLER_INVOKE(ifnet_detach_event
, ifp
);
432 /* Announce the departure of the interface. */
433 rt_ifannouncemsg(ifp
, IFAN_DEPARTURE
);
436 funsetown(&tp
->tap_sigio
);
437 tp
->tap_sigio
= NULL
;
438 KNOTE(&tp
->tap_rkq
.ki_note
, 0);
440 tp
->tap_flags
&= ~TAP_OPEN
;
441 funsetown(&tp
->tap_sigtd
);
442 tp
->tap_sigtd
= NULL
;
447 if_printf(ifp
, "minor = %#x, refcnt = %d is out of sync. "
448 "set refcnt to 0\n", minor(tp
->tap_dev
), taprefcnt
);
451 TAPDEBUG(ifp
, "closed. minor = %#x, refcnt = %d, taplastunit = %d\n",
452 minor(tp
->tap_dev
), taprefcnt
, taplastunit
);
455 * Only auto-destroy if the interface was not manually
458 if ((tp
->tap_flags
& TAP_MANUALMAKE
) == 0 &&
459 tp
->tap_unit
>= TAP_PREALLOCATED_UNITS
) {
470 * Destroy a tap instance.
473 tapdestroy(struct tap_softc
*tp
)
475 struct ifnet
*ifp
= &tp
->arpcom
.ac_if
;
478 TAPDEBUG(ifp
, "destroyed. minor = %#x, refcnt = %d, taplastunit = %d\n",
479 minor(tp
->tap_dev
), taprefcnt
, taplastunit
);
481 ifnet_serialize_all(ifp
);
483 ifnet_deserialize_all(ifp
);
486 SLIST_REMOVE(&tap_listhead
, tp
, tap_softc
, tap_link
);
492 release_dev(dev
); /* tp association */
495 * Also destroy the cloned device
497 if (tp
->tap_unit
>= TAP_PREALLOCATED_UNITS
) {
499 devfs_clone_bitmap_put(&DEVFS_CLONE_BITMAP(tap
), tp
->tap_unit
);
510 * Destroy a tap instance.
513 tap_clone_destroy(struct ifnet
*ifp
)
515 struct tap_softc
*tp
= ifp
->if_softc
;
517 if ((tp
->tap_flags
& TAP_CLONE
) == 0)
520 TAPDEBUG(&tp
->tap_if
, "clone destroyed. minor = %#x tap_flags = 0x%x\n",
521 minor(tp
->tap_dev
), tp
->tap_flags
);
530 * Network interface initialization function (called with if serializer held)
537 struct tap_softc
*tp
= xtp
;
538 struct ifnet
*ifp
= &tp
->tap_if
;
539 struct ifaltq_subque
*ifsq
= ifq_get_subq_default(&ifp
->if_snd
);
541 TAPDEBUG(ifp
, "initializing, minor = %#x tap_flags = 0x%x\n",
542 minor(tp
->tap_dev
), tp
->tap_flags
);
544 ASSERT_IFNET_SERIALIZED_ALL(ifp
);
548 ifp
->if_flags
|= IFF_RUNNING
;
549 ifsq_clr_oactive(ifsq
);
551 /* attempt to start output */
552 tapifstart(ifp
, ifsq
);
559 * Process an ioctl request on network interface (called with if serializer
565 tapifioctl(struct ifnet
*ifp
, u_long cmd
, caddr_t data
, struct ucred
*cr
)
567 struct tap_softc
*tp
= (struct tap_softc
*)(ifp
->if_softc
);
568 struct ifstat
*ifs
= NULL
;
569 struct ifmediareq
*ifmr
= NULL
;
577 error
= ether_ioctl(ifp
, cmd
, data
);
584 case SIOCADDMULTI
: /* XXX -- just like vmnet does */
590 * The bridge code needs this when running the
591 * spanning tree protocol.
593 ifmr
= (struct ifmediareq
*)data
;
594 dummy
= ifmr
->ifm_count
;
596 ifmr
->ifm_status
= IFM_AVALID
;
597 ifmr
->ifm_active
= IFM_ETHER
;
598 if (tp
->tap_flags
& TAP_OPEN
)
599 ifmr
->ifm_status
|= IFM_ACTIVE
;
600 ifmr
->ifm_current
= ifmr
->ifm_active
;
602 int media
= IFM_ETHER
;
603 error
= copyout(&media
,
610 ifs
= (struct ifstat
*)data
;
611 dummy
= strlen(ifs
->ascii
);
612 if ((tp
->tap_flags
& TAP_OPEN
) &&
613 dummy
< sizeof(ifs
->ascii
)) {
614 if (tp
->tap_sigtd
&& tp
->tap_sigtd
->sio_proc
) {
615 ksnprintf(ifs
->ascii
+ dummy
,
616 sizeof(ifs
->ascii
) - dummy
,
617 "\tOpened by pid %d\n",
618 (int)tp
->tap_sigtd
->sio_proc
->p_pid
);
620 ksnprintf(ifs
->ascii
+ dummy
,
621 sizeof(ifs
->ascii
) - dummy
,
622 "\tOpened by <unknown>\n");
639 * Queue packets from higher level ready to put out (called with if serializer
645 tapifstart(struct ifnet
*ifp
, struct ifaltq_subque
*ifsq
)
647 struct tap_softc
*tp
= ifp
->if_softc
;
652 ASSERT_ALTQ_SQ_DEFAULT(ifp
, ifsq
);
653 TAPDEBUG(ifp
, "starting, minor = %#x\n", minor(tp
->tap_dev
));
656 * do not junk pending output if we are in VMnet mode.
657 * XXX: can this do any harm because of queue overflow?
660 if (((tp
->tap_flags
& TAP_VMNET
) == 0) &&
661 ((tp
->tap_flags
& TAP_READY
) != TAP_READY
)) {
662 TAPDEBUG(ifp
, "not ready. minor = %#x, tap_flags = 0x%x\n",
663 minor(tp
->tap_dev
), tp
->tap_flags
);
668 ifsq_set_oactive(ifsq
);
671 while ((m
= ifsq_dequeue(ifsq
)) != NULL
) {
674 IFNET_STAT_INC(ifp
, oerrors
, 1);
678 IFNET_STAT_INC(ifp
, opackets
, 1);
684 if (tp
->tap_flags
& TAP_RWAIT
) {
685 tp
->tap_flags
&= ~TAP_RWAIT
;
689 KNOTE(&tp
->tap_rkq
.ki_note
, 0);
691 if ((tp
->tap_flags
& TAP_ASYNC
) && (tp
->tap_sigio
!= NULL
)) {
693 pgsigio(tp
->tap_sigio
, SIGIO
, 0);
698 ifsq_clr_oactive(ifsq
);
705 * The ops interface is now pretty minimal. Called via fileops with nothing
711 tapioctl(struct dev_ioctl_args
*ap
)
713 cdev_t dev
= ap
->a_head
.a_dev
;
714 caddr_t data
= ap
->a_data
;
715 struct tap_softc
*tp
= dev
->si_drv1
;
716 struct ifnet
*ifp
= &tp
->tap_if
;
717 struct tapinfo
*tapp
= NULL
;
722 ifnet_serialize_all(ifp
);
727 tapp
= (struct tapinfo
*)data
;
728 ifp
->if_mtu
= tapp
->mtu
;
729 ifp
->if_type
= tapp
->type
;
730 ifp
->if_baudrate
= tapp
->baudrate
;
734 tapp
= (struct tapinfo
*)data
;
735 tapp
->mtu
= ifp
->if_mtu
;
736 tapp
->type
= ifp
->if_type
;
737 tapp
->baudrate
= ifp
->if_baudrate
;
741 tapdebug
= *(int *)data
;
745 *(int *)data
= tapdebug
;
750 tp
->tap_flags
|= TAP_ASYNC
;
752 tp
->tap_flags
&= ~TAP_ASYNC
;
756 /* Take a look at devq first */
757 IF_POLL(&tp
->tap_devq
, mb
);
760 for(; mb
!= NULL
; mb
= mb
->m_next
)
761 *(int *)data
+= mb
->m_len
;
763 *(int *)data
= ifsq_poll_pktlen(
764 ifq_get_subq_default(&ifp
->if_snd
));
769 error
= fsetown(*(int *)data
, &tp
->tap_sigio
);
773 *(int *)data
= fgetown(&tp
->tap_sigio
);
776 /* this is deprecated, FIOSETOWN should be used instead */
778 error
= fsetown(-(*(int *)data
), &tp
->tap_sigio
);
781 /* this is deprecated, FIOGETOWN should be used instead */
783 *(int *)data
= -fgetown(&tp
->tap_sigio
);
786 /* VMware/VMnet port ioctl's */
788 case SIOCGIFFLAGS
: /* get ifnet flags */
789 bcopy(&ifp
->if_flags
, data
, sizeof(ifp
->if_flags
));
792 case VMIO_SIOCSIFFLAGS
: /* VMware/VMnet SIOCSIFFLAGS */
795 f
&= ~IFF_CANTCHANGE
;
797 ifp
->if_flags
= f
| (ifp
->if_flags
& IFF_CANTCHANGE
);
800 case OSIOCGIFADDR
: /* get MAC address of the remote side */
802 bcopy(tp
->ether_addr
, data
, sizeof(tp
->ether_addr
));
805 case SIOCSIFADDR
: /* set MAC address of the remote side */
806 bcopy(data
, tp
->ether_addr
, sizeof(tp
->ether_addr
));
813 ifnet_deserialize_all(ifp
);
821 * The ops read interface - reads a packet at a time, or at
822 * least as much of a packet as can be read.
824 * Called from the fileops interface with nothing held.
829 tapread(struct dev_read_args
*ap
)
831 cdev_t dev
= ap
->a_head
.a_dev
;
832 struct uio
*uio
= ap
->a_uio
;
833 struct tap_softc
*tp
= dev
->si_drv1
;
834 struct ifnet
*ifp
= &tp
->tap_if
;
835 struct mbuf
*m0
= NULL
;
838 TAPDEBUG(ifp
, "reading, minor = %#x\n", minor(tp
->tap_dev
));
840 if ((tp
->tap_flags
& TAP_READY
) != TAP_READY
) {
841 TAPDEBUG(ifp
, "not ready. minor = %#x, tap_flags = 0x%x\n",
842 minor(tp
->tap_dev
), tp
->tap_flags
);
847 tp
->tap_flags
&= ~TAP_RWAIT
;
849 /* sleep until we get a packet */
851 ifnet_serialize_all(ifp
);
852 IF_DEQUEUE(&tp
->tap_devq
, m0
);
854 if (ap
->a_ioflag
& IO_NDELAY
) {
855 ifnet_deserialize_all(ifp
);
856 return (EWOULDBLOCK
);
858 tp
->tap_flags
|= TAP_RWAIT
;
859 tsleep_interlock(tp
, PCATCH
);
860 ifnet_deserialize_all(ifp
);
861 error
= tsleep(tp
, PCATCH
| PINTERLOCKED
, "taprd", 0);
865 ifnet_deserialize_all(ifp
);
867 } while (m0
== NULL
);
871 /* xfer packet to user space */
872 while ((m0
!= NULL
) && (uio
->uio_resid
> 0) && (error
== 0)) {
873 len
= (int)szmin(uio
->uio_resid
, m0
->m_len
);
877 error
= uiomove(mtod(m0
, caddr_t
), (size_t)len
, uio
);
882 TAPDEBUG(ifp
, "dropping mbuf, minor = %#x\n",
893 * The ops write interface - an atomic write is a packet - or else!
895 * Called from the fileops interface with nothing held.
900 tapwrite(struct dev_write_args
*ap
)
902 cdev_t dev
= ap
->a_head
.a_dev
;
903 struct uio
*uio
= ap
->a_uio
;
904 struct tap_softc
*tp
= dev
->si_drv1
;
905 struct ifnet
*ifp
= &tp
->tap_if
;
906 struct mbuf
*top
= NULL
, **mp
= NULL
, *m
= NULL
;
910 TAPDEBUG(ifp
, "writing, minor = %#x\n", minor(tp
->tap_dev
));
912 if ((tp
->tap_flags
& TAP_READY
) != TAP_READY
) {
913 TAPDEBUG(ifp
, "not ready. minor = %#x, tap_flags = 0x%x\n",
914 minor(tp
->tap_dev
), tp
->tap_flags
);
918 if (uio
->uio_resid
== 0)
921 if (uio
->uio_resid
> TAPMRU
) {
922 TAPDEBUG(ifp
, "invalid packet len = %zu, minor = %#x\n",
923 uio
->uio_resid
, minor(tp
->tap_dev
));
927 tlen
= uio
->uio_resid
;
929 /* get a header mbuf */
930 MGETHDR(m
, M_WAITOK
, MT_DATA
);
939 while (error
== 0 && uio
->uio_resid
> 0) {
940 m
->m_len
= (int)szmin(mlen
, uio
->uio_resid
);
941 error
= uiomove(mtod(m
, caddr_t
), (size_t)m
->m_len
, uio
);
944 if (uio
->uio_resid
> 0) {
945 MGET(m
, M_WAITOK
, MT_DATA
);
954 IFNET_STAT_INC(ifp
, ierrors
, 1);
960 top
->m_pkthdr
.len
= (int)tlen
;
961 top
->m_pkthdr
.rcvif
= ifp
;
964 * Ethernet bridge and bpf are handled in ether_input
966 * adjust mbuf and give packet to the ether_input
968 ifnet_serialize_all(ifp
);
969 ifp
->if_input(ifp
, top
, NULL
, -1);
970 IFNET_STAT_INC(ifp
, ipackets
, 1);/* ibytes are counted in ether_input */
971 ifnet_deserialize_all(ifp
);
977 * tapkqfilter - called from the fileops interface with nothing held
981 static int filt_tapread(struct knote
*kn
, long hint
);
982 static int filt_tapwrite(struct knote
*kn
, long hint
);
983 static void filt_tapdetach(struct knote
*kn
);
984 static struct filterops tapread_filtops
=
985 { FILTEROP_ISFD
, NULL
, filt_tapdetach
, filt_tapread
};
986 static struct filterops tapwrite_filtops
=
987 { FILTEROP_ISFD
, NULL
, filt_tapdetach
, filt_tapwrite
};
990 tapkqfilter(struct dev_kqfilter_args
*ap
)
992 cdev_t dev
= ap
->a_head
.a_dev
;
993 struct knote
*kn
= ap
->a_kn
;
994 struct tap_softc
*tp
;
998 list
= &tp
->tap_rkq
.ki_note
;
1001 switch(kn
->kn_filter
) {
1003 kn
->kn_fop
= &tapread_filtops
;
1004 kn
->kn_hook
= (void *)tp
;
1007 kn
->kn_fop
= &tapwrite_filtops
;
1008 kn
->kn_hook
= (void *)tp
;
1011 ap
->a_result
= EOPNOTSUPP
;
1015 knote_insert(list
, kn
);
1020 filt_tapread(struct knote
*kn
, long hint
)
1022 struct tap_softc
*tp
= (void *)kn
->kn_hook
;
1024 if (IF_QEMPTY(&tp
->tap_devq
) == 0) /* XXX serializer */
1031 filt_tapwrite(struct knote
*kn
, long hint
)
1033 /* Always ready for a write */
1038 filt_tapdetach(struct knote
*kn
)
1040 struct tap_softc
*tp
= (void *)kn
->kn_hook
;
1042 knote_remove(&tp
->tap_rkq
.ki_note
, kn
);
1046 tapifstop(struct tap_softc
*tp
, int clear_flags
)
1048 struct ifnet
*ifp
= &tp
->tap_if
;
1050 ASSERT_IFNET_SERIALIZED_ALL(ifp
);
1051 IF_DRAIN(&tp
->tap_devq
);
1052 tp
->tap_flags
&= ~TAP_CLOSEDOWN
;
1054 ifp
->if_flags
&= ~IFF_RUNNING
;
1055 ifsq_clr_oactive(ifq_get_subq_default(&ifp
->if_snd
));
1060 tapifflags(struct tap_softc
*tp
)
1062 struct ifnet
*ifp
= &tp
->arpcom
.ac_if
;
1064 ASSERT_IFNET_SERIALIZED_ALL(ifp
);
1065 if ((tp
->tap_flags
& TAP_VMNET
) == 0) {
1067 * Only for non-vmnet tap(4)
1069 if (ifp
->if_flags
& IFF_UP
) {
1070 if ((ifp
->if_flags
& IFF_RUNNING
) == 0)