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