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