kernel - Fix kqfilter error return codes
[dragonfly.git] / sys / net / tap / if_tap.c
1 /*
2  * Copyright (C) 1999-2000 by Maksim Yevmenkin <m_evmenkin@yahoo.com>
3  * All rights reserved.
4  *
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.
13  *
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.
25  *
26  * BASED ON:
27  * -------------------------------------------------------------------------
28  *
29  * Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk>
30  * Nottingham University 1987.
31  */
32
33 /*
34  * $FreeBSD: src/sys/net/if_tap.c,v 1.3.2.3 2002/04/14 21:41:48 luigi Exp $
35  * $DragonFly: src/sys/net/tap/if_tap.c,v 1.41 2008/09/05 17:03:15 dillon Exp $
36  * $Id: if_tap.c,v 0.21 2000/07/23 21:46:02 max Exp $
37  */
38
39 #include "opt_inet.h"
40
41 #include <sys/param.h>
42 #include <sys/conf.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>
48 #include <sys/mbuf.h>
49 #include <sys/poll.h>
50 #include <sys/proc.h>
51 #include <sys/priv.h>
52 #include <sys/signalvar.h>
53 #include <sys/socket.h>
54 #include <sys/sockio.h>
55 #include <sys/sysctl.h>
56 #include <sys/systm.h>
57 #include <sys/ttycom.h>
58 #include <sys/uio.h>
59 #include <sys/vnode.h>
60 #include <sys/serialize.h>
61
62 #include <sys/thread2.h>
63 #include <sys/mplock2.h>
64
65 #include <net/bpf.h>
66 #include <net/ethernet.h>
67 #include <net/if.h>
68 #include <net/ifq_var.h>
69 #include <net/if_arp.h>
70 #include <net/if_clone.h>
71 #include <net/route.h>
72 #include <sys/devfs.h>
73
74 #include <netinet/in.h>
75
76 #include "if_tapvar.h"
77 #include "if_tap.h"
78
79 #define TAP_IFFLAGS     (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST)
80
81 #define TAP_PREALLOCATED_UNITS  4
82
83 #define CDEV_NAME       "tap"
84 #define CDEV_MAJOR      149
85 #define TAPDEBUG        if (tapdebug) if_printf
86
87 #define TAP             "tap"
88 #define VMNET           "vmnet"
89 #define VMNET_DEV_MASK  0x00010000
90
91 DEVFS_DECLARE_CLONE_BITMAP(tap);
92
93 /* module */
94 static int              tapmodevent     (module_t, int, void *);
95
96 /* device */
97 static struct tap_softc *tapcreate(int, cdev_t);
98 static void             tapdestroy(struct tap_softc *);
99
100 /* clone */
101 static int              tap_clone_create(struct if_clone *, int, caddr_t);
102 static void             tap_clone_destroy(struct ifnet *);
103
104
105 /* network interface */
106 static void             tapifstart      (struct ifnet *);
107 static int              tapifioctl      (struct ifnet *, u_long, caddr_t,
108                                          struct ucred *);
109 static void             tapifinit       (void *);
110 static void             tapifstop(struct tap_softc *, int);
111 static void             tapifflags(struct tap_softc *);
112
113 /* character device */
114 static d_open_t         tapopen;
115 static d_clone_t        tapclone;
116 static d_close_t        tapclose;
117 static d_read_t         tapread;
118 static d_write_t        tapwrite;
119 static d_ioctl_t        tapioctl;
120 static d_poll_t         tappoll;
121 static d_kqfilter_t     tapkqfilter;
122
123 static struct dev_ops   tap_ops = {
124         { CDEV_NAME, CDEV_MAJOR, 0 },
125         .d_open =       tapopen,
126         .d_close =      tapclose,
127         .d_read =       tapread,
128         .d_write =      tapwrite,
129         .d_ioctl =      tapioctl,
130         .d_poll =       tappoll,
131         .d_kqfilter =   tapkqfilter
132 };
133
134 static int              taprefcnt = 0;          /* module ref. counter   */
135 static int              taplastunit = -1;       /* max. open unit number */
136 static int              tapdebug = 0;           /* debug flag            */
137 static int              tapuopen = 0;           /* all user open()       */
138 static int              tapuponopen = 0;        /* IFF_UP       */
139
140 MALLOC_DECLARE(M_TAP);
141 MALLOC_DEFINE(M_TAP, CDEV_NAME, "Ethernet tunnel interface");
142 struct if_clone tap_cloner = IF_CLONE_INITIALIZER("tap",
143                              tap_clone_create, tap_clone_destroy,
144                              0, IF_MAXUNIT);
145 static SLIST_HEAD(,tap_softc) tap_listhead =
146         SLIST_HEAD_INITIALIZER(&tap_listhead);
147
148 SYSCTL_INT(_debug, OID_AUTO, if_tap_debug, CTLFLAG_RW, &tapdebug, 0, "");
149 SYSCTL_DECL(_net_link);
150 SYSCTL_NODE(_net_link, OID_AUTO, tap, CTLFLAG_RW, 0,
151             "Ethernet tunnel software network interface");
152 SYSCTL_INT(_net_link_tap, OID_AUTO, user_open, CTLFLAG_RW, &tapuopen, 0,
153            "Allow user to open /dev/tap (based on node permissions)");
154 SYSCTL_INT(_net_link_tap, OID_AUTO, up_on_open, CTLFLAG_RW, &tapuponopen, 0,
155            "Bring interface up when /dev/tap is opened");
156 SYSCTL_INT(_net_link_tap, OID_AUTO, debug, CTLFLAG_RW, &tapdebug, 0, "");
157
158 DEV_MODULE(if_tap, tapmodevent, NULL);
159
160 /*
161  * tapmodevent
162  *
163  * module event handler
164  */
165 static int
166 tapmodevent(module_t mod, int type, void *data)
167 {
168         static int attached = 0;
169         struct tap_softc *tp, *ntp;
170         int i;
171
172         switch (type) {
173         case MOD_LOAD:
174                 if (attached)
175                         return (EEXIST);
176
177                 make_autoclone_dev(&tap_ops, &DEVFS_CLONE_BITMAP(tap), tapclone,
178                                    UID_ROOT, GID_WHEEL, 0600, "tap");
179                 SLIST_INIT(&tap_listhead);
180                 if_clone_attach(&tap_cloner);
181
182                 for (i = 0; i < TAP_PREALLOCATED_UNITS; ++i) {
183                         make_dev(&tap_ops, i, UID_ROOT, GID_WHEEL,
184                                  0600, "tap%d", i);
185                         devfs_clone_bitmap_set(&DEVFS_CLONE_BITMAP(tap), i);
186                 }
187
188                 attached = 1;
189                 break;
190
191         case MOD_UNLOAD:
192                 if (taprefcnt > 0)
193                         return (EBUSY);
194
195                 if_clone_detach(&tap_cloner);
196
197                 /* Maintain tap ifs in a local list */
198                 SLIST_FOREACH_MUTABLE(tp, &tap_listhead, tap_link, ntp)
199                         tapdestroy(tp);
200
201                 attached = 0;
202
203                 devfs_clone_handler_del("tap");
204                 dev_ops_remove_all(&tap_ops);
205                 devfs_clone_bitmap_uninit(&DEVFS_CLONE_BITMAP(tap));
206                 break;
207
208         default:
209                 return (EOPNOTSUPP);
210         }
211
212         return (0);
213 } /* tapmodevent */
214
215
216 /*
217  * tapcreate - create or clone an interface
218  */
219 static struct tap_softc *
220 tapcreate(int unit, cdev_t dev)
221 {
222         const char      *name = TAP;
223         struct ifnet    *ifp;
224         struct tap_softc *tp;
225         uint8_t         ether_addr[ETHER_ADDR_LEN];
226
227         tp = kmalloc(sizeof(*tp), M_TAP, M_WAITOK | M_ZERO);
228         dev->si_drv1 = tp;
229         tp->tap_dev = dev;
230         tp->tap_unit = unit;
231
232         reference_dev(dev);     /* tp association */
233
234         /* generate fake MAC address: 00 bd xx xx xx unit_no */
235         ether_addr[0] = 0x00;
236         ether_addr[1] = 0xbd;
237         bcopy(&ticks, &ether_addr[2], 3);
238         ether_addr[5] = (u_char)unit;
239
240         /* fill the rest and attach interface */        
241         ifp = &tp->tap_if;
242         ifp->if_softc = tp;
243
244         if_initname(ifp, name, unit);
245         if (unit > taplastunit)
246                 taplastunit = unit;
247
248         ifp->if_init = tapifinit;
249         ifp->if_start = tapifstart;
250         ifp->if_ioctl = tapifioctl;
251         ifp->if_mtu = ETHERMTU;
252         ifp->if_flags = TAP_IFFLAGS;
253         ifq_set_maxlen(&ifp->if_snd, ifqmaxlen);
254         ifq_set_ready(&ifp->if_snd);
255
256         ether_ifattach(ifp, ether_addr, NULL);
257
258         tp->tap_flags |= TAP_INITED;
259         tp->tap_devq.ifq_maxlen = ifqmaxlen;
260
261         SLIST_INSERT_HEAD(&tap_listhead, tp, tap_link);
262
263         TAPDEBUG(ifp, "created. minor = %#x\n", minor(dev));
264         return (tp);
265 }
266
267 static
268 struct tap_softc *
269 tapfind(int unit)
270 {
271         struct tap_softc *tp;
272
273         SLIST_FOREACH(tp, &tap_listhead, tap_link) {
274                 if (tp->tap_unit == unit)
275                         return(tp);
276         }
277         return (NULL);
278 }
279
280 /*
281  * tap_clone_create:
282  *
283  * Create a new tap instance via ifconfig.
284  */
285 static int
286 tap_clone_create(struct if_clone *ifc __unused, int unit,
287     caddr_t param __unused)
288 {
289         struct tap_softc *tp;
290         cdev_t dev;
291
292         tp = tapfind(unit);
293         if (tp == NULL) {
294                 if (!devfs_clone_bitmap_chk(&DEVFS_CLONE_BITMAP(tap), unit)) {
295                         devfs_clone_bitmap_set(&DEVFS_CLONE_BITMAP(tap), unit);
296                         dev = make_dev(&tap_ops, unit, UID_ROOT, GID_WHEEL,
297                                            0600, "%s%d", TAP, unit);
298                 } else {
299                         dev = devfs_find_device_by_name("%s%d", TAP, unit);
300                 }
301
302                 KKASSERT(dev != NULL);
303                 tp = tapcreate(unit, dev);
304         }
305         tp->tap_flags |= TAP_CLONE;
306         TAPDEBUG(&tp->tap_if, "clone created. minor = %#x tap_flags = 0x%x\n",
307                  minor(tp->tap_dev), tp->tap_flags);
308
309         return (0);
310 }
311
312 /*
313  * tapopen 
314  *
315  * to open tunnel. must be superuser
316  */
317 static int
318 tapopen(struct dev_open_args *ap)
319 {
320         cdev_t dev = NULL;
321         struct tap_softc *tp = NULL;
322         struct ifnet *ifp = NULL;
323         int error;
324
325         if (tapuopen == 0 && 
326             (error = priv_check_cred(ap->a_cred, PRIV_ROOT, 0)) != 0)
327                 return (error);
328
329         get_mplock();
330         dev = ap->a_head.a_dev;
331         tp = dev->si_drv1;
332         if (tp == NULL)
333                 tp = tapcreate(minor(dev), dev);
334         if (tp->tap_flags & TAP_OPEN) {
335                 rel_mplock();
336                 return (EBUSY);
337         }
338         ifp = &tp->arpcom.ac_if;
339
340         if ((tp->tap_flags & TAP_CLONE) == 0) {
341                 EVENTHANDLER_INVOKE(ifnet_attach_event, ifp);
342
343                 /* Announce the return of the interface. */
344                 rt_ifannouncemsg(ifp, IFAN_ARRIVAL);
345         }
346
347         bcopy(tp->arpcom.ac_enaddr, tp->ether_addr, sizeof(tp->ether_addr));
348
349         if (curthread->td_proc)
350                 fsetown(curthread->td_proc->p_pid, &tp->tap_sigtd);
351         tp->tap_flags |= TAP_OPEN;
352         taprefcnt ++;
353
354         if (tapuponopen && (ifp->if_flags & IFF_UP) == 0) {
355                 crit_enter();
356                 if_up(ifp);
357                 crit_exit();
358
359                 ifnet_serialize_all(ifp);
360                 tapifflags(tp);
361                 ifnet_deserialize_all(ifp);
362
363                 tp->tap_flags |= TAP_CLOSEDOWN;
364         }
365
366         TAPDEBUG(ifp, "opened. minor = %#x, refcnt = %d, taplastunit = %d\n",
367                  minor(tp->tap_dev), taprefcnt, taplastunit);
368
369         rel_mplock();
370         return (0);
371 }
372
373 static int
374 tapclone(struct dev_clone_args *ap)
375 {
376         int unit;
377
378         unit = devfs_clone_bitmap_get(&DEVFS_CLONE_BITMAP(tap), 0);
379         ap->a_dev = make_only_dev(&tap_ops, unit, UID_ROOT, GID_WHEEL,
380                                   0600, "%s%d", TAP, unit);
381         tapcreate(unit, ap->a_dev);
382         return (0);
383 }
384
385 /*
386  * tapclose
387  *
388  * close the device - mark i/f down & delete routing info
389  */
390 static int
391 tapclose(struct dev_close_args *ap)
392 {
393         cdev_t dev = ap->a_head.a_dev;
394         struct tap_softc *tp = dev->si_drv1;
395         struct ifnet *ifp = &tp->tap_if;
396         int clear_flags = 0;
397
398         get_mplock();
399
400         /* Junk all pending output */
401         ifq_purge(&ifp->if_snd);
402
403         /*
404          * Do not bring the interface down, and do not anything with
405          * interface, if we are in VMnet mode. just close the device.
406          *
407          * If the interface is not cloned, we always bring it down.
408          *
409          * If the interface is cloned, then we bring it down during
410          * closing only if it was brought up during opening.
411          */
412         if ((tp->tap_flags & TAP_VMNET) == 0 &&
413             ((tp->tap_flags & TAP_CLONE) == 0 ||
414              (tp->tap_flags & TAP_CLOSEDOWN))) {
415                 if (ifp->if_flags & IFF_UP)
416                         if_down(ifp);
417                 clear_flags = 1;
418         }
419         ifnet_serialize_all(ifp);
420         tapifstop(tp, clear_flags);
421         ifnet_deserialize_all(ifp);
422
423         if ((tp->tap_flags & TAP_CLONE) == 0) {
424                 if_purgeaddrs_nolink(ifp);
425
426                 EVENTHANDLER_INVOKE(ifnet_detach_event, ifp);
427
428                 /* Announce the departure of the interface. */
429                 rt_ifannouncemsg(ifp, IFAN_DEPARTURE);
430         }
431
432         funsetown(tp->tap_sigio);
433         tp->tap_sigio = NULL;
434         selwakeup(&tp->tap_rsel);
435
436         tp->tap_flags &= ~TAP_OPEN;
437         funsetown(tp->tap_sigtd);
438         tp->tap_sigtd = NULL;
439
440         taprefcnt --;
441         if (taprefcnt < 0) {
442                 taprefcnt = 0;
443                 if_printf(ifp, "minor = %#x, refcnt = %d is out of sync. "
444                         "set refcnt to 0\n", minor(tp->tap_dev), taprefcnt);
445         }
446
447         TAPDEBUG(ifp, "closed. minor = %#x, refcnt = %d, taplastunit = %d\n",
448                  minor(tp->tap_dev), taprefcnt, taplastunit);
449
450         if (tp->tap_unit >= TAP_PREALLOCATED_UNITS)
451                 tapdestroy(tp);
452
453         rel_mplock();
454         return (0);
455 }
456
457 /*
458  * tapdestroy:
459  *
460  *      Destroy a tap instance.
461  */
462 static void
463 tapdestroy(struct tap_softc *tp)
464 {
465         struct ifnet *ifp = &tp->arpcom.ac_if;
466         cdev_t dev;
467
468         TAPDEBUG(ifp, "destroyed. minor = %#x, refcnt = %d, taplastunit = %d\n",
469                  minor(tp->tap_dev), taprefcnt, taplastunit);
470
471         ifnet_serialize_all(ifp);
472         tapifstop(tp, 1);
473         ifnet_deserialize_all(ifp);
474
475         ether_ifdetach(ifp);
476         SLIST_REMOVE(&tap_listhead, tp, tap_softc, tap_link);
477
478         dev = tp->tap_dev;
479         tp->tap_dev = NULL;
480         dev->si_drv1 = NULL;
481
482         release_dev(dev);       /* tp association */
483
484         /*
485          * Also destroy the cloned device
486          */
487         if (tp->tap_unit >= TAP_PREALLOCATED_UNITS) {
488                 destroy_dev(dev);
489                 devfs_clone_bitmap_put(&DEVFS_CLONE_BITMAP(tap), tp->tap_unit);
490         }
491
492         kfree(tp, M_TAP);
493
494         taplastunit--;
495 }
496
497 /*
498  * tap_clone_destroy:
499  *
500  *      Destroy a tap instance.
501  */
502 static void
503 tap_clone_destroy(struct ifnet *ifp)
504 {
505         struct tap_softc *tp = ifp->if_softc;
506         
507         TAPDEBUG(&tp->tap_if, "clone destroyed. minor = %#x tap_flags = 0x%x\n",
508                  minor(tp->tap_dev), tp->tap_flags);
509         if (tp->tap_flags & TAP_CLONE)
510                 tapdestroy(tp);
511 }
512
513 /*
514  * tapifinit
515  *
516  * Network interface initialization function (called with if serializer held)
517  *
518  * MPSAFE
519  */
520 static void
521 tapifinit(void *xtp)
522 {
523         struct tap_softc *tp = xtp;
524         struct ifnet *ifp = &tp->tap_if;
525
526         TAPDEBUG(ifp, "initializing, minor = %#x tap_flags = 0x%x\n",
527                  minor(tp->tap_dev), tp->tap_flags);
528
529         ASSERT_IFNET_SERIALIZED_ALL(ifp);
530
531         tapifstop(tp, 1);
532
533         ifp->if_flags |= IFF_RUNNING;
534         ifp->if_flags &= ~IFF_OACTIVE;
535
536         /* attempt to start output */
537         tapifstart(ifp);
538 }
539
540
541 /*
542  * tapifioctl
543  *
544  * Process an ioctl request on network interface (called with if serializer
545  * held).
546  *
547  * MPSAFE
548  */
549 static int
550 tapifioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr)
551 {
552         struct tap_softc        *tp = (struct tap_softc *)(ifp->if_softc);
553         struct ifstat           *ifs = NULL;
554         int                      dummy;
555
556         switch (cmd) {
557                 case SIOCSIFADDR:
558                 case SIOCGIFADDR:
559                 case SIOCSIFMTU:
560                         dummy = ether_ioctl(ifp, cmd, data);
561                         return (dummy);
562
563                 case SIOCSIFFLAGS:
564                         tapifflags(tp);
565                         break;
566
567                 case SIOCADDMULTI: /* XXX -- just like vmnet does */
568                 case SIOCDELMULTI:
569                         break;
570
571                 case SIOCGIFSTATUS:
572                         ifs = (struct ifstat *)data;
573                         dummy = strlen(ifs->ascii);
574                         if ((tp->tap_flags & TAP_OPEN) &&
575                             dummy < sizeof(ifs->ascii)) {
576                                 if (tp->tap_sigtd && tp->tap_sigtd->sio_proc) {
577                                     ksnprintf(ifs->ascii + dummy,
578                                         sizeof(ifs->ascii) - dummy,
579                                         "\tOpened by pid %d\n",
580                                         (int)tp->tap_sigtd->sio_proc->p_pid);
581                                 } else {
582                                     ksnprintf(ifs->ascii + dummy,
583                                         sizeof(ifs->ascii) - dummy,
584                                         "\tOpened by <unknown>\n");
585                                 }
586                         }
587                         break;
588
589                 default:
590                         return (EINVAL);
591         }
592
593         return (0);
594 }
595
596
597 /*
598  * tapifstart 
599  * 
600  * Queue packets from higher level ready to put out (called with if serializer
601  * held)
602  *
603  * MPSAFE
604  */
605 static void
606 tapifstart(struct ifnet *ifp)
607 {
608         struct tap_softc *tp = ifp->if_softc;
609         struct ifqueue *ifq;
610         struct mbuf *m;
611         int has_data = 0;
612
613         TAPDEBUG(ifp, "starting, minor = %#x\n", minor(tp->tap_dev));
614
615         /*
616          * do not junk pending output if we are in VMnet mode.
617          * XXX: can this do any harm because of queue overflow?
618          */
619
620         if (((tp->tap_flags & TAP_VMNET) == 0) && 
621             ((tp->tap_flags & TAP_READY) != TAP_READY)) {
622                 TAPDEBUG(ifp, "not ready. minor = %#x, tap_flags = 0x%x\n",
623                          minor(tp->tap_dev), tp->tap_flags);
624                 ifq_purge(&ifp->if_snd);
625                 return;
626         }
627
628         ifp->if_flags |= IFF_OACTIVE;
629
630         ifq = &tp->tap_devq;
631         while ((m = ifq_dequeue(&ifp->if_snd, NULL)) != NULL) {
632                 if (IF_QFULL(ifq)) {
633                         IF_DROP(ifq);
634                         ifp->if_oerrors++;
635                         m_freem(m);
636                 } else {
637                         IF_ENQUEUE(ifq, m);
638                         ifp->if_opackets++;
639                         has_data = 1;
640                 }
641         }
642
643         if (has_data) {
644                 if (tp->tap_flags & TAP_RWAIT) {
645                         tp->tap_flags &= ~TAP_RWAIT;
646                         wakeup((caddr_t)tp);
647                 }
648
649                 get_mplock();
650                 KNOTE(&tp->tap_rsel.si_note, 0);
651                 rel_mplock();
652
653                 if ((tp->tap_flags & TAP_ASYNC) && (tp->tap_sigio != NULL)) {
654                         get_mplock();
655                         pgsigio(tp->tap_sigio, SIGIO, 0);
656                         rel_mplock();
657                 }
658
659                 /*
660                  * selwakeup is not MPSAFE.  tapifstart is.
661                  */
662                 get_mplock();
663                 selwakeup(&tp->tap_rsel);
664                 rel_mplock();
665         }
666
667         ifp->if_flags &= ~IFF_OACTIVE;
668 }
669
670
671 /*
672  * tapioctl
673  *
674  * The ops interface is now pretty minimal.  Called via fileops with nothing
675  * held.
676  *
677  * MPSAFE
678  */
679 static int
680 tapioctl(struct dev_ioctl_args *ap)
681 {
682         cdev_t dev = ap->a_head.a_dev;
683         caddr_t data = ap->a_data;
684         struct tap_softc        *tp = dev->si_drv1;
685         struct ifnet            *ifp = &tp->tap_if;
686         struct tapinfo          *tapp = NULL;
687         struct mbuf *mb;
688         short f;
689         int error;
690
691         ifnet_serialize_all(ifp);
692         error = 0;
693
694         switch (ap->a_cmd) {
695         case TAPSIFINFO:
696                 tapp = (struct tapinfo *)data;
697                 ifp->if_mtu = tapp->mtu;
698                 ifp->if_type = tapp->type;
699                 ifp->if_baudrate = tapp->baudrate;
700                 break;
701
702         case TAPGIFINFO:
703                 tapp = (struct tapinfo *)data;
704                 tapp->mtu = ifp->if_mtu;
705                 tapp->type = ifp->if_type;
706                 tapp->baudrate = ifp->if_baudrate;
707                 break;
708
709         case TAPSDEBUG:
710                 tapdebug = *(int *)data;
711                 break;
712
713         case TAPGDEBUG:
714                 *(int *)data = tapdebug;
715                 break;
716
717         case FIOASYNC:
718                 if (*(int *)data)
719                         tp->tap_flags |= TAP_ASYNC;
720                 else
721                         tp->tap_flags &= ~TAP_ASYNC;
722                 break;
723
724         case FIONREAD:
725                 *(int *)data = 0;
726
727                 /* Take a look at devq first */
728                 IF_POLL(&tp->tap_devq, mb);
729                 if (mb == NULL)
730                         mb = ifq_poll(&ifp->if_snd);
731
732                 if (mb != NULL) {
733                         for(; mb != NULL; mb = mb->m_next)
734                                 *(int *)data += mb->m_len;
735                 } 
736                 break;
737
738         case FIOSETOWN:
739                 error = fsetown(*(int *)data, &tp->tap_sigio);
740                 break;
741
742         case FIOGETOWN:
743                 *(int *)data = fgetown(tp->tap_sigio);
744                 break;
745
746         /* this is deprecated, FIOSETOWN should be used instead */
747         case TIOCSPGRP:
748                 error = fsetown(-(*(int *)data), &tp->tap_sigio);
749                 break;
750
751         /* this is deprecated, FIOGETOWN should be used instead */
752         case TIOCGPGRP:
753                 *(int *)data = -fgetown(tp->tap_sigio);
754                 break;
755
756         /* VMware/VMnet port ioctl's */
757
758         case SIOCGIFFLAGS:      /* get ifnet flags */
759                 bcopy(&ifp->if_flags, data, sizeof(ifp->if_flags));
760                 break;
761
762         case VMIO_SIOCSIFFLAGS: /* VMware/VMnet SIOCSIFFLAGS */
763                 f = *(short *)data;
764                 f &= 0x0fff;
765                 f &= ~IFF_CANTCHANGE;
766                 f |= IFF_UP;
767                 ifp->if_flags = f | (ifp->if_flags & IFF_CANTCHANGE);
768                 break;
769
770         case OSIOCGIFADDR:      /* get MAC address of the remote side */
771         case SIOCGIFADDR:
772                 bcopy(tp->ether_addr, data, sizeof(tp->ether_addr));
773                 break;
774
775         case SIOCSIFADDR:       /* set MAC address of the remote side */
776                 bcopy(data, tp->ether_addr, sizeof(tp->ether_addr));
777                 break;
778
779         default:
780                 error = ENOTTY;
781                 break;
782         }
783         ifnet_deserialize_all(ifp);
784         return (error);
785 }
786
787
788 /*
789  * tapread
790  *
791  * The ops read interface - reads a packet at a time, or at
792  * least as much of a packet as can be read.
793  *
794  * Called from the fileops interface with nothing held.
795  *
796  * MPSAFE
797  */
798 static int
799 tapread(struct dev_read_args *ap)
800 {
801         cdev_t dev = ap->a_head.a_dev;
802         struct uio *uio = ap->a_uio;
803         struct tap_softc        *tp = dev->si_drv1;
804         struct ifnet            *ifp = &tp->tap_if;
805         struct mbuf             *m0 = NULL;
806         int                      error = 0, len;
807
808         TAPDEBUG(ifp, "reading, minor = %#x\n", minor(tp->tap_dev));
809
810         if ((tp->tap_flags & TAP_READY) != TAP_READY) {
811                 TAPDEBUG(ifp, "not ready. minor = %#x, tap_flags = 0x%x\n",
812                          minor(tp->tap_dev), tp->tap_flags);
813
814                 return (EHOSTDOWN);
815         }
816
817         tp->tap_flags &= ~TAP_RWAIT;
818
819         /* sleep until we get a packet */
820         do {
821                 ifnet_serialize_all(ifp);
822                 IF_DEQUEUE(&tp->tap_devq, m0);
823                 if (m0 == NULL) {
824                         if (ap->a_ioflag & IO_NDELAY) {
825                                 ifnet_deserialize_all(ifp);
826                                 return (EWOULDBLOCK);
827                         }
828                         tp->tap_flags |= TAP_RWAIT;
829                         tsleep_interlock(tp, PCATCH);
830                         ifnet_deserialize_all(ifp);
831                         error = tsleep(tp, PCATCH | PINTERLOCKED, "taprd", 0);
832                         if (error)
833                                 return (error);
834                 } else {
835                         ifnet_deserialize_all(ifp);
836                 }
837         } while (m0 == NULL);
838
839         BPF_MTAP(ifp, m0);
840
841         /* xfer packet to user space */
842         while ((m0 != NULL) && (uio->uio_resid > 0) && (error == 0)) {
843                 len = (int)szmin(uio->uio_resid, m0->m_len);
844                 if (len == 0)
845                         break;
846
847                 error = uiomove(mtod(m0, caddr_t), (size_t)len, uio);
848                 m0 = m_free(m0);
849         }
850
851         if (m0 != NULL) {
852                 TAPDEBUG(ifp, "dropping mbuf, minor = %#x\n",
853                          minor(tp->tap_dev));
854                 m_freem(m0);
855         }
856
857         return (error);
858 }
859
860 /*
861  * tapwrite
862  *
863  * The ops write interface - an atomic write is a packet - or else!
864  *
865  * Called from the fileops interface with nothing held.
866  *
867  * MPSAFE
868  */
869 static int
870 tapwrite(struct dev_write_args *ap)
871 {
872         cdev_t dev = ap->a_head.a_dev;
873         struct uio *uio = ap->a_uio;
874         struct tap_softc        *tp = dev->si_drv1;
875         struct ifnet            *ifp = &tp->tap_if;
876         struct mbuf             *top = NULL, **mp = NULL, *m = NULL;
877         int                     error = 0;
878         size_t                  tlen, mlen;
879
880         TAPDEBUG(ifp, "writing, minor = %#x\n", minor(tp->tap_dev));
881
882         if ((tp->tap_flags & TAP_READY) != TAP_READY) {
883                 TAPDEBUG(ifp, "not ready. minor = %#x, tap_flags = 0x%x\n",
884                          minor(tp->tap_dev), tp->tap_flags);
885                 return (EHOSTDOWN);
886         }
887
888         if (uio->uio_resid == 0)
889                 return (0);
890
891         if (uio->uio_resid > TAPMRU) {
892                 TAPDEBUG(ifp, "invalid packet len = %zu, minor = %#x\n",
893                          uio->uio_resid, minor(tp->tap_dev));
894
895                 return (EIO);
896         }
897         tlen = uio->uio_resid;
898
899         /* get a header mbuf */
900         MGETHDR(m, MB_DONTWAIT, MT_DATA);
901         if (m == NULL)
902                 return (ENOBUFS);
903         mlen = MHLEN;
904
905         top = 0;
906         mp = &top;
907         while ((error == 0) && (uio->uio_resid > 0)) {
908                 m->m_len = (int)szmin(mlen, uio->uio_resid);
909                 error = uiomove(mtod(m, caddr_t), (size_t)m->m_len, uio);
910                 *mp = m;
911                 mp = &m->m_next;
912                 if (uio->uio_resid > 0) {
913                         MGET(m, MB_DONTWAIT, MT_DATA);
914                         if (m == NULL) {
915                                 error = ENOBUFS;
916                                 break;
917                         }
918                         mlen = MLEN;
919                 }
920         }
921         if (error) {
922                 ifp->if_ierrors ++;
923                 if (top)
924                         m_freem(top);
925                 return (error);
926         }
927
928         top->m_pkthdr.len = (int)tlen;
929         top->m_pkthdr.rcvif = ifp;
930         
931         /*
932          * Ethernet bridge and bpf are handled in ether_input
933          *
934          * adjust mbuf and give packet to the ether_input
935          */
936         ifnet_serialize_all(ifp);
937         ifp->if_input(ifp, top);
938         ifp->if_ipackets ++; /* ibytes are counted in ether_input */
939         ifnet_deserialize_all(ifp);
940
941         return (0);
942 }
943
944 /*
945  * tappoll
946  *
947  * The poll interface, this is only useful on reads really. The write
948  * detect always returns true, write never blocks anyway, it either
949  * accepts the packet or drops it
950  *
951  * Called from the fileops interface with nothing held.
952  *
953  * MPSAFE
954  */
955 static int
956 tappoll(struct dev_poll_args *ap)
957 {
958         cdev_t dev = ap->a_head.a_dev;
959         struct tap_softc        *tp = dev->si_drv1;
960         struct ifnet            *ifp = &tp->tap_if;
961         int                      revents = 0;
962
963         TAPDEBUG(ifp, "polling, minor = %#x\n", minor(tp->tap_dev));
964
965         if (ap->a_events & (POLLIN | POLLRDNORM)) {
966                 if (!IF_QEMPTY(&tp->tap_devq)) {
967                         TAPDEBUG(ifp,
968                                  "has data in queue. minor = %#x\n",
969                                  minor(tp->tap_dev));
970
971                         revents |= (ap->a_events & (POLLIN | POLLRDNORM));
972                 } else {
973                         TAPDEBUG(ifp, "waiting for data, minor = %#x\n",
974                                  minor(tp->tap_dev));
975
976                         get_mplock();
977                         selrecord(curthread, &tp->tap_rsel);
978                         rel_mplock();
979                 }
980         }
981
982         if (ap->a_events & (POLLOUT | POLLWRNORM))
983                 revents |= (ap->a_events & (POLLOUT | POLLWRNORM));
984         ap->a_events = revents;
985         return (0);
986 }
987
988 /*
989  * tapkqfilter - called from the fileops interface with nothing held
990  *
991  * MPSAFE
992  */
993 static int filt_tapread(struct knote *kn, long hint);
994 static void filt_tapdetach(struct knote *kn);
995 static struct filterops tapread_filtops =
996         { 1, NULL, filt_tapdetach, filt_tapread };
997
998 static int
999 tapkqfilter(struct dev_kqfilter_args *ap)
1000 {
1001         cdev_t dev = ap->a_head.a_dev;
1002         struct knote *kn = ap->a_kn;
1003         struct tap_softc *tp;
1004         struct klist *list;
1005         struct ifnet *ifp;
1006
1007         get_mplock();
1008         tp = dev->si_drv1;
1009         ifp = &tp->tap_if;
1010         ap->a_result =0;
1011
1012         switch(kn->kn_filter) {
1013         case EVFILT_READ:
1014                 list = &tp->tap_rsel.si_note;
1015                 kn->kn_fop = &tapread_filtops;
1016                 kn->kn_hook = (void *)tp;
1017                 break;
1018         case EVFILT_WRITE:
1019                 /* fall through */
1020         default:
1021                 ap->a_result = EOPNOTSUPP;
1022                 rel_mplock();
1023                 return(0);
1024         }
1025         crit_enter();
1026         SLIST_INSERT_HEAD(list, kn, kn_selnext);
1027         crit_exit();
1028         rel_mplock();
1029         return(0);
1030 }
1031
1032 static int
1033 filt_tapread(struct knote *kn, long hint)
1034 {
1035         struct tap_softc *tp = (void *)kn->kn_hook;
1036
1037         if (IF_QEMPTY(&tp->tap_devq) == 0)      /* XXX serializer */
1038                 return(1);
1039         else
1040                 return(0);
1041 }
1042
1043 static void
1044 filt_tapdetach(struct knote *kn)
1045 {
1046         struct tap_softc *tp = (void *)kn->kn_hook;
1047
1048         SLIST_REMOVE(&tp->tap_rsel.si_note, kn, knote, kn_selnext);
1049 }
1050
1051 static void
1052 tapifstop(struct tap_softc *tp, int clear_flags)
1053 {
1054         struct ifnet *ifp = &tp->tap_if;
1055
1056         ASSERT_IFNET_SERIALIZED_ALL(ifp);
1057         IF_DRAIN(&tp->tap_devq);
1058         tp->tap_flags &= ~TAP_CLOSEDOWN;
1059         if (clear_flags)
1060                 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
1061 }
1062
1063 static void
1064 tapifflags(struct tap_softc *tp)
1065 {
1066         struct ifnet *ifp = &tp->arpcom.ac_if;
1067
1068         ASSERT_IFNET_SERIALIZED_ALL(ifp);
1069         if ((tp->tap_flags & TAP_VMNET) == 0) {
1070                 /*
1071                  * Only for non-vmnet tap(4)
1072                  */
1073                 if (ifp->if_flags & IFF_UP) {
1074                         if ((ifp->if_flags & IFF_RUNNING) == 0)
1075                                 tapifinit(tp);
1076                 } else {
1077                         tapifstop(tp, 1);
1078                 }
1079         } else {
1080                 /* XXX */
1081         }
1082 }