bridge(4): document net.link.bridge.pfil_onlyip
[dragonfly.git] / sys / net / tap / if_tap.c
blob152ea7b9e69123134e55466cb7d9ae88433f32d3
1 /*
2 * Copyright (C) 1999-2000 by Maksim Yevmenkin <m_evmenkin@yahoo.com>
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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
24 * SUCH DAMAGE.
26 * BASED ON:
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 $
38 #include "opt_inet.h"
40 #include <sys/param.h>
41 #include <sys/conf.h>
42 #include <sys/device.h>
43 #include <sys/filedesc.h>
44 #include <sys/filio.h>
45 #include <sys/kernel.h>
46 #include <sys/malloc.h>
47 #include <sys/mbuf.h>
48 #include <sys/proc.h>
49 #include <sys/caps.h>
50 #include <sys/signalvar.h>
51 #include <sys/socket.h>
52 #include <sys/sockio.h>
53 #include <sys/sysctl.h>
54 #include <sys/systm.h>
55 #include <sys/ttycom.h>
56 #include <sys/uio.h>
57 #include <sys/vnode.h>
58 #include <sys/serialize.h>
59 #include <sys/thread2.h>
60 #include <sys/mplock2.h>
61 #include <sys/devfs.h>
62 #include <sys/queue.h>
64 #include <net/bpf.h>
65 #include <net/ethernet.h>
66 #include <net/if.h>
67 #include <net/if_types.h>
68 #include <net/if_arp.h>
69 #include <net/if_clone.h>
70 #include <net/if_media.h>
71 #include <net/ifq_var.h>
72 #include <net/route.h>
74 #include <netinet/in.h>
76 #include "if_tapvar.h"
77 #include "if_tap.h"
79 #define TAP_IFFLAGS (IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST)
81 #define TAP "tap"
82 #define TAPDEBUG if (tapdebug) if_printf
84 /* module */
85 static int tapmodevent(module_t, int, void *);
87 /* device */
88 static struct tap_softc *tapcreate(cdev_t, int);
89 static void tapdestroy(struct tap_softc *);
91 /* clone */
92 static int tap_clone_create(struct if_clone *, int,
93 caddr_t, caddr_t);
94 static int tap_clone_destroy(struct ifnet *);
96 /* network interface */
97 static void tapifinit(void *);
98 static void tapifstart(struct ifnet *, struct ifaltq_subque *);
99 static int tapifioctl(struct ifnet *, u_long, caddr_t,
100 struct ucred *);
101 static void tapifstop(struct tap_softc *, int);
102 static void tapifflags(struct tap_softc *);
104 /* character device */
105 static d_open_t tapopen;
106 static d_clone_t tapclone;
107 static d_close_t tapclose;
108 static d_read_t tapread;
109 static d_write_t tapwrite;
110 static d_ioctl_t tapioctl;
111 static d_kqfilter_t tapkqfilter;
113 static struct dev_ops tap_ops = {
114 { TAP, 0, 0 },
115 .d_open = tapopen,
116 .d_close = tapclose,
117 .d_read = tapread,
118 .d_write = tapwrite,
119 .d_ioctl = tapioctl,
120 .d_kqfilter = tapkqfilter
123 /* kqueue support */
124 static void tap_filter_detach(struct knote *);
125 static int tap_filter_read(struct knote *, long);
126 static int tap_filter_write(struct knote *, long);
128 static struct filterops tapread_filtops = {
129 FILTEROP_ISFD,
130 NULL,
131 tap_filter_detach,
132 tap_filter_read
134 static struct filterops tapwrite_filtops = {
135 FILTEROP_ISFD,
136 NULL,
137 tap_filter_detach,
138 tap_filter_write
141 static int tapdebug = 0; /* debug flag */
142 static int taprefcnt = 0; /* module ref. counter */
143 static int tapuopen = 0; /* allow user open() */
144 static int tapuponopen = 0; /* IFF_UP when opened */
146 static MALLOC_DEFINE(M_TAP, TAP, "Ethernet tunnel interface");
148 static DEVFS_DEFINE_CLONE_BITMAP(tap);
150 struct if_clone tap_cloner = IF_CLONE_INITIALIZER(
151 TAP, tap_clone_create, tap_clone_destroy, 0, IF_MAXUNIT);
153 static SLIST_HEAD(,tap_softc) tap_listhead =
154 SLIST_HEAD_INITIALIZER(&tap_listhead);
156 SYSCTL_INT(_debug, OID_AUTO, if_tap_debug, CTLFLAG_RW, &tapdebug, 0, "");
157 SYSCTL_DECL(_net_link);
158 SYSCTL_NODE(_net_link, OID_AUTO, tap, CTLFLAG_RW, 0,
159 "Ethernet tunnel software network interface");
160 SYSCTL_INT(_net_link_tap, OID_AUTO, user_open, CTLFLAG_RW, &tapuopen, 0,
161 "Allow user to open /dev/tap (based on node permissions)");
162 SYSCTL_INT(_net_link_tap, OID_AUTO, up_on_open, CTLFLAG_RW, &tapuponopen, 0,
163 "Bring interface up when /dev/tap is opened");
164 SYSCTL_INT(_net_link_tap, OID_AUTO, debug, CTLFLAG_RW, &tapdebug, 0, "");
165 SYSCTL_INT(_net_link_tap, OID_AUTO, refcnt, CTLFLAG_RD, &taprefcnt, 0,
166 "Number of opened devices");
168 DEV_MODULE(if_tap, tapmodevent, NULL);
171 * tapmodevent
173 * module event handler
175 static int
176 tapmodevent(module_t mod, int type, void *data)
178 static cdev_t dev = NULL;
179 struct tap_softc *sc, *sc_tmp;
181 switch (type) {
182 case MOD_LOAD:
183 dev = make_autoclone_dev(&tap_ops, &DEVFS_CLONE_BITMAP(tap),
184 tapclone, UID_ROOT, GID_WHEEL,
185 0600, TAP);
186 SLIST_INIT(&tap_listhead);
187 if_clone_attach(&tap_cloner);
188 break;
190 case MOD_UNLOAD:
191 if (taprefcnt > 0)
192 return (EBUSY);
194 if_clone_detach(&tap_cloner);
196 SLIST_FOREACH_MUTABLE(sc, &tap_listhead, tap_link, sc_tmp)
197 tapdestroy(sc);
199 dev_ops_remove_all(&tap_ops);
200 destroy_autoclone_dev(dev, &DEVFS_CLONE_BITMAP(tap));
201 break;
203 default:
204 return (EOPNOTSUPP);
207 return (0);
212 * Create or clone an interface
214 static struct tap_softc *
215 tapcreate(cdev_t dev, int flags)
217 struct tap_softc *sc;
218 struct ifnet *ifp;
219 uint8_t ether_addr[ETHER_ADDR_LEN];
220 int unit = minor(dev);
222 sc = kmalloc(sizeof(*sc), M_TAP, M_WAITOK | M_ZERO);
223 dev->si_drv1 = sc;
224 sc->tap_dev = dev;
225 sc->tap_flags |= flags;
227 reference_dev(dev); /* device association */
229 /* generate fake MAC address: 00 bd xx xx xx unit_no */
230 ether_addr[0] = 0x00;
231 ether_addr[1] = 0xbd;
232 bcopy(&ticks, &ether_addr[2], 3);
233 ether_addr[5] = (u_char)unit;
235 /* fill the rest and attach interface */
236 ifp = &sc->tap_if;
237 if_initname(ifp, TAP, unit);
238 ifp->if_type = IFT_ETHER;
239 ifp->if_init = tapifinit;
240 ifp->if_start = tapifstart;
241 ifp->if_ioctl = tapifioctl;
242 ifp->if_mtu = ETHERMTU;
243 ifp->if_flags = TAP_IFFLAGS;
244 ifp->if_softc = sc;
245 ifq_set_maxlen(&ifp->if_snd, ifqmaxlen);
246 ifq_set_ready(&ifp->if_snd);
248 ether_ifattach(ifp, ether_addr, NULL);
250 sc->tap_flags |= TAP_INITED;
251 sc->tap_devq.ifq_maxlen = ifqmaxlen;
253 SLIST_INSERT_HEAD(&tap_listhead, sc, tap_link);
255 TAPDEBUG(ifp, "created, minor = %#x, flags = 0x%x\n",
256 unit, sc->tap_flags);
257 return (sc);
260 static struct tap_softc *
261 tapfind(int unit)
263 struct tap_softc *sc;
265 SLIST_FOREACH(sc, &tap_listhead, tap_link) {
266 if (minor(sc->tap_dev) == unit)
267 return (sc);
269 return (NULL);
273 * Create a new tap instance via ifconfig.
275 static int
276 tap_clone_create(struct if_clone *ifc __unused, int unit,
277 caddr_t params __unused, caddr_t data)
279 struct tap_softc *sc;
280 cdev_t dev = (cdev_t)data;
281 int flags;
283 if (tapfind(unit) != NULL)
284 return (EEXIST);
286 if (dev == NULL) {
287 if (!devfs_clone_bitmap_chk(&DEVFS_CLONE_BITMAP(tap), unit)) {
288 devfs_clone_bitmap_set(&DEVFS_CLONE_BITMAP(tap), unit);
289 dev = make_dev(&tap_ops, unit, UID_ROOT, GID_WHEEL,
290 0600, "%s%d", TAP, unit);
291 } else {
292 dev = devfs_find_device_by_name("%s%d", TAP, unit);
293 if (dev == NULL)
294 return (ENOENT);
296 flags = TAP_MANUALMAKE;
297 } else {
298 flags = 0;
301 if ((sc = tapcreate(dev, flags)) == NULL)
302 return (ENOMEM);
304 sc->tap_flags |= TAP_CLONE;
306 TAPDEBUG(&sc->tap_if, "clone created, minor = %#x, flags = 0x%x\n",
307 minor(sc->tap_dev), sc->tap_flags);
309 return (0);
313 * Open the tap device.
315 static int
316 tapopen(struct dev_open_args *ap)
318 cdev_t dev = NULL;
319 struct tap_softc *sc = NULL;
320 struct ifnet *ifp = NULL;
321 int error;
323 if (tapuopen == 0 &&
324 (error = caps_priv_check(ap->a_cred, SYSCAP_RESTRICTEDROOT)) != 0)
326 return (error);
329 get_mplock();
331 dev = ap->a_head.a_dev;
332 sc = dev->si_drv1;
333 if (sc == NULL && (sc = tapcreate(dev, 0)) == NULL) {
334 rel_mplock();
335 return (ENOMEM);
337 if (sc->tap_flags & TAP_OPEN) {
338 rel_mplock();
339 return (EBUSY);
342 ifp = &sc->tap_if;
343 bcopy(sc->arpcom.ac_enaddr, sc->ether_addr, sizeof(sc->ether_addr));
345 if (curthread->td_proc)
346 fsetown(curthread->td_proc->p_pid, &sc->tap_sigtd);
347 sc->tap_flags |= TAP_OPEN;
348 taprefcnt++;
350 if (tapuponopen && (ifp->if_flags & IFF_UP) == 0) {
351 crit_enter();
352 if_up(ifp);
353 crit_exit();
355 ifnet_serialize_all(ifp);
356 tapifflags(sc);
357 ifnet_deserialize_all(ifp);
359 sc->tap_flags |= TAP_CLOSEDOWN;
362 TAPDEBUG(ifp, "opened, minor = %#x. Module refcnt = %d\n",
363 minor(dev), taprefcnt);
365 rel_mplock();
366 return (0);
369 static int
370 tapclone(struct dev_clone_args *ap)
372 char ifname[IFNAMSIZ];
373 int unit;
375 unit = devfs_clone_bitmap_get(&DEVFS_CLONE_BITMAP(tap), 0);
376 ksnprintf(ifname, IFNAMSIZ, "%s%d", TAP, unit);
377 ap->a_dev = make_only_dev(&tap_ops, unit, UID_ROOT, GID_WHEEL,
378 0600, "%s", ifname);
381 * Use the if_clone framework to create cloned device/interface,
382 * so the two clone methods (autoclone device /dev/tap; ifconfig
383 * clone) are consistent and can be mix used.
385 * Need to pass the cdev_t because the device created by
386 * 'make_only_dev()' doesn't appear in '/dev' yet so that it can't
387 * be found by 'devfs_find_device_by_name()' in 'tap_clone_create()'.
389 return (if_clone_create(ifname, IFNAMSIZ, NULL, (caddr_t)ap->a_dev));
393 * Close the tap device: bring the interface down & delete routing info.
395 static int
396 tapclose(struct dev_close_args *ap)
398 cdev_t dev = ap->a_head.a_dev;
399 struct tap_softc *sc = dev->si_drv1;
400 struct ifnet *ifp;
401 int unit = minor(dev);
402 int clear_flags = 0;
403 char ifname[IFNAMSIZ];
405 KASSERT(sc != NULL,
406 ("try closing the already destroyed %s%d", TAP, unit));
407 ifp = &sc->tap_if;
409 get_mplock();
411 /* Junk all pending output */
412 ifq_purge_all(&ifp->if_snd);
415 * If the interface is not cloned, we always bring it down.
417 * If the interface is cloned, then we bring it down during
418 * closing only if it was brought up during opening.
420 if ((sc->tap_flags & TAP_CLONE) == 0 ||
421 (sc->tap_flags & TAP_CLOSEDOWN)) {
422 if (ifp->if_flags & IFF_UP)
423 if_down(ifp);
424 clear_flags = 1;
426 ifnet_serialize_all(ifp);
427 tapifstop(sc, clear_flags);
428 ifnet_deserialize_all(ifp);
430 if ((sc->tap_flags & TAP_MANUALMAKE) == 0) {
431 if_purgeaddrs_nolink(ifp);
433 EVENTHANDLER_INVOKE(ifnet_detach_event, ifp);
435 /* Announce the departure of the interface. */
436 rt_ifannouncemsg(ifp, IFAN_DEPARTURE);
439 funsetown(&sc->tap_sigio);
440 sc->tap_sigio = NULL;
441 KNOTE(&sc->tap_rkq.ki_note, 0);
443 sc->tap_flags &= ~TAP_OPEN;
444 funsetown(&sc->tap_sigtd);
445 sc->tap_sigtd = NULL;
447 taprefcnt--;
448 if (taprefcnt < 0) {
449 taprefcnt = 0;
450 if_printf(ifp, ". Module refcnt = %d is out of sync! "
451 "Force refcnt to be 0.\n", taprefcnt);
454 TAPDEBUG(ifp, "closed, minor = %#x. Module refcnt = %d\n",
455 unit, taprefcnt);
457 /* Only auto-destroy if the interface was not manually created. */
458 if ((sc->tap_flags & TAP_MANUALMAKE) == 0) {
459 ksnprintf(ifname, IFNAMSIZ, "%s%d", TAP, unit);
460 if_clone_destroy(ifname);
463 rel_mplock();
464 return (0);
469 * Destroy a tap instance: the interface and the associated device.
471 static void
472 tapdestroy(struct tap_softc *sc)
474 struct ifnet *ifp = &sc->tap_if;
475 cdev_t dev = sc->tap_dev;
476 int unit = minor(dev);
478 TAPDEBUG(ifp, "destroyed, minor = %#x. Module refcnt = %d\n",
479 unit, taprefcnt);
481 ifnet_serialize_all(ifp);
482 tapifstop(sc, 1);
483 ifnet_deserialize_all(ifp);
484 ether_ifdetach(ifp);
486 sc->tap_dev = NULL;
487 dev->si_drv1 = NULL;
488 release_dev(dev); /* device disassociation */
490 /* Also destroy the cloned device */
491 destroy_dev(dev);
492 devfs_clone_bitmap_put(&DEVFS_CLONE_BITMAP(tap), unit);
494 SLIST_REMOVE(&tap_listhead, sc, tap_softc, tap_link);
495 kfree(sc, M_TAP);
500 * Destroy a tap instance that is created via ifconfig.
502 static int
503 tap_clone_destroy(struct ifnet *ifp)
505 struct tap_softc *sc = ifp->if_softc;
507 if (sc->tap_flags & TAP_OPEN)
508 return (EBUSY);
509 if ((sc->tap_flags & TAP_CLONE) == 0)
510 return (EINVAL);
512 TAPDEBUG(ifp, "clone destroyed, minor = %#x, flags = 0x%x\n",
513 minor(sc->tap_dev), sc->tap_flags);
514 tapdestroy(sc);
516 return (0);
521 * tapifinit
523 * Network interface initialization function (called with if serializer held)
525 * MPSAFE
527 static void
528 tapifinit(void *xtp)
530 struct tap_softc *sc = xtp;
531 struct ifnet *ifp = &sc->tap_if;
532 struct ifaltq_subque *ifsq = ifq_get_subq_default(&ifp->if_snd);
534 TAPDEBUG(ifp, "initializing, minor = %#x, flags = 0x%x\n",
535 minor(sc->tap_dev), sc->tap_flags);
537 ASSERT_IFNET_SERIALIZED_ALL(ifp);
539 tapifstop(sc, 1);
541 ifp->if_flags |= IFF_RUNNING;
542 ifsq_clr_oactive(ifsq);
544 /* attempt to start output */
545 tapifstart(ifp, ifsq);
548 static void
549 tapifflags(struct tap_softc *sc)
551 struct ifnet *ifp = &sc->tap_if;
553 ASSERT_IFNET_SERIALIZED_ALL(ifp);
555 if (ifp->if_flags & IFF_UP) {
556 if ((ifp->if_flags & IFF_RUNNING) == 0)
557 tapifinit(sc);
558 } else {
559 tapifstop(sc, 1);
564 * tapifioctl
566 * Process an ioctl request on network interface (called with if serializer
567 * held).
569 * MPSAFE
571 static int
572 tapifioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr)
574 struct tap_softc *sc = ifp->if_softc;
575 struct ifreq *ifr = NULL;
576 struct ifstat *ifs = NULL;
577 struct ifmediareq *ifmr = NULL;
578 int error = 0;
579 int dummy;
581 switch (cmd) {
582 case SIOCADDMULTI:
583 case SIOCDELMULTI:
584 break;
586 case SIOCSIFMTU:
587 ifr = (struct ifreq *)data;
588 ifp->if_mtu = ifr->ifr_mtu;
589 TAPDEBUG(ifp, "mtu set\n");
590 break;
592 case SIOCSIFADDR:
593 case SIOCGIFADDR:
594 error = ether_ioctl(ifp, cmd, data);
595 break;
597 case SIOCSIFFLAGS:
598 tapifflags(sc);
599 break;
601 case SIOCGIFMEDIA:
603 * The bridge code needs this when running the
604 * spanning tree protocol.
606 ifmr = (struct ifmediareq *)data;
607 dummy = ifmr->ifm_count;
608 ifmr->ifm_count = 1;
609 ifmr->ifm_status = IFM_AVALID;
610 ifmr->ifm_active = IFM_ETHER;
611 if (sc->tap_flags & TAP_OPEN)
612 ifmr->ifm_status |= IFM_ACTIVE;
613 ifmr->ifm_current = ifmr->ifm_active;
614 if (dummy >= 1) {
615 int media = IFM_ETHER;
616 error = copyout(&media, ifmr->ifm_ulist, sizeof(int));
618 break;
620 case SIOCGIFSTATUS:
621 ifs = (struct ifstat *)data;
622 dummy = strlen(ifs->ascii);
623 if ((sc->tap_flags & TAP_OPEN) && dummy < sizeof(ifs->ascii)) {
624 if (sc->tap_sigtd && sc->tap_sigtd->sio_proc) {
625 ksnprintf(ifs->ascii + dummy,
626 sizeof(ifs->ascii) - dummy,
627 "\tOpened by pid %d\n",
628 (int)sc->tap_sigtd->sio_proc->p_pid);
629 } else {
630 ksnprintf(ifs->ascii + dummy,
631 sizeof(ifs->ascii) - dummy,
632 "\tOpened by <unknown>\n");
635 break;
637 default:
638 error = EINVAL;
639 break;
642 return (error);
646 * tapifstart
648 * Queue packets from higher level ready to put out (called with if serializer
649 * held)
651 * MPSAFE
653 static void
654 tapifstart(struct ifnet *ifp, struct ifaltq_subque *ifsq)
656 struct tap_softc *sc = ifp->if_softc;
657 struct ifqueue *ifq;
658 struct mbuf *m;
659 int has_data = 0;
661 ASSERT_ALTQ_SQ_DEFAULT(ifp, ifsq);
662 TAPDEBUG(ifp, "starting, minor = %#x\n", minor(sc->tap_dev));
664 if ((sc->tap_flags & TAP_READY) != TAP_READY) {
665 TAPDEBUG(ifp, "not ready, minor = %#x, flags = 0x%x\n",
666 minor(sc->tap_dev), sc->tap_flags);
667 ifsq_purge(ifsq);
668 return;
671 ifsq_set_oactive(ifsq);
673 ifq = &sc->tap_devq;
674 while ((m = ifsq_dequeue(ifsq)) != NULL) {
675 if (IF_QFULL(ifq)) {
676 IF_DROP(ifq);
677 IFNET_STAT_INC(ifp, oerrors, 1);
678 m_freem(m);
679 } else {
680 IF_ENQUEUE(ifq, m);
681 IFNET_STAT_INC(ifp, opackets, 1);
682 has_data = 1;
686 if (has_data) {
687 if (sc->tap_flags & TAP_RWAIT) {
688 sc->tap_flags &= ~TAP_RWAIT;
689 wakeup((caddr_t)sc);
692 KNOTE(&sc->tap_rkq.ki_note, 0);
694 if ((sc->tap_flags & TAP_ASYNC) && (sc->tap_sigio != NULL)) {
695 get_mplock();
696 pgsigio(sc->tap_sigio, SIGIO, 0);
697 rel_mplock();
701 ifsq_clr_oactive(ifsq);
704 static void
705 tapifstop(struct tap_softc *sc, int clear_flags)
707 struct ifnet *ifp = &sc->tap_if;
709 ASSERT_IFNET_SERIALIZED_ALL(ifp);
710 IF_DRAIN(&sc->tap_devq);
711 sc->tap_flags &= ~TAP_CLOSEDOWN;
712 if (clear_flags) {
713 ifp->if_flags &= ~IFF_RUNNING;
714 ifsq_clr_oactive(ifq_get_subq_default(&ifp->if_snd));
719 * tapioctl
721 * The ops interface is now pretty minimal. Called via fileops with nothing
722 * held.
724 * MPSAFE
726 static int
727 tapioctl(struct dev_ioctl_args *ap)
729 cdev_t dev = ap->a_head.a_dev;
730 caddr_t data = ap->a_data;
731 struct tap_softc *sc = dev->si_drv1;
732 struct ifnet *ifp = &sc->tap_if;
733 struct ifreq *ifr;
734 struct tapinfo *tapp = NULL;
735 struct mbuf *mb;
736 int error;
738 ifnet_serialize_all(ifp);
739 error = 0;
741 switch (ap->a_cmd) {
742 case TAPSIFINFO:
743 tapp = (struct tapinfo *)data;
744 if (ifp->if_type != tapp->type)
745 return (EPROTOTYPE);
746 ifp->if_mtu = tapp->mtu;
747 ifp->if_baudrate = tapp->baudrate;
748 break;
750 case TAPGIFINFO:
751 tapp = (struct tapinfo *)data;
752 tapp->mtu = ifp->if_mtu;
753 tapp->type = ifp->if_type;
754 tapp->baudrate = ifp->if_baudrate;
755 break;
757 case TAPGIFNAME:
758 ifr = (struct ifreq *)data;
759 strlcpy(ifr->ifr_name, ifp->if_xname, IFNAMSIZ);
760 break;
762 case TAPSDEBUG:
763 tapdebug = *(int *)data;
764 break;
766 case TAPGDEBUG:
767 *(int *)data = tapdebug;
768 break;
770 case FIOASYNC:
771 if (*(int *)data)
772 sc->tap_flags |= TAP_ASYNC;
773 else
774 sc->tap_flags &= ~TAP_ASYNC;
775 break;
777 case FIONREAD:
778 /* Take a look at devq first */
779 IF_POLL(&sc->tap_devq, mb);
780 if (mb != NULL) {
781 *(int *)data = 0;
782 for(; mb != NULL; mb = mb->m_next)
783 *(int *)data += mb->m_len;
784 } else {
785 *(int *)data = ifsq_poll_pktlen(
786 ifq_get_subq_default(&ifp->if_snd));
788 break;
790 case FIOSETOWN:
791 error = fsetown(*(int *)data, &sc->tap_sigio);
792 if (error == 0)
793 error = fsetown(*(int *)data, &sc->tap_sigtd);
794 break;
796 case FIOGETOWN:
797 *(int *)data = fgetown(&sc->tap_sigio);
798 break;
800 /* this is deprecated, FIOSETOWN should be used instead */
801 case TIOCSPGRP:
802 error = fsetown(-(*(int *)data), &sc->tap_sigio);
803 break;
805 /* this is deprecated, FIOGETOWN should be used instead */
806 case TIOCGPGRP:
807 *(int *)data = -fgetown(&sc->tap_sigio);
808 break;
811 * Support basic control of the network interface via the device file.
812 * e.g., vke(4) currently uses the 'SIOCGIFADDR' ioctl.
815 case SIOCGIFFLAGS:
816 bcopy(&ifp->if_flags, data, sizeof(ifp->if_flags));
817 break;
819 case SIOCGIFADDR:
820 bcopy(sc->ether_addr, data, sizeof(sc->ether_addr));
821 break;
823 case SIOCSIFADDR:
824 bcopy(data, sc->ether_addr, sizeof(sc->ether_addr));
825 break;
827 default:
828 error = ENOTTY;
829 break;
832 ifnet_deserialize_all(ifp);
833 return (error);
838 * tapread
840 * The ops read interface - reads a packet at a time, or at
841 * least as much of a packet as can be read.
843 * Called from the fileops interface with nothing held.
845 * MPSAFE
847 static int
848 tapread(struct dev_read_args *ap)
850 cdev_t dev = ap->a_head.a_dev;
851 struct uio *uio = ap->a_uio;
852 struct tap_softc *sc = dev->si_drv1;
853 struct ifnet *ifp = &sc->tap_if;
854 struct mbuf *m0 = NULL;
855 int error = 0, len;
857 TAPDEBUG(ifp, "reading, minor = %#x\n", minor(dev));
859 if ((sc->tap_flags & TAP_READY) != TAP_READY) {
860 TAPDEBUG(ifp, "not ready, minor = %#x, flags = 0x%x\n",
861 minor(dev), sc->tap_flags);
863 return (EHOSTDOWN);
866 sc->tap_flags &= ~TAP_RWAIT;
868 /* sleep until we get a packet */
869 do {
870 ifnet_serialize_all(ifp);
871 IF_DEQUEUE(&sc->tap_devq, m0);
872 if (m0 == NULL) {
873 if (ap->a_ioflag & IO_NDELAY) {
874 ifnet_deserialize_all(ifp);
875 return (EWOULDBLOCK);
877 sc->tap_flags |= TAP_RWAIT;
878 tsleep_interlock(sc, PCATCH);
879 ifnet_deserialize_all(ifp);
880 error = tsleep(sc, PCATCH | PINTERLOCKED, "taprd", 0);
881 if (error)
882 return (error);
883 } else {
884 ifnet_deserialize_all(ifp);
886 } while (m0 == NULL);
888 BPF_MTAP(ifp, m0);
890 /* xfer packet to user space */
891 while ((m0 != NULL) && (uio->uio_resid > 0) && (error == 0)) {
892 len = (int)szmin(uio->uio_resid, m0->m_len);
893 if (len == 0)
894 break;
896 error = uiomove(mtod(m0, caddr_t), (size_t)len, uio);
897 m0 = m_free(m0);
900 if (m0 != NULL) {
901 TAPDEBUG(ifp, "dropping mbuf, minor = %#x\n", minor(dev));
902 m_freem(m0);
905 return (error);
909 * tapwrite
911 * The ops write interface - an atomic write is a packet - or else!
913 * Called from the fileops interface with nothing held.
915 * MPSAFE
917 static int
918 tapwrite(struct dev_write_args *ap)
920 cdev_t dev = ap->a_head.a_dev;
921 struct uio *uio = ap->a_uio;
922 struct tap_softc *sc = dev->si_drv1;
923 struct ifnet *ifp = &sc->tap_if;
924 struct mbuf *top = NULL, **mp = NULL, *m = NULL;
925 int error;
926 size_t tlen, mlen;
928 TAPDEBUG(ifp, "writing, minor = %#x\n", minor(dev));
930 if ((sc->tap_flags & TAP_READY) != TAP_READY) {
931 TAPDEBUG(ifp, "not ready, minor = %#x, flags = 0x%x\n",
932 minor(dev), sc->tap_flags);
933 return (EHOSTDOWN);
936 if (uio->uio_resid == 0)
937 return (0);
939 if (uio->uio_resid > TAPMRU) {
940 TAPDEBUG(ifp, "invalid packet len = %zu, minor = %#x\n",
941 uio->uio_resid, minor(dev));
943 return (EIO);
945 tlen = uio->uio_resid;
947 /* get a header mbuf */
948 MGETHDR(m, M_WAITOK, MT_DATA);
949 mlen = MHLEN;
951 top = NULL;
952 mp = &top;
953 error = 0;
955 while (error == 0 && uio->uio_resid > 0) {
956 m->m_len = (int)szmin(mlen, uio->uio_resid);
957 error = uiomove(mtod(m, caddr_t), (size_t)m->m_len, uio);
958 *mp = m;
959 mp = &m->m_next;
960 if (uio->uio_resid > 0) {
961 MGET(m, M_WAITOK, MT_DATA);
962 mlen = MLEN;
965 if (error) {
966 IFNET_STAT_INC(ifp, ierrors, 1);
967 if (top)
968 m_freem(top);
969 return (error);
972 top->m_pkthdr.len = (int)tlen;
973 top->m_pkthdr.rcvif = ifp;
976 * Ethernet bridge and bpf are handled in ether_input
978 * adjust mbuf and give packet to the ether_input
980 ifnet_serialize_all(ifp);
981 ifp->if_input(ifp, top, NULL, -1);
982 IFNET_STAT_INC(ifp, ipackets, 1); /* ibytes are counted in ether_input */
983 ifnet_deserialize_all(ifp);
985 return (0);
990 * tapkqfilter - called from the fileops interface with nothing held
992 * MPSAFE
994 static int
995 tapkqfilter(struct dev_kqfilter_args *ap)
997 cdev_t dev = ap->a_head.a_dev;
998 struct knote *kn = ap->a_kn;
999 struct tap_softc *sc = dev->si_drv1;
1000 struct klist *list;
1002 list = &sc->tap_rkq.ki_note;
1003 ap->a_result =0;
1005 switch (kn->kn_filter) {
1006 case EVFILT_READ:
1007 kn->kn_fop = &tapread_filtops;
1008 kn->kn_hook = (void *)sc;
1009 break;
1010 case EVFILT_WRITE:
1011 kn->kn_fop = &tapwrite_filtops;
1012 kn->kn_hook = (void *)sc;
1013 break;
1014 default:
1015 ap->a_result = EOPNOTSUPP;
1016 return (0);
1019 knote_insert(list, kn);
1020 return (0);
1023 static int
1024 tap_filter_read(struct knote *kn, long hint)
1026 struct tap_softc *sc = (struct tap_softc *)kn->kn_hook;
1028 if (IF_QEMPTY(&sc->tap_devq) == 0) /* XXX serializer */
1029 return (1);
1030 else
1031 return (0);
1034 static int
1035 tap_filter_write(struct knote *kn, long hint)
1037 /* Always ready for a write */
1038 return (1);
1041 static void
1042 tap_filter_detach(struct knote *kn)
1044 struct tap_softc *sc = (struct tap_softc *)kn->kn_hook;
1046 knote_remove(&sc->tap_rkq.ki_note, kn);