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