d2492973b92106ae02add11272ed42f395c5a239
[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.18 2005/06/14 18:15:37 joerg 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/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/poll.h>
49 #include <sys/proc.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
59 #include <net/bpf.h>
60 #include <net/ethernet.h>
61 #include <net/if.h>
62 #include <net/if_arp.h>
63 #include <net/route.h>
64
65 #include <netinet/in.h>
66
67 #include "if_tapvar.h"
68 #include "if_tap.h"
69
70
71 #define CDEV_NAME       "tap"
72 #define CDEV_MAJOR      149
73 #define TAPDEBUG        if (tapdebug) if_printf
74
75 #define TAP             "tap"
76 #define VMNET           "vmnet"
77 #define VMNET_DEV_MASK  0x00010000
78
79 /* module */
80 static int              tapmodevent     (module_t, int, void *);
81
82 /* device */
83 static void             tapcreate       (dev_t);
84
85 /* network interface */
86 static void             tapifstart      (struct ifnet *);
87 static int              tapifioctl      (struct ifnet *, u_long, caddr_t,
88                                          struct ucred *);
89 static void             tapifinit       (void *);
90
91 /* character device */
92 static d_open_t         tapopen;
93 static d_close_t        tapclose;
94 static d_read_t         tapread;
95 static d_write_t        tapwrite;
96 static d_ioctl_t        tapioctl;
97 static d_poll_t         tappoll;
98
99 static struct cdevsw    tap_cdevsw = {
100         /* dev name */  CDEV_NAME,
101         /* dev major */ CDEV_MAJOR,
102         /* flags */     0,
103         /* port */      NULL,
104         /* clone */     NULL,
105
106         /* open */      tapopen,
107         /* close */     tapclose,
108         /* read */      tapread,
109         /* write */     tapwrite,
110         /* ioctl */     tapioctl,
111         /* poll */      tappoll,
112         /* mmap */      nommap,
113         /* startegy */  nostrategy,
114         /* dump */      nodump,
115         /* psize */     nopsize
116 };
117
118 static int              taprefcnt = 0;          /* module ref. counter   */
119 static int              taplastunit = -1;       /* max. open unit number */
120 static int              tapdebug = 0;           /* debug flag            */
121
122 MALLOC_DECLARE(M_TAP);
123 MALLOC_DEFINE(M_TAP, CDEV_NAME, "Ethernet tunnel interface");
124 SYSCTL_INT(_debug, OID_AUTO, if_tap_debug, CTLFLAG_RW, &tapdebug, 0, "");
125 DEV_MODULE(if_tap, tapmodevent, NULL);
126
127 /*
128  * tapmodevent
129  *
130  * module event handler
131  */
132 static int
133 tapmodevent(mod, type, data)
134         module_t         mod;
135         int              type;
136         void            *data;
137 {
138         static int               attached = 0;
139         struct ifnet            *ifp = NULL;
140         int                      unit, s;
141
142         switch (type) {
143         case MOD_LOAD:
144                 if (attached)
145                         return (EEXIST);
146
147                 cdevsw_add(&tap_cdevsw, 0, 0);
148                 attached = 1;
149         break;
150
151         case MOD_UNLOAD:
152                 if (taprefcnt > 0)
153                         return (EBUSY);
154
155                 cdevsw_remove(&tap_cdevsw, 0, 0);
156
157                 /* XXX: maintain tap ifs in a local list */
158                 unit = 0;
159                 while (unit <= taplastunit) {
160                         s = splimp();
161                         TAILQ_FOREACH(ifp, &ifnet, if_link)
162                                 if ((strcmp(ifp->if_dname, TAP) == 0) ||
163                                     (strcmp(ifp->if_dname, VMNET) == 0))
164                                         if (ifp->if_dunit == unit)
165                                                 break;
166                         splx(s);
167
168                         if (ifp != NULL) {
169                                 struct tap_softc        *tp = ifp->if_softc;
170
171                                 TAPDEBUG(ifp, "detached. minor = %#x, " \
172                                         "taplastunit = %d\n",
173                                         minor(tp->tap_dev), taplastunit);
174
175                                 s = splimp();
176                                 ether_ifdetach(ifp);
177                                 splx(s);
178                                 destroy_dev(tp->tap_dev);
179                                 free(tp, M_TAP);
180                         }
181                         else
182                                 unit ++;
183                 }
184
185                 attached = 0;
186         break;
187
188         default:
189                 return (EOPNOTSUPP);
190         }
191
192         return (0);
193 } /* tapmodevent */
194
195
196 /*
197  * tapcreate
198  *
199  * to create interface
200  */
201 static void
202 tapcreate(dev)
203         dev_t   dev;
204 {
205         struct ifnet            *ifp = NULL;
206         struct tap_softc        *tp = NULL;
207         uint8_t                 ether_addr[ETHER_ADDR_LEN];
208         int                      unit, s;
209         char                    *name = NULL;
210
211         /* allocate driver storage and create device */
212         MALLOC(tp, struct tap_softc *, sizeof(*tp), M_TAP, M_WAITOK);
213         bzero(tp, sizeof(*tp));
214
215         /* select device: tap or vmnet */
216         if (minor(dev) & VMNET_DEV_MASK) {
217                 name = VMNET;
218                 unit = lminor(dev) & 0xff;
219                 tp->tap_flags |= TAP_VMNET;
220         }
221         else {
222                 name = TAP;
223                 unit = lminor(dev);
224         }
225
226         tp->tap_dev = make_dev(&tap_cdevsw, minor(dev), UID_ROOT, GID_WHEEL, 
227                                                 0600, "%s%d", name, unit);
228         tp->tap_dev->si_drv1 = dev->si_drv1 = tp;
229         reference_dev(tp->tap_dev);     /* so we can destroy it later */
230
231         /* generate fake MAC address: 00 bd xx xx xx unit_no */
232         ether_addr[0] = 0x00;
233         ether_addr[1] = 0xbd;
234         bcopy(&ticks, ether_addr, 4);
235         ether_addr[5] = (u_char)unit;
236
237         /* fill the rest and attach interface */        
238         ifp = &tp->tap_if;
239         ifp->if_softc = tp;
240
241         if_initname(ifp, name, unit);
242         if (unit > taplastunit)
243                 taplastunit = unit;
244
245         ifp->if_init = tapifinit;
246         ifp->if_start = tapifstart;
247         ifp->if_ioctl = tapifioctl;
248         ifp->if_mtu = ETHERMTU;
249         ifp->if_flags = (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST);
250         ifp->if_snd.ifq_maxlen = ifqmaxlen;
251
252         s = splimp();
253         ether_ifattach(ifp, ether_addr);
254         splx(s);
255
256         tp->tap_flags |= TAP_INITED;
257
258         TAPDEBUG(ifp, "created. minor = %#x\n", minor(tp->tap_dev));
259 } /* tapcreate */
260
261
262 /*
263  * tapopen 
264  *
265  * to open tunnel. must be superuser
266  */
267 static int
268 tapopen(dev_t dev, int flag, int mode, d_thread_t *td)
269 {
270         struct tap_softc        *tp = NULL;
271         int                      error;
272
273         if ((error = suser(td)) != 0)
274                 return (error);
275
276         tp = dev->si_drv1;
277         if (tp == NULL) {
278                 tapcreate(dev);
279                 tp = dev->si_drv1;
280         }
281
282         if (tp->tap_flags & TAP_OPEN)
283                 return (EBUSY);
284
285         bcopy(tp->arpcom.ac_enaddr, tp->ether_addr, sizeof(tp->ether_addr));
286
287         tp->tap_td = td;
288         tp->tap_flags |= TAP_OPEN;
289         taprefcnt ++;
290
291         TAPDEBUG(&tp->arpcom.ac_if,
292                  "opened. minor = %#x, refcnt = %d, taplastunit = %d\n",
293                  minor(tp->tap_dev), taprefcnt, taplastunit);
294
295         return (0);
296 } /* tapopen */
297
298
299 /*
300  * tapclose
301  *
302  * close the device - mark i/f down & delete routing info
303  */
304 static int
305 tapclose(dev_t dev, int foo, int bar, d_thread_t *td)
306 {
307         int                      s;
308         struct tap_softc        *tp = dev->si_drv1;
309         struct ifnet            *ifp = &tp->tap_if;
310         struct mbuf             *m = NULL;
311
312         /* junk all pending output */
313
314         s = splimp();
315         do {
316                 IF_DEQUEUE(&ifp->if_snd, m);
317                 if (m != NULL)
318                         m_freem(m);
319         } while (m != NULL);
320         splx(s);
321
322         /*
323          * do not bring the interface down, and do not anything with
324          * interface, if we are in VMnet mode. just close the device.
325          */
326
327         if (((tp->tap_flags & TAP_VMNET) == 0) && (ifp->if_flags & IFF_UP)) {
328                 s = splimp();
329                 if_down(ifp);
330                 if (ifp->if_flags & IFF_RUNNING) {
331                         /* find internet addresses and delete routes */
332                         struct ifaddr   *ifa = NULL;
333
334                         TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
335                                 if (ifa->ifa_addr->sa_family == AF_INET) {
336                                         rtinit(ifa, (int)RTM_DELETE, 0);
337
338                                         /* remove address from interface */
339                                         bzero(ifa->ifa_addr, 
340                                                    sizeof(*(ifa->ifa_addr)));
341                                         bzero(ifa->ifa_dstaddr, 
342                                                    sizeof(*(ifa->ifa_dstaddr)));
343                                         bzero(ifa->ifa_netmask, 
344                                                    sizeof(*(ifa->ifa_netmask)));
345                                 }
346                         }
347
348                         ifp->if_flags &= ~IFF_RUNNING;
349                 }
350                 splx(s);
351         }
352
353         funsetown(tp->tap_sigio);
354         selwakeup(&tp->tap_rsel);
355
356         tp->tap_flags &= ~TAP_OPEN;
357         tp->tap_td = NULL;
358
359         taprefcnt --;
360         if (taprefcnt < 0) {
361                 taprefcnt = 0;
362                 if_printf(ifp, "minor = %#x, refcnt = %d is out of sync. "
363                         "set refcnt to 0\n", minor(tp->tap_dev), taprefcnt);
364         }
365
366         TAPDEBUG(ifp, "closed. minor = %#x, refcnt = %d, taplastunit = %d\n",
367                  minor(tp->tap_dev), taprefcnt, taplastunit);
368
369         return (0);
370 } /* tapclose */
371
372
373 /*
374  * tapifinit
375  *
376  * network interface initialization function
377  */
378 static void
379 tapifinit(xtp)
380         void    *xtp;
381 {
382         struct tap_softc        *tp = (struct tap_softc *)xtp;
383         struct ifnet            *ifp = &tp->tap_if;
384
385         TAPDEBUG(ifp, "initializing, minor = %#x\n", minor(tp->tap_dev));
386
387         ifp->if_flags |= IFF_RUNNING;
388         ifp->if_flags &= ~IFF_OACTIVE;
389
390         /* attempt to start output */
391         tapifstart(ifp);
392 } /* tapifinit */
393
394
395 /*
396  * tapifioctl
397  *
398  * Process an ioctl request on network interface
399  */
400 int
401 tapifioctl(ifp, cmd, data, cr)
402         struct ifnet    *ifp;
403         u_long           cmd;
404         caddr_t          data;
405         struct ucred    *cr;
406 {
407         struct tap_softc        *tp = (struct tap_softc *)(ifp->if_softc);
408         struct ifstat           *ifs = NULL;
409         int                      s, dummy;
410
411         switch (cmd) {
412                 case SIOCSIFADDR:
413                 case SIOCGIFADDR:
414                 case SIOCSIFMTU:
415                         s = splimp();
416                         dummy = ether_ioctl(ifp, cmd, data);
417                         splx(s);
418                         return (dummy);
419
420                 case SIOCSIFFLAGS: /* XXX -- just like vmnet does */
421                 case SIOCADDMULTI:
422                 case SIOCDELMULTI:
423                 break;
424
425                 case SIOCGIFSTATUS:
426                         s = splimp();
427                         ifs = (struct ifstat *)data;
428                         dummy = strlen(ifs->ascii);
429                         if (tp->tap_td != NULL && dummy < sizeof(ifs->ascii)) {
430                                 if (tp->tap_td->td_proc) {
431                                     snprintf(ifs->ascii + dummy,
432                                         sizeof(ifs->ascii) - dummy,
433                                         "\tOpened by pid %d\n",
434                                         (int)tp->tap_td->td_proc->p_pid);
435                                 } else {
436                                     snprintf(ifs->ascii + dummy,
437                                         sizeof(ifs->ascii) - dummy,
438                                         "\tOpened by td %p\n", tp->tap_td);
439                                 }
440                         }
441                         splx(s);
442                 break;
443
444                 default:
445                         return (EINVAL);
446         }
447
448         return (0);
449 } /* tapifioctl */
450
451
452 /*
453  * tapifstart 
454  * 
455  * queue packets from higher level ready to put out
456  */
457 static void
458 tapifstart(ifp)
459         struct ifnet    *ifp;
460 {
461         struct tap_softc        *tp = ifp->if_softc;
462         int                      s;
463
464         TAPDEBUG(ifp, "starting, minor = %#x\n", minor(tp->tap_dev));
465
466         /*
467          * do not junk pending output if we are in VMnet mode.
468          * XXX: can this do any harm because of queue overflow?
469          */
470
471         if (((tp->tap_flags & TAP_VMNET) == 0) && 
472             ((tp->tap_flags & TAP_READY) != TAP_READY)) {
473                 struct mbuf     *m = NULL;
474
475                 TAPDEBUG(ifp, "not ready. minor = %#x, tap_flags = 0x%x\n",
476                          minor(tp->tap_dev), tp->tap_flags);
477
478                 s = splimp();
479                 do {
480                         IF_DEQUEUE(&ifp->if_snd, m);
481                         if (m != NULL)
482                                 m_freem(m);
483                         ifp->if_oerrors ++;
484                 } while (m != NULL);
485                 splx(s);
486
487                 return;
488         }
489
490         s = splimp();
491         ifp->if_flags |= IFF_OACTIVE;
492
493         if (ifp->if_snd.ifq_len != 0) {
494                 if (tp->tap_flags & TAP_RWAIT) {
495                         tp->tap_flags &= ~TAP_RWAIT;
496                         wakeup((caddr_t)tp);
497                 }
498
499                 if ((tp->tap_flags & TAP_ASYNC) && (tp->tap_sigio != NULL))
500                         pgsigio(tp->tap_sigio, SIGIO, 0);
501
502                 selwakeup(&tp->tap_rsel);
503                 ifp->if_opackets ++; /* obytes are counted in ether_output */
504         }
505
506         ifp->if_flags &= ~IFF_OACTIVE;
507         splx(s);
508 } /* tapifstart */
509
510
511 /*
512  * tapioctl
513  *
514  * the cdevsw interface is now pretty minimal
515  */
516 static int
517 tapioctl(dev_t dev, u_long cmd, caddr_t data, int flag, d_thread_t *td)
518 {
519         struct tap_softc        *tp = dev->si_drv1;
520         struct ifnet            *ifp = &tp->tap_if;
521         struct tapinfo          *tapp = NULL;
522         int                      s;
523
524         switch (cmd) {
525                 case TAPSIFINFO:
526                         s = splimp();
527                         tapp = (struct tapinfo *)data;
528                         ifp->if_mtu = tapp->mtu;
529                         ifp->if_type = tapp->type;
530                         ifp->if_baudrate = tapp->baudrate;
531                         splx(s);
532                 break;
533
534                 case TAPGIFINFO:
535                         tapp = (struct tapinfo *)data;
536                         tapp->mtu = ifp->if_mtu;
537                         tapp->type = ifp->if_type;
538                         tapp->baudrate = ifp->if_baudrate;
539                 break;
540
541                 case TAPSDEBUG:
542                         tapdebug = *(int *)data;
543                 break;
544
545                 case TAPGDEBUG:
546                         *(int *)data = tapdebug;
547                 break;
548
549                 case FIONBIO:
550                 break;
551
552                 case FIOASYNC:
553                         s = splimp();
554                         if (*(int *)data)
555                                 tp->tap_flags |= TAP_ASYNC;
556                         else
557                                 tp->tap_flags &= ~TAP_ASYNC;
558                         splx(s);
559                 break;
560
561                 case FIONREAD:
562                         s = splimp();
563                         if (ifp->if_snd.ifq_head) {
564                                 struct mbuf     *mb = ifp->if_snd.ifq_head;
565
566                                 for(*(int *)data = 0;mb != NULL;mb = mb->m_next)
567                                         *(int *)data += mb->m_len;
568                         } 
569                         else
570                                 *(int *)data = 0;
571                         splx(s);
572                 break;
573
574                 case FIOSETOWN:
575                         return (fsetown(*(int *)data, &tp->tap_sigio));
576
577                 case FIOGETOWN:
578                         *(int *)data = fgetown(tp->tap_sigio);
579                         return (0);
580
581                 /* this is deprecated, FIOSETOWN should be used instead */
582                 case TIOCSPGRP:
583                         return (fsetown(-(*(int *)data), &tp->tap_sigio));
584
585                 /* this is deprecated, FIOGETOWN should be used instead */
586                 case TIOCGPGRP:
587                         *(int *)data = -fgetown(tp->tap_sigio);
588                         return (0);
589
590                 /* VMware/VMnet port ioctl's */
591
592                 case SIOCGIFFLAGS:      /* get ifnet flags */
593                         bcopy(&ifp->if_flags, data, sizeof(ifp->if_flags));
594                 break;
595
596                 case VMIO_SIOCSIFFLAGS: { /* VMware/VMnet SIOCSIFFLAGS */
597                         short   f = *(short *)data;
598
599                         f &= 0x0fff;
600                         f &= ~IFF_CANTCHANGE;
601                         f |= IFF_UP;
602
603                         s = splimp();
604                         ifp->if_flags = f | (ifp->if_flags & IFF_CANTCHANGE);
605                         splx(s);
606                 } break;
607
608                 case OSIOCGIFADDR:      /* get MAC address of the remote side */
609                 case SIOCGIFADDR:
610                         bcopy(tp->ether_addr, data, sizeof(tp->ether_addr));
611                 break;
612
613                 case SIOCSIFADDR:       /* set MAC address of the remote side */
614                         bcopy(data, tp->ether_addr, sizeof(tp->ether_addr));
615                 break;
616
617                 default:
618                         return (ENOTTY);
619         }
620         return (0);
621 } /* tapioctl */
622
623
624 /*
625  * tapread
626  *
627  * the cdevsw read interface - reads a packet at a time, or at
628  * least as much of a packet as can be read
629  */
630 static int
631 tapread(dev, uio, flag)
632         dev_t            dev;
633         struct uio      *uio;
634         int              flag;
635 {
636         struct tap_softc        *tp = dev->si_drv1;
637         struct ifnet            *ifp = &tp->tap_if;
638         struct mbuf             *m0 = NULL;
639         int                      error = 0, len, s;
640
641         TAPDEBUG(ifp, "reading, minor = %#x\n", minor(tp->tap_dev));
642
643         if ((tp->tap_flags & TAP_READY) != TAP_READY) {
644                 TAPDEBUG(ifp, "not ready. minor = %#x, tap_flags = 0x%x\n",
645                          minor(tp->tap_dev), tp->tap_flags);
646
647                 return (EHOSTDOWN);
648         }
649
650         tp->tap_flags &= ~TAP_RWAIT;
651
652         /* sleep until we get a packet */
653         do {
654                 s = splimp();
655                 IF_DEQUEUE(&ifp->if_snd, m0);
656                 splx(s);
657
658                 if (m0 == NULL) {
659                         if (flag & IO_NDELAY)
660                                 return (EWOULDBLOCK);
661                         
662                         tp->tap_flags |= TAP_RWAIT;
663                         error = tsleep((caddr_t)tp, PCATCH, "taprd", 0);
664                         if (error)
665                                 return (error);
666                 }
667         } while (m0 == NULL);
668
669         BPF_MTAP(ifp, m0);
670
671         /* xfer packet to user space */
672         while ((m0 != NULL) && (uio->uio_resid > 0) && (error == 0)) {
673                 len = min(uio->uio_resid, m0->m_len);
674                 if (len == 0)
675                         break;
676
677                 error = uiomove(mtod(m0, caddr_t), len, uio);
678                 m0 = m_free(m0);
679         }
680
681         if (m0 != NULL) {
682                 TAPDEBUG(ifp, "dropping mbuf, minor = %#x\n",
683                          minor(tp->tap_dev));
684                 m_freem(m0);
685         }
686
687         return (error);
688 } /* tapread */
689
690
691 /*
692  * tapwrite
693  *
694  * the cdevsw write interface - an atomic write is a packet - or else!
695  */
696 static int
697 tapwrite(dev, uio, flag)
698         dev_t            dev;
699         struct uio      *uio;
700         int              flag;
701 {
702         struct tap_softc        *tp = dev->si_drv1;
703         struct ifnet            *ifp = &tp->tap_if;
704         struct mbuf             *top = NULL, **mp = NULL, *m = NULL;
705         int                      error = 0, tlen, mlen;
706
707         TAPDEBUG(ifp, "writting, minor = %#x\n", minor(tp->tap_dev));
708
709         if (uio->uio_resid == 0)
710                 return (0);
711
712         if ((uio->uio_resid < 0) || (uio->uio_resid > TAPMRU)) {
713                 TAPDEBUG(ifp, "invalid packet len = %d, minor = %#x\n",
714                          uio->uio_resid, minor(tp->tap_dev));
715
716                 return (EIO);
717         }
718         tlen = uio->uio_resid;
719
720         /* get a header mbuf */
721         MGETHDR(m, MB_DONTWAIT, MT_DATA);
722         if (m == NULL)
723                 return (ENOBUFS);
724         mlen = MHLEN;
725
726         top = 0;
727         mp = &top;
728         while ((error == 0) && (uio->uio_resid > 0)) {
729                 m->m_len = min(mlen, uio->uio_resid);
730                 error = uiomove(mtod(m, caddr_t), m->m_len, uio);
731                 *mp = m;
732                 mp = &m->m_next;
733                 if (uio->uio_resid > 0) {
734                         MGET(m, MB_DONTWAIT, MT_DATA);
735                         if (m == NULL) {
736                                 error = ENOBUFS;
737                                 break;
738                         }
739                         mlen = MLEN;
740                 }
741         }
742         if (error) {
743                 ifp->if_ierrors ++;
744                 if (top)
745                         m_freem(top);
746                 return (error);
747         }
748
749         top->m_pkthdr.len = tlen;
750         top->m_pkthdr.rcvif = ifp;
751         
752         /*
753          * Ethernet bridge and bpf are handled in ether_input
754          *
755          * adjust mbuf and give packet to the ether_input
756          */
757
758         (*ifp->if_input)(ifp, top);
759         ifp->if_ipackets ++; /* ibytes are counted in ether_input */
760
761         return (0);
762 } /* tapwrite */
763
764
765 /*
766  * tappoll
767  *
768  * the poll interface, this is only useful on reads
769  * really. the write detect always returns true, write never blocks
770  * anyway, it either accepts the packet or drops it
771  */
772 static int
773 tappoll(dev_t dev, int events, d_thread_t *td)
774 {
775         struct tap_softc        *tp = dev->si_drv1;
776         struct ifnet            *ifp = &tp->tap_if;
777         int                      s, revents = 0;
778
779         TAPDEBUG(ifp, "polling, minor = %#x\n", minor(tp->tap_dev));
780
781         s = splimp();
782         if (events & (POLLIN | POLLRDNORM)) {
783                 if (ifp->if_snd.ifq_len > 0) {
784                         TAPDEBUG(ifp,
785                                  "has data in queue. len = %d, minor = %#x\n",
786                                  ifp->if_snd.ifq_len, minor(tp->tap_dev));
787
788                         revents |= (events & (POLLIN | POLLRDNORM));
789                 } 
790                 else {
791                         TAPDEBUG(ifp, "waiting for data, minor = %#x\n",
792                                  minor(tp->tap_dev));
793
794                         selrecord(td, &tp->tap_rsel);
795                 }
796         }
797
798         if (events & (POLLOUT | POLLWRNORM))
799                 revents |= (events & (POLLOUT | POLLWRNORM));
800
801         splx(s);
802         return (revents);
803 } /* tappoll */