]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/net/if_tap.c
This commit was generated by cvs2svn to compensate for changes in r147013,
[FreeBSD/FreeBSD.git] / sys / net / 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$
35  * $Id: if_tap.c,v 0.21 2000/07/23 21:46:02 max Exp $
36  */
37
38 #include "opt_inet.h"
39
40 #include <sys/param.h>
41 #include <sys/conf.h>
42 #include <sys/fcntl.h>
43 #include <sys/filio.h>
44 #include <sys/kernel.h>
45 #include <sys/malloc.h>
46 #include <sys/mbuf.h>
47 #include <sys/module.h>
48 #include <sys/poll.h>
49 #include <sys/proc.h>
50 #include <sys/selinfo.h>
51 #include <sys/signalvar.h>
52 #include <sys/socket.h>
53 #include <sys/sockio.h>
54 #include <sys/sysctl.h>
55 #include <sys/systm.h>
56 #include <sys/ttycom.h>
57 #include <sys/uio.h>
58 #include <sys/queue.h>
59
60 #include <net/bpf.h>
61 #include <net/ethernet.h>
62 #include <net/if.h>
63 #include <net/if_arp.h>
64 #include <net/route.h>
65
66 #include <netinet/in.h>
67
68 #include <net/if_tapvar.h>
69 #include <net/if_tap.h>
70
71
72 #define CDEV_NAME       "tap"
73 #define TAPDEBUG        if (tapdebug) printf
74
75 #define TAP             "tap"
76 #define VMNET           "vmnet"
77 #define TAPMAXUNIT      0x7fff
78 #define VMNET_DEV_MASK  CLONE_FLAG0
79
80 /* module */
81 static int              tapmodevent(module_t, int, void *);
82
83 /* device */
84 static void             tapclone(void *, char *, int, struct cdev **);
85 static void             tapcreate(struct cdev *);
86
87 /* network interface */
88 static void             tapifstart(struct ifnet *);
89 static int              tapifioctl(struct ifnet *, u_long, caddr_t);
90 static void             tapifinit(void *);
91
92 /* character device */
93 static d_open_t         tapopen;
94 static d_close_t        tapclose;
95 static d_read_t         tapread;
96 static d_write_t        tapwrite;
97 static d_ioctl_t        tapioctl;
98 static d_poll_t         tappoll;
99
100 static struct cdevsw    tap_cdevsw = {
101         .d_version =    D_VERSION,
102         .d_flags =      D_PSEUDO | D_NEEDGIANT,
103         .d_open =       tapopen,
104         .d_close =      tapclose,
105         .d_read =       tapread,
106         .d_write =      tapwrite,
107         .d_ioctl =      tapioctl,
108         .d_poll =       tappoll,
109         .d_name =       CDEV_NAME,
110 };
111
112 /*
113  * All global variables in if_tap.c are locked with tapmtx, with the
114  * exception of tapdebug, which is accessed unlocked; tapclones is
115  * static at runtime.
116  */
117 static struct mtx               tapmtx;
118 static int                      tapdebug = 0;        /* debug flag   */
119 static int                      tapuopen = 0;        /* allow user open() */         
120 static SLIST_HEAD(, tap_softc)  taphead;             /* first device */
121 static struct clonedevs         *tapclones;
122
123 MALLOC_DECLARE(M_TAP);
124 MALLOC_DEFINE(M_TAP, CDEV_NAME, "Ethernet tunnel interface");
125 SYSCTL_INT(_debug, OID_AUTO, if_tap_debug, CTLFLAG_RW, &tapdebug, 0, "");
126
127 SYSCTL_DECL(_net_link);
128 SYSCTL_NODE(_net_link, OID_AUTO, tap, CTLFLAG_RW, 0,
129     "Ethernet tunnel software network interface");
130 SYSCTL_INT(_net_link_tap, OID_AUTO, user_open, CTLFLAG_RW, &tapuopen, 0,
131         "Allow user to open /dev/tap (based on node permissions)");
132 SYSCTL_INT(_net_link_tap, OID_AUTO, debug, CTLFLAG_RW, &tapdebug, 0, "");
133
134 DEV_MODULE(if_tap, tapmodevent, NULL);
135
136 /*
137  * tapmodevent
138  *
139  * module event handler
140  */
141 static int
142 tapmodevent(mod, type, data)
143         module_t         mod;
144         int              type;
145         void            *data;
146 {
147         static eventhandler_tag  eh_tag = NULL;
148         struct tap_softc        *tp = NULL;
149         struct ifnet            *ifp = NULL;
150         int                      s;
151
152         switch (type) {
153         case MOD_LOAD:
154
155                 /* intitialize device */
156
157                 mtx_init(&tapmtx, "tapmtx", NULL, MTX_DEF);
158                 SLIST_INIT(&taphead);
159
160                 clone_setup(&tapclones);
161                 eh_tag = EVENTHANDLER_REGISTER(dev_clone, tapclone, 0, 1000);
162                 if (eh_tag == NULL) {
163                         clone_cleanup(&tapclones);
164                         mtx_destroy(&tapmtx);
165                         return (ENOMEM);
166                 }
167                 return (0);
168
169         case MOD_UNLOAD:
170                 /*
171                  * The EBUSY algorithm here can't quite atomically
172                  * guarantee that this is race-free since we have to
173                  * release the tap mtx to deregister the clone handler.
174                  */
175                 mtx_lock(&tapmtx);
176                 SLIST_FOREACH(tp, &taphead, tap_next) {
177                         mtx_lock(&tp->tap_mtx);
178                         if (tp->tap_flags & TAP_OPEN) {
179                                 mtx_unlock(&tp->tap_mtx);
180                                 mtx_unlock(&tapmtx);
181                                 return (EBUSY);
182                         }
183                         mtx_unlock(&tp->tap_mtx);
184                 }
185                 mtx_unlock(&tapmtx);
186
187                 EVENTHANDLER_DEREGISTER(dev_clone, eh_tag);
188
189                 mtx_lock(&tapmtx);
190                 while ((tp = SLIST_FIRST(&taphead)) != NULL) {
191                         SLIST_REMOVE_HEAD(&taphead, tap_next);
192                         mtx_unlock(&tapmtx);
193
194                         ifp = &tp->tap_if;
195
196                         TAPDEBUG("detaching %s\n", ifp->if_xname);
197
198                         /* Unlocked read. */
199                         KASSERT(!(tp->tap_flags & TAP_OPEN), 
200                                 ("%s flags is out of sync", ifp->if_xname));
201
202                         destroy_dev(tp->tap_dev);
203                         s = splimp();
204                         ether_ifdetach(ifp);
205                         splx(s);
206
207                         mtx_destroy(&tp->tap_mtx);
208                         free(tp, M_TAP);
209                         mtx_lock(&tapmtx);
210                 }
211                 mtx_unlock(&tapmtx);
212                 clone_cleanup(&tapclones);
213
214                 mtx_destroy(&tapmtx);
215
216                 break;
217
218         default:
219                 return (EOPNOTSUPP);
220         }
221
222         return (0);
223 } /* tapmodevent */
224
225
226 /*
227  * DEVFS handler
228  *
229  * We need to support two kind of devices - tap and vmnet
230  */
231 static void
232 tapclone(arg, name, namelen, dev)
233         void    *arg;
234         char    *name;
235         int      namelen;
236         struct cdev **dev;
237 {
238         u_int           extra;
239         int             i, unit;
240         char            *device_name = name;
241
242         if (*dev != NULL)
243                 return;
244
245         device_name = TAP;
246         extra = 0;
247         if (strcmp(name, TAP) == 0) {
248                 unit = -1;
249         } else if (strcmp(name, VMNET) == 0) {
250                 device_name = VMNET;
251                 extra = VMNET_DEV_MASK;
252                 unit = -1;
253         } else if (dev_stdclone(name, NULL, device_name, &unit) != 1) {
254                 device_name = VMNET;
255                 extra = VMNET_DEV_MASK;
256                 if (dev_stdclone(name, NULL, device_name, &unit) != 1)
257                         return;
258         }
259
260         /* find any existing device, or allocate new unit number */
261         i = clone_create(&tapclones, &tap_cdevsw, &unit, dev, extra);
262         if (i) {
263                 *dev = make_dev(&tap_cdevsw, unit2minor(unit | extra),
264                      UID_ROOT, GID_WHEEL, 0600, "%s%d", device_name, unit);
265                 if (*dev != NULL) {
266                         dev_ref(*dev);
267                         (*dev)->si_flags |= SI_CHEAPCLONE;
268                 }
269         }
270 } /* tapclone */
271
272
273 /*
274  * tapcreate
275  *
276  * to create interface
277  */
278 static void
279 tapcreate(dev)
280         struct cdev *dev;
281 {
282         struct ifnet            *ifp = NULL;
283         struct tap_softc        *tp = NULL;
284         unsigned short           macaddr_hi;
285         int                      unit, s;
286         char                    *name = NULL;
287
288         dev->si_flags &= ~SI_CHEAPCLONE;
289
290         /* allocate driver storage and create device */
291         MALLOC(tp, struct tap_softc *, sizeof(*tp), M_TAP, M_WAITOK | M_ZERO);
292         mtx_init(&tp->tap_mtx, "tap_mtx", NULL, MTX_DEF);
293         mtx_lock(&tapmtx);
294         SLIST_INSERT_HEAD(&taphead, tp, tap_next);
295         mtx_unlock(&tapmtx);
296
297         unit = dev2unit(dev);
298
299         /* select device: tap or vmnet */
300         if (unit & VMNET_DEV_MASK) {
301                 name = VMNET;
302                 tp->tap_flags |= TAP_VMNET;
303         } else
304                 name = TAP;
305
306         unit &= TAPMAXUNIT;
307
308         TAPDEBUG("tapcreate(%s%d). minor = %#x\n", name, unit, minor(dev));
309
310         /* generate fake MAC address: 00 bd xx xx xx unit_no */
311         macaddr_hi = htons(0x00bd);
312         bcopy(&macaddr_hi, &tp->arpcom.ac_enaddr[0], sizeof(short));
313         bcopy(&ticks, &tp->arpcom.ac_enaddr[2], sizeof(long));
314         tp->arpcom.ac_enaddr[5] = (u_char)unit;
315
316         /* fill the rest and attach interface */
317         ifp = &tp->tap_if;
318         ifp->if_softc = tp;
319         if_initname(ifp, name, unit);
320         ifp->if_init = tapifinit;
321         ifp->if_start = tapifstart;
322         ifp->if_ioctl = tapifioctl;
323         ifp->if_mtu = ETHERMTU;
324         ifp->if_flags = (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST);
325         ifp->if_snd.ifq_maxlen = ifqmaxlen;
326
327         dev->si_drv1 = tp;
328         tp->tap_dev = dev;
329
330         s = splimp();
331         ether_ifattach(ifp, tp->arpcom.ac_enaddr);
332         splx(s);
333
334         mtx_lock(&tp->tap_mtx);
335         tp->tap_flags |= TAP_INITED;
336         mtx_unlock(&tp->tap_mtx);
337
338         TAPDEBUG("interface %s is created. minor = %#x\n", 
339                 ifp->if_xname, minor(dev));
340 } /* tapcreate */
341
342
343 /*
344  * tapopen
345  *
346  * to open tunnel. must be superuser
347  */
348 static int
349 tapopen(dev, flag, mode, td)
350         struct cdev *dev;
351         int              flag;
352         int              mode;
353         struct thread   *td;
354 {
355         struct tap_softc        *tp = NULL;
356         struct ifnet            *ifp = NULL;
357         int                      s;
358
359         if (tapuopen == 0 && suser(td) != 0)
360                 return (EPERM);
361
362         if ((dev2unit(dev) & CLONE_UNITMASK) > TAPMAXUNIT)
363                 return (ENXIO);
364
365         /*
366          * XXXRW: Non-atomic test-and-set of si_drv1.  Currently protected
367          * by Giant, but the race actually exists under memory pressure as
368          * well even when running with Giant, as malloc() may sleep.
369          */
370         tp = dev->si_drv1;
371         if (tp == NULL) {
372                 tapcreate(dev);
373                 tp = dev->si_drv1;
374         }
375
376         mtx_lock(&tp->tap_mtx);
377         if (tp->tap_flags & TAP_OPEN) {
378                 mtx_unlock(&tp->tap_mtx);
379                 return (EBUSY);
380         }
381
382         bcopy(tp->arpcom.ac_enaddr, tp->ether_addr, sizeof(tp->ether_addr));
383         tp->tap_pid = td->td_proc->p_pid;
384         tp->tap_flags |= TAP_OPEN;
385         ifp = &tp->tap_if;
386         mtx_unlock(&tp->tap_mtx);
387
388         s = splimp();
389         ifp->if_flags |= IFF_RUNNING;
390         ifp->if_flags &= ~IFF_OACTIVE;
391         splx(s);
392
393         TAPDEBUG("%s is open. minor = %#x\n", ifp->if_xname, minor(dev));
394
395         return (0);
396 } /* tapopen */
397
398
399 /*
400  * tapclose
401  *
402  * close the device - mark i/f down & delete routing info
403  */
404 static int
405 tapclose(dev, foo, bar, td)
406         struct cdev *dev;
407         int              foo;
408         int              bar;
409         struct thread   *td;
410 {
411         struct ifaddr *ifa;
412         struct tap_softc        *tp = dev->si_drv1;
413         struct ifnet            *ifp = &tp->tap_if;
414         int                     s;
415
416         /* junk all pending output */
417         IF_DRAIN(&ifp->if_snd);
418
419         /*
420          * do not bring the interface down, and do not anything with
421          * interface, if we are in VMnet mode. just close the device.
422          */
423
424         mtx_lock(&tp->tap_mtx);
425         if (((tp->tap_flags & TAP_VMNET) == 0) && (ifp->if_flags & IFF_UP)) {
426                 mtx_unlock(&tp->tap_mtx);
427                 s = splimp();
428                 if_down(ifp);
429                 if (ifp->if_flags & IFF_RUNNING) {
430                         TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
431                                 rtinit(ifa, (int)RTM_DELETE, 0);
432                         }
433                         if_purgeaddrs(ifp);
434                         ifp->if_flags &= ~IFF_RUNNING;
435                 }
436                 splx(s);
437         } else
438                 mtx_unlock(&tp->tap_mtx);
439
440         funsetown(&tp->tap_sigio);
441         selwakeuppri(&tp->tap_rsel, PZERO+1);
442
443         mtx_lock(&tp->tap_mtx);
444         tp->tap_flags &= ~TAP_OPEN;
445         tp->tap_pid = 0;
446         mtx_unlock(&tp->tap_mtx);
447
448         TAPDEBUG("%s is closed. minor = %#x\n", 
449                 ifp->if_xname, minor(dev));
450
451         return (0);
452 } /* tapclose */
453
454
455 /*
456  * tapifinit
457  *
458  * network interface initialization function
459  */
460 static void
461 tapifinit(xtp)
462         void    *xtp;
463 {
464         struct tap_softc        *tp = (struct tap_softc *)xtp;
465         struct ifnet            *ifp = &tp->tap_if;
466
467         TAPDEBUG("initializing %s\n", ifp->if_xname);
468
469         ifp->if_flags |= IFF_RUNNING;
470         ifp->if_flags &= ~IFF_OACTIVE;
471
472         /* attempt to start output */
473         tapifstart(ifp);
474 } /* tapifinit */
475
476
477 /*
478  * tapifioctl
479  *
480  * Process an ioctl request on network interface
481  */
482 static int
483 tapifioctl(ifp, cmd, data)
484         struct ifnet    *ifp;
485         u_long           cmd;
486         caddr_t          data;
487 {
488         struct tap_softc        *tp = (struct tap_softc *)(ifp->if_softc);
489         struct ifstat           *ifs = NULL;
490         int                      s, dummy;
491
492         switch (cmd) {
493                 case SIOCSIFFLAGS: /* XXX -- just like vmnet does */
494                 case SIOCADDMULTI:
495                 case SIOCDELMULTI:
496                         break;
497
498                 case SIOCGIFSTATUS:
499                         s = splimp();
500                         ifs = (struct ifstat *)data;
501                         dummy = strlen(ifs->ascii);
502                         mtx_lock(&tp->tap_mtx);
503                         if (tp->tap_pid != 0 && dummy < sizeof(ifs->ascii))
504                                 snprintf(ifs->ascii + dummy,
505                                         sizeof(ifs->ascii) - dummy,
506                                         "\tOpened by PID %d\n", tp->tap_pid);
507                         mtx_unlock(&tp->tap_mtx);
508                         splx(s);
509                         break;
510
511                 default:
512                         s = splimp();
513                         dummy = ether_ioctl(ifp, cmd, data);
514                         splx(s);
515                         return (dummy);
516         }
517
518         return (0);
519 } /* tapifioctl */
520
521
522 /*
523  * tapifstart
524  *
525  * queue packets from higher level ready to put out
526  */
527 static void
528 tapifstart(ifp)
529         struct ifnet    *ifp;
530 {
531         struct tap_softc        *tp = ifp->if_softc;
532         int                      s;
533
534         TAPDEBUG("%s starting\n", ifp->if_xname);
535
536         /*
537          * do not junk pending output if we are in VMnet mode.
538          * XXX: can this do any harm because of queue overflow?
539          */
540
541         mtx_lock(&tp->tap_mtx);
542         if (((tp->tap_flags & TAP_VMNET) == 0) &&
543             ((tp->tap_flags & TAP_READY) != TAP_READY)) {
544                 struct mbuf     *m = NULL;
545
546                 mtx_unlock(&tp->tap_mtx);
547
548                 /* Unlocked read. */
549                 TAPDEBUG("%s not ready, tap_flags = 0x%x\n", ifp->if_xname, 
550                     tp->tap_flags);
551
552                 s = splimp();
553                 do {
554                         IF_DEQUEUE(&ifp->if_snd, m);
555                         if (m != NULL)
556                                 m_freem(m);
557                         ifp->if_oerrors ++;
558                 } while (m != NULL);
559                 splx(s);
560
561                 return;
562         }
563         mtx_unlock(&tp->tap_mtx);
564
565         s = splimp();
566         ifp->if_flags |= IFF_OACTIVE;
567
568         if (ifp->if_snd.ifq_len != 0) {
569                 mtx_lock(&tp->tap_mtx);
570                 if (tp->tap_flags & TAP_RWAIT) {
571                         tp->tap_flags &= ~TAP_RWAIT;
572                         wakeup(tp);
573                 }
574
575                 if ((tp->tap_flags & TAP_ASYNC) && (tp->tap_sigio != NULL)) {
576                         mtx_unlock(&tp->tap_mtx);
577                         pgsigio(&tp->tap_sigio, SIGIO, 0);
578                 } else
579                         mtx_unlock(&tp->tap_mtx);
580
581                 selwakeuppri(&tp->tap_rsel, PZERO+1);
582                 ifp->if_opackets ++; /* obytes are counted in ether_output */
583         }
584
585         ifp->if_flags &= ~IFF_OACTIVE;
586         splx(s);
587 } /* tapifstart */
588
589
590 /*
591  * tapioctl
592  *
593  * the cdevsw interface is now pretty minimal
594  */
595 static int
596 tapioctl(dev, cmd, data, flag, td)
597         struct cdev *dev;
598         u_long           cmd;
599         caddr_t          data;
600         int              flag;
601         struct thread   *td;
602 {
603         struct tap_softc        *tp = dev->si_drv1;
604         struct ifnet            *ifp = &tp->tap_if;
605         struct tapinfo          *tapp = NULL;
606         int                      s;
607         int                      f;
608
609         switch (cmd) {
610                 case TAPSIFINFO:
611                         s = splimp();
612                         tapp = (struct tapinfo *)data;
613                         ifp->if_mtu = tapp->mtu;
614                         ifp->if_type = tapp->type;
615                         ifp->if_baudrate = tapp->baudrate;
616                         splx(s);
617                         break;
618
619                 case TAPGIFINFO:
620                         tapp = (struct tapinfo *)data;
621                         tapp->mtu = ifp->if_mtu;
622                         tapp->type = ifp->if_type;
623                         tapp->baudrate = ifp->if_baudrate;
624                         break;
625
626                 case TAPSDEBUG:
627                         tapdebug = *(int *)data;
628                         break;
629
630                 case TAPGDEBUG:
631                         *(int *)data = tapdebug;
632                         break;
633
634                 case FIONBIO:
635                         break;
636
637                 case FIOASYNC:
638                         s = splimp();
639                         mtx_lock(&tp->tap_mtx);
640                         if (*(int *)data)
641                                 tp->tap_flags |= TAP_ASYNC;
642                         else
643                                 tp->tap_flags &= ~TAP_ASYNC;
644                         mtx_unlock(&tp->tap_mtx);
645                         splx(s);
646                         break;
647
648                 case FIONREAD:
649                         s = splimp();
650                         if (ifp->if_snd.ifq_head) {
651                                 struct mbuf     *mb = ifp->if_snd.ifq_head;
652
653                                 for(*(int *)data = 0;mb != NULL;mb = mb->m_next)
654                                         *(int *)data += mb->m_len;
655                         } else
656                                 *(int *)data = 0;
657                         splx(s);
658                         break;
659
660                 case FIOSETOWN:
661                         return (fsetown(*(int *)data, &tp->tap_sigio));
662
663                 case FIOGETOWN:
664                         *(int *)data = fgetown(&tp->tap_sigio);
665                         return (0);
666
667                 /* this is deprecated, FIOSETOWN should be used instead */
668                 case TIOCSPGRP:
669                         return (fsetown(-(*(int *)data), &tp->tap_sigio));
670
671                 /* this is deprecated, FIOGETOWN should be used instead */
672                 case TIOCGPGRP:
673                         *(int *)data = -fgetown(&tp->tap_sigio);
674                         return (0);
675
676                 /* VMware/VMnet port ioctl's */
677
678                 case SIOCGIFFLAGS:      /* get ifnet flags */
679                         bcopy(&ifp->if_flags, data, sizeof(ifp->if_flags));
680                         break;
681
682                 case VMIO_SIOCSIFFLAGS: /* VMware/VMnet SIOCSIFFLAGS */
683                         f = *(int *)data;
684                         f &= 0x0fff;
685                         f &= ~IFF_CANTCHANGE;
686                         f |= IFF_UP;
687
688                         s = splimp();
689                         ifp->if_flags = f | (ifp->if_flags & IFF_CANTCHANGE);
690                         splx(s);
691                         break;
692
693                 case OSIOCGIFADDR:      /* get MAC address of the remote side */
694                 case SIOCGIFADDR:
695                         mtx_lock(&tp->tap_mtx);
696                         bcopy(tp->ether_addr, data, sizeof(tp->ether_addr));
697                         mtx_unlock(&tp->tap_mtx);
698                         break;
699
700                 case SIOCSIFADDR:       /* set MAC address of the remote side */
701                         mtx_lock(&tp->tap_mtx);
702                         bcopy(data, tp->ether_addr, sizeof(tp->ether_addr));
703                         mtx_unlock(&tp->tap_mtx);
704                         break;
705
706                 default:
707                         return (ENOTTY);
708         }
709         return (0);
710 } /* tapioctl */
711
712
713 /*
714  * tapread
715  *
716  * the cdevsw read interface - reads a packet at a time, or at
717  * least as much of a packet as can be read
718  */
719 static int
720 tapread(dev, uio, flag)
721         struct cdev *dev;
722         struct uio      *uio;
723         int              flag;
724 {
725         struct tap_softc        *tp = dev->si_drv1;
726         struct ifnet            *ifp = &tp->tap_if;
727         struct mbuf             *m = NULL;
728         int                      error = 0, len, s;
729
730         TAPDEBUG("%s reading, minor = %#x\n", ifp->if_xname, minor(dev));
731
732         mtx_lock(&tp->tap_mtx);
733         if ((tp->tap_flags & TAP_READY) != TAP_READY) {
734                 mtx_unlock(&tp->tap_mtx);
735
736                 /* Unlocked read. */
737                 TAPDEBUG("%s not ready. minor = %#x, tap_flags = 0x%x\n",
738                         ifp->if_xname, minor(dev), tp->tap_flags);
739
740                 return (EHOSTDOWN);
741         }
742
743         tp->tap_flags &= ~TAP_RWAIT;
744         mtx_unlock(&tp->tap_mtx);
745
746         /* sleep until we get a packet */
747         do {
748                 s = splimp();
749                 IF_DEQUEUE(&ifp->if_snd, m);
750                 splx(s);
751
752                 if (m == NULL) {
753                         if (flag & O_NONBLOCK)
754                                 return (EWOULDBLOCK);
755
756                         mtx_lock(&tp->tap_mtx);
757                         tp->tap_flags |= TAP_RWAIT;
758                         mtx_unlock(&tp->tap_mtx);
759                         error = tsleep(tp,PCATCH|(PZERO+1),"taprd",0);
760                         if (error)
761                                 return (error);
762                 }
763         } while (m == NULL);
764
765         /* feed packet to bpf */
766         BPF_MTAP(ifp, m);
767
768         /* xfer packet to user space */
769         while ((m != NULL) && (uio->uio_resid > 0) && (error == 0)) {
770                 len = min(uio->uio_resid, m->m_len);
771                 if (len == 0)
772                         break;
773
774                 error = uiomove(mtod(m, void *), len, uio);
775                 m = m_free(m);
776         }
777
778         if (m != NULL) {
779                 TAPDEBUG("%s dropping mbuf, minor = %#x\n", ifp->if_xname, 
780                         minor(dev));
781                 m_freem(m);
782         }
783
784         return (error);
785 } /* tapread */
786
787
788 /*
789  * tapwrite
790  *
791  * the cdevsw write interface - an atomic write is a packet - or else!
792  */
793 static int
794 tapwrite(dev, uio, flag)
795         struct cdev *dev;
796         struct uio      *uio;
797         int              flag;
798 {
799         struct tap_softc        *tp = dev->si_drv1;
800         struct ifnet            *ifp = &tp->tap_if;
801         struct mbuf             *m;
802         int                      error = 0;
803
804         TAPDEBUG("%s writting, minor = %#x\n", 
805                 ifp->if_xname, minor(dev));
806
807         if (uio->uio_resid == 0)
808                 return (0);
809
810         if ((uio->uio_resid < 0) || (uio->uio_resid > TAPMRU)) {
811                 TAPDEBUG("%s invalid packet len = %d, minor = %#x\n",
812                         ifp->if_xname, uio->uio_resid, minor(dev));
813
814                 return (EIO);
815         }
816
817         if ((m = m_uiotombuf(uio, M_DONTWAIT, 0, ETHER_ALIGN)) == NULL) {
818                 ifp->if_ierrors ++;
819                 return (error);
820         }
821
822         m->m_pkthdr.rcvif = ifp;
823
824         /* Pass packet up to parent. */
825         (*ifp->if_input)(ifp, m);
826         ifp->if_ipackets ++; /* ibytes are counted in parent */
827
828         return (0);
829 } /* tapwrite */
830
831
832 /*
833  * tappoll
834  *
835  * the poll interface, this is only useful on reads
836  * really. the write detect always returns true, write never blocks
837  * anyway, it either accepts the packet or drops it
838  */
839 static int
840 tappoll(dev, events, td)
841         struct cdev *dev;
842         int              events;
843         struct thread   *td;
844 {
845         struct tap_softc        *tp = dev->si_drv1;
846         struct ifnet            *ifp = &tp->tap_if;
847         int                      s, revents = 0;
848
849         TAPDEBUG("%s polling, minor = %#x\n", 
850                 ifp->if_xname, minor(dev));
851
852         s = splimp();
853         if (events & (POLLIN | POLLRDNORM)) {
854                 if (ifp->if_snd.ifq_len > 0) {
855                         TAPDEBUG("%s have data in queue. len = %d, " \
856                                 "minor = %#x\n", ifp->if_xname,
857                                 ifp->if_snd.ifq_len, minor(dev));
858
859                         revents |= (events & (POLLIN | POLLRDNORM));
860                 } else {
861                         TAPDEBUG("%s waiting for data, minor = %#x\n",
862                                 ifp->if_xname, minor(dev));
863
864                         selrecord(td, &tp->tap_rsel);
865                 }
866         }
867
868         if (events & (POLLOUT | POLLWRNORM))
869                 revents |= (events & (POLLOUT | POLLWRNORM));
870
871         splx(s);
872         return (revents);
873 } /* tappoll */