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