Make all network interrupt service routines MPSAFE part 1/3.
[dragonfly.git] / sys / net / tun / if_tun.c
CommitLineData
984263bc
MD
1/* $NetBSD: if_tun.c,v 1.14 1994/06/29 06:36:25 cgd Exp $ */
2
3/*
4 * Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk>
5 * Nottingham University 1987.
6 *
7 * This source may be freely distributed, however I would be interested
8 * in any changes that are made.
9 *
10 * This driver takes packets off the IP i/f and hands them up to a
11 * user process to have its wicked way with. This driver has it's
12 * roots in a similar driver written by Phil Cockcroft (formerly) at
13 * UCL. This driver is based much more on read/write/poll mode of
14 * operation though.
15 *
16 * $FreeBSD: src/sys/net/if_tun.c,v 1.74.2.8 2002/02/13 00:43:11 dillon Exp $
78195a76 17 * $DragonFly: src/sys/net/tun/if_tun.c,v 1.25 2005/11/28 17:13:46 dillon Exp $
984263bc
MD
18 */
19
8bde602d 20#include "opt_atalk.h"
984263bc 21#include "opt_inet.h"
8bde602d
JH
22#include "opt_inet6.h"
23#include "opt_ipx.h"
984263bc
MD
24
25#include <sys/param.h>
26#include <sys/proc.h>
27#include <sys/systm.h>
28#include <sys/mbuf.h>
29#include <sys/socket.h>
30#include <sys/filio.h>
31#include <sys/sockio.h>
03522324 32#include <sys/thread2.h>
984263bc
MD
33#include <sys/ttycom.h>
34#include <sys/poll.h>
35#include <sys/signalvar.h>
36#include <sys/filedesc.h>
37#include <sys/kernel.h>
38#include <sys/sysctl.h>
39#include <sys/conf.h>
40#include <sys/uio.h>
41#include <sys/vnode.h>
42#include <sys/malloc.h>
43
44#include <net/if.h>
45#include <net/if_types.h>
4d723e5a 46#include <net/ifq_var.h>
8bde602d 47#include <net/netisr.h>
984263bc 48#include <net/route.h>
984263bc
MD
49
50#ifdef INET
51#include <netinet/in.h>
52#endif
53
54#include <net/bpf.h>
55
1f2de5d4
MD
56#include "if_tunvar.h"
57#include "if_tun.h"
984263bc
MD
58
59static MALLOC_DEFINE(M_TUN, "tun", "Tunnel Interface");
60
158abb01 61static void tunattach (void *);
984263bc
MD
62PSEUDO_SET(tunattach, if_tun);
63
158abb01 64static void tuncreate (dev_t dev);
984263bc 65
02b6afba 66#define TUNDEBUG if (tundebug) if_printf
984263bc
MD
67static int tundebug = 0;
68SYSCTL_INT(_debug, OID_AUTO, if_tun_debug, CTLFLAG_RW, &tundebug, 0, "");
69
158abb01
RG
70static int tunoutput (struct ifnet *, struct mbuf *, struct sockaddr *,
71 struct rtentry *rt);
bd4539cc 72static int tunifioctl (struct ifnet *, u_long, caddr_t, struct ucred *);
158abb01 73static int tuninit (struct ifnet *);
4d723e5a 74static void tunstart(struct ifnet *);
984263bc
MD
75
76static d_open_t tunopen;
77static d_close_t tunclose;
78static d_read_t tunread;
79static d_write_t tunwrite;
80static d_ioctl_t tunioctl;
81static d_poll_t tunpoll;
82
83#define CDEV_MAJOR 52
84static struct cdevsw tun_cdevsw = {
fabb8ceb
MD
85 /* name */ "tun",
86 /* maj */ CDEV_MAJOR,
87 /* flags */ 0,
88 /* port */ NULL,
455fcd7e 89 /* clone */ NULL,
fabb8ceb 90
984263bc
MD
91 /* open */ tunopen,
92 /* close */ tunclose,
93 /* read */ tunread,
94 /* write */ tunwrite,
95 /* ioctl */ tunioctl,
96 /* poll */ tunpoll,
97 /* mmap */ nommap,
98 /* strategy */ nostrategy,
984263bc 99 /* dump */ nodump,
fabb8ceb 100 /* psize */ nopsize
984263bc
MD
101};
102
103static void
e4c9c0c8 104tunattach(void *dummy)
984263bc 105{
e4c9c0c8 106 cdevsw_add(&tun_cdevsw, 0, 0);
984263bc
MD
107}
108
109static void
110tuncreate(dev)
111 dev_t dev;
112{
113 struct tun_softc *sc;
114 struct ifnet *ifp;
115
116 dev = make_dev(&tun_cdevsw, minor(dev),
117 UID_UUCP, GID_DIALER, 0600, "tun%d", lminor(dev));
118
119 MALLOC(sc, struct tun_softc *, sizeof(*sc), M_TUN, M_WAITOK);
120 bzero(sc, sizeof *sc);
121 sc->tun_flags = TUN_INITED;
122
123 ifp = &sc->tun_if;
cdb7d804 124 if_initname(ifp, "tun", lminor(dev));
984263bc
MD
125 ifp->if_mtu = TUNMTU;
126 ifp->if_ioctl = tunifioctl;
127 ifp->if_output = tunoutput;
4d723e5a 128 ifp->if_start = tunstart;
984263bc
MD
129 ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
130 ifp->if_type = IFT_PPP;
4d723e5a
JS
131 ifq_set_maxlen(&ifp->if_snd, ifqmaxlen);
132 ifq_set_ready(&ifp->if_snd);
984263bc 133 ifp->if_softc = sc;
78195a76 134 if_attach(ifp, NULL);
984263bc
MD
135 bpfattach(ifp, DLT_NULL, sizeof(u_int));
136 dev->si_drv1 = sc;
137}
138
139/*
140 * tunnel open - must be superuser & the device must be
141 * configured in
142 */
143static int
41c20dac 144tunopen(dev_t dev, int flag, int mode, struct thread *td)
984263bc
MD
145{
146 struct ifnet *ifp;
147 struct tun_softc *tp;
82ed7fc2 148 int error;
984263bc 149
41c20dac 150 KKASSERT(td->td_proc);
dadab5e9 151 if ((error = suser(td)) != NULL)
984263bc
MD
152 return (error);
153
154 tp = dev->si_drv1;
155 if (!tp) {
156 tuncreate(dev);
157 tp = dev->si_drv1;
158 }
159 if (tp->tun_flags & TUN_OPEN)
160 return EBUSY;
41c20dac 161 tp->tun_pid = td->td_proc->p_pid;
984263bc
MD
162 ifp = &tp->tun_if;
163 tp->tun_flags |= TUN_OPEN;
02b6afba 164 TUNDEBUG(ifp, "open\n");
984263bc
MD
165 return (0);
166}
167
168/*
169 * tunclose - close the device - mark i/f down & delete
170 * routing info
171 */
172static int
41c20dac 173tunclose(dev_t dev, int foo, int bar, struct thread *td)
984263bc 174{
984263bc
MD
175 struct tun_softc *tp;
176 struct ifnet *ifp;
984263bc
MD
177
178 tp = dev->si_drv1;
179 ifp = &tp->tun_if;
180
181 tp->tun_flags &= ~TUN_OPEN;
182 tp->tun_pid = 0;
183
4d723e5a 184 /* Junk all pending output. */
78195a76 185 lwkt_serialize_enter(ifp->if_serializer);
4d723e5a 186 ifq_purge(&ifp->if_snd);
78195a76 187 lwkt_serialize_exit(ifp->if_serializer);
984263bc
MD
188
189 if (ifp->if_flags & IFF_UP) {
78195a76 190 lwkt_serialize_enter(ifp->if_serializer);
984263bc 191 if_down(ifp);
78195a76 192 lwkt_serialize_exit(ifp->if_serializer);
984263bc
MD
193 }
194
195 if (ifp->if_flags & IFF_RUNNING) {
82ed7fc2 196 struct ifaddr *ifa;
984263bc 197
78195a76 198 lwkt_serialize_enter(ifp->if_serializer);
984263bc 199 /* find internet addresses and delete routes */
78195a76
MD
200 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
201 if (ifa->ifa_addr->sa_family == AF_INET) {
984263bc
MD
202 rtinit(ifa, (int)RTM_DELETE,
203 tp->tun_flags & TUN_DSTADDR ? RTF_HOST : 0);
78195a76
MD
204 }
205 }
984263bc 206 ifp->if_flags &= ~IFF_RUNNING;
78195a76 207 lwkt_serialize_exit(ifp->if_serializer);
984263bc
MD
208 }
209
210 funsetown(tp->tun_sigio);
211 selwakeup(&tp->tun_rsel);
212
02b6afba 213 TUNDEBUG(ifp, "closed\n");
984263bc
MD
214 return (0);
215}
216
217static int
218tuninit(ifp)
219 struct ifnet *ifp;
220{
221 struct tun_softc *tp = ifp->if_softc;
82ed7fc2 222 struct ifaddr *ifa;
984263bc
MD
223 int error = 0;
224
02b6afba 225 TUNDEBUG(ifp, "tuninit\n");
984263bc
MD
226
227 ifp->if_flags |= IFF_UP | IFF_RUNNING;
228 getmicrotime(&ifp->if_lastchange);
229
230 for (ifa = TAILQ_FIRST(&ifp->if_addrhead); ifa;
231 ifa = TAILQ_NEXT(ifa, ifa_link)) {
232 if (ifa->ifa_addr == NULL)
233 error = EFAULT;
234 /* XXX: Should maybe return straight off? */
235 else {
236#ifdef INET
237 if (ifa->ifa_addr->sa_family == AF_INET) {
238 struct sockaddr_in *si;
239
240 si = (struct sockaddr_in *)ifa->ifa_addr;
241 if (si->sin_addr.s_addr)
242 tp->tun_flags |= TUN_IASET;
243
244 si = (struct sockaddr_in *)ifa->ifa_dstaddr;
245 if (si && si->sin_addr.s_addr)
246 tp->tun_flags |= TUN_DSTADDR;
247 }
248#endif
249 }
250 }
251 return (error);
252}
253
254/*
255 * Process an ioctl request.
78195a76
MD
256 *
257 * MPSAFE
984263bc
MD
258 */
259int
bd4539cc 260tunifioctl(ifp, cmd, data, cr)
984263bc
MD
261 struct ifnet *ifp;
262 u_long cmd;
263 caddr_t data;
bd4539cc 264 struct ucred *cr;
984263bc
MD
265{
266 struct ifreq *ifr = (struct ifreq *)data;
267 struct tun_softc *tp = ifp->if_softc;
268 struct ifstat *ifs;
03522324
JS
269 int error = 0;
270
984263bc
MD
271 switch(cmd) {
272 case SIOCGIFSTATUS:
273 ifs = (struct ifstat *)data;
274 if (tp->tun_pid)
275 sprintf(ifs->ascii + strlen(ifs->ascii),
276 "\tOpened by PID %d\n", tp->tun_pid);
277 break;
278 case SIOCSIFADDR:
279 error = tuninit(ifp);
02b6afba 280 TUNDEBUG(ifp, "address set, error=%d\n", error);
984263bc
MD
281 break;
282 case SIOCSIFDSTADDR:
283 error = tuninit(ifp);
02b6afba 284 TUNDEBUG(ifp, "destination address set, error=%d\n", error);
984263bc
MD
285 break;
286 case SIOCSIFMTU:
287 ifp->if_mtu = ifr->ifr_mtu;
02b6afba 288 TUNDEBUG(ifp, "mtu set\n");
984263bc
MD
289 break;
290 case SIOCSIFFLAGS:
291 case SIOCADDMULTI:
292 case SIOCDELMULTI:
293 break;
294 default:
295 error = EINVAL;
296 }
984263bc
MD
297 return (error);
298}
299
300/*
301 * tunoutput - queue packets from higher level ready to put out.
78195a76
MD
302 *
303 * MPSAFE
984263bc
MD
304 */
305int
306tunoutput(ifp, m0, dst, rt)
307 struct ifnet *ifp;
308 struct mbuf *m0;
309 struct sockaddr *dst;
310 struct rtentry *rt;
311{
312 struct tun_softc *tp = ifp->if_softc;
03522324 313 int error;
4d723e5a 314 struct altq_pktattr pktattr;
984263bc 315
02b6afba 316 TUNDEBUG(ifp, "tunoutput\n");
984263bc
MD
317
318 if ((tp->tun_flags & TUN_READY) != TUN_READY) {
02b6afba 319 TUNDEBUG(ifp, "not ready 0%o\n", tp->tun_flags);
984263bc
MD
320 m_freem (m0);
321 return EHOSTDOWN;
322 }
323
4d723e5a
JS
324 /*
325 * if the queueing discipline needs packet classification,
326 * do it before prepending link headers.
327 */
328 ifq_classify(&ifp->if_snd, m0, dst->sa_family, &pktattr);
329
984263bc
MD
330 /* BPF write needs to be handled specially */
331 if (dst->sa_family == AF_UNSPEC) {
332 dst->sa_family = *(mtod(m0, int *));
333 m0->m_len -= sizeof(int);
334 m0->m_pkthdr.len -= sizeof(int);
335 m0->m_data += sizeof(int);
336 }
337
338 if (ifp->if_bpf) {
339 /*
340 * We need to prepend the address family as
1f8e62c9 341 * a four byte field.
984263bc 342 */
984263bc
MD
343 uint32_t af = dst->sa_family;
344
1f8e62c9 345 bpf_ptap(ifp->if_bpf, m0, &af, sizeof(af));
984263bc
MD
346 }
347
348 /* prepend sockaddr? this may abort if the mbuf allocation fails */
349 if (tp->tun_flags & TUN_LMODE) {
350 /* allocate space for sockaddr */
74f1caca 351 M_PREPEND(m0, dst->sa_len, MB_DONTWAIT);
984263bc
MD
352
353 /* if allocation failed drop packet */
354 if (m0 == NULL){
984263bc 355 IF_DROP(&ifp->if_snd);
984263bc
MD
356 ifp->if_oerrors++;
357 return (ENOBUFS);
358 } else {
359 bcopy(dst, m0->m_data, dst->sa_len);
360 }
361 }
362
363 if (tp->tun_flags & TUN_IFHEAD) {
364 /* Prepend the address family */
74f1caca 365 M_PREPEND(m0, 4, MB_DONTWAIT);
984263bc
MD
366
367 /* if allocation failed drop packet */
368 if (m0 == NULL){
984263bc 369 IF_DROP(&ifp->if_snd);
984263bc
MD
370 ifp->if_oerrors++;
371 return ENOBUFS;
372 } else
373 *(u_int32_t *)m0->m_data = htonl(dst->sa_family);
374 } else {
375#ifdef INET
376 if (dst->sa_family != AF_INET)
377#endif
378 {
379 m_freem(m0);
380 return EAFNOSUPPORT;
381 }
382 }
383
e38741f7 384 error = ifq_handoff(ifp, m0, &pktattr);
0bf52946 385 if (error) {
984263bc 386 ifp->if_collisions++;
0bf52946 387 } else {
e38741f7 388 ifp->if_opackets++;
0bf52946
JS
389 if (tp->tun_flags & TUN_RWAIT) {
390 tp->tun_flags &= ~TUN_RWAIT;
78195a76 391 wakeup((caddr_t)tp);
0bf52946 392 }
78195a76 393 get_mplock();
0bf52946
JS
394 if (tp->tun_flags & TUN_ASYNC && tp->tun_sigio)
395 pgsigio(tp->tun_sigio, SIGIO, 0);
396 selwakeup(&tp->tun_rsel);
78195a76 397 rel_mplock();
0bf52946 398 }
e38741f7 399 return (error);
984263bc
MD
400}
401
402/*
403 * the cdevsw interface is now pretty minimal.
404 */
405static int
41c20dac 406tunioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
984263bc 407{
984263bc
MD
408 struct tun_softc *tp = dev->si_drv1;
409 struct tuninfo *tunp;
410
411 switch (cmd) {
412 case TUNSIFINFO:
413 tunp = (struct tuninfo *)data;
414 if (tunp->mtu < IF_MINMTU)
415 return (EINVAL);
416 tp->tun_if.if_mtu = tunp->mtu;
417 tp->tun_if.if_type = tunp->type;
418 tp->tun_if.if_baudrate = tunp->baudrate;
419 break;
420 case TUNGIFINFO:
421 tunp = (struct tuninfo *)data;
422 tunp->mtu = tp->tun_if.if_mtu;
423 tunp->type = tp->tun_if.if_type;
424 tunp->baudrate = tp->tun_if.if_baudrate;
425 break;
426 case TUNSDEBUG:
427 tundebug = *(int *)data;
428 break;
429 case TUNGDEBUG:
430 *(int *)data = tundebug;
431 break;
432 case TUNSLMODE:
433 if (*(int *)data) {
434 tp->tun_flags |= TUN_LMODE;
435 tp->tun_flags &= ~TUN_IFHEAD;
436 } else
437 tp->tun_flags &= ~TUN_LMODE;
438 break;
439 case TUNSIFHEAD:
440 if (*(int *)data) {
441 tp->tun_flags |= TUN_IFHEAD;
442 tp->tun_flags &= ~TUN_LMODE;
443 } else
444 tp->tun_flags &= ~TUN_IFHEAD;
445 break;
446 case TUNGIFHEAD:
447 *(int *)data = (tp->tun_flags & TUN_IFHEAD) ? 1 : 0;
448 break;
449 case TUNSIFMODE:
450 /* deny this if UP */
451 if (tp->tun_if.if_flags & IFF_UP)
452 return(EBUSY);
453
454 switch (*(int *)data & ~IFF_MULTICAST) {
455 case IFF_POINTOPOINT:
456 case IFF_BROADCAST:
457 tp->tun_if.if_flags &= ~(IFF_BROADCAST|IFF_POINTOPOINT);
458 tp->tun_if.if_flags |= *(int *)data;
459 break;
460 default:
461 return(EINVAL);
462 }
463 break;
464 case TUNSIFPID:
465 tp->tun_pid = curproc->p_pid;
466 break;
467 case FIONBIO:
468 break;
469 case FIOASYNC:
470 if (*(int *)data)
471 tp->tun_flags |= TUN_ASYNC;
472 else
473 tp->tun_flags &= ~TUN_ASYNC;
474 break;
475 case FIONREAD:
78195a76 476 lwkt_serialize_enter(tp->tun_if.if_serializer);
4d723e5a
JS
477 if (!ifq_is_empty(&tp->tun_if.if_snd)) {
478 struct mbuf *mb;
479
480 mb = ifq_poll(&tp->tun_if.if_snd);
984263bc
MD
481 for( *(int *)data = 0; mb != 0; mb = mb->m_next)
482 *(int *)data += mb->m_len;
78195a76 483 } else {
984263bc 484 *(int *)data = 0;
78195a76
MD
485 }
486 lwkt_serialize_exit(tp->tun_if.if_serializer);
984263bc
MD
487 break;
488 case FIOSETOWN:
489 return (fsetown(*(int *)data, &tp->tun_sigio));
490
491 case FIOGETOWN:
492 *(int *)data = fgetown(tp->tun_sigio);
493 return (0);
494
495 /* This is deprecated, FIOSETOWN should be used instead. */
496 case TIOCSPGRP:
497 return (fsetown(-(*(int *)data), &tp->tun_sigio));
498
499 /* This is deprecated, FIOGETOWN should be used instead. */
500 case TIOCGPGRP:
501 *(int *)data = -fgetown(tp->tun_sigio);
502 return (0);
503
504 default:
505 return (ENOTTY);
506 }
507 return (0);
508}
509
510/*
511 * The cdevsw read interface - reads a packet at a time, or at
512 * least as much of a packet as can be read.
513 */
514static int
515tunread(dev, uio, flag)
516 dev_t dev;
517 struct uio *uio;
518 int flag;
519{
520 struct tun_softc *tp = dev->si_drv1;
521 struct ifnet *ifp = &tp->tun_if;
522 struct mbuf *m0;
03522324 523 int error=0, len;
984263bc 524
02b6afba 525 TUNDEBUG(ifp, "read\n");
984263bc 526 if ((tp->tun_flags & TUN_READY) != TUN_READY) {
02b6afba 527 TUNDEBUG(ifp, "not ready 0%o\n", tp->tun_flags);
984263bc
MD
528 return EHOSTDOWN;
529 }
530
531 tp->tun_flags &= ~TUN_RWAIT;
532
78195a76 533 lwkt_serialize_enter(ifp->if_serializer);
03522324 534
d2c71fa0 535 while ((m0 = ifq_dequeue(&ifp->if_snd, NULL)) == NULL) {
c934080f 536 if (flag & IO_NDELAY) {
78195a76 537 lwkt_serialize_exit(ifp->if_serializer);
c934080f 538 return EWOULDBLOCK;
984263bc 539 }
c934080f
JS
540 tp->tun_flags |= TUN_RWAIT;
541 if ((error = tsleep(tp, PCATCH, "tunread", 0)) != 0) {
78195a76 542 lwkt_serialize_exit(ifp->if_serializer);
c934080f
JS
543 return error;
544 }
545 }
03522324 546
78195a76 547 lwkt_serialize_exit(ifp->if_serializer);
984263bc
MD
548
549 while (m0 && uio->uio_resid > 0 && error == 0) {
550 len = min(uio->uio_resid, m0->m_len);
551 if (len != 0)
552 error = uiomove(mtod(m0, caddr_t), len, uio);
553 m0 = m_free(m0);
554 }
555
556 if (m0) {
02b6afba 557 TUNDEBUG(ifp, "Dropping mbuf\n");
984263bc
MD
558 m_freem(m0);
559 }
560 return error;
561}
562
563/*
564 * the cdevsw write interface - an atomic write is a packet - or else!
565 */
566static int
567tunwrite(dev, uio, flag)
568 dev_t dev;
569 struct uio *uio;
570 int flag;
571{
572 struct tun_softc *tp = dev->si_drv1;
573 struct ifnet *ifp = &tp->tun_if;
574 struct mbuf *top, **mp, *m;
575 int error=0, tlen, mlen;
576 uint32_t family;
8bde602d 577 int isr;
984263bc 578
02b6afba 579 TUNDEBUG(ifp, "tunwrite\n");
984263bc
MD
580
581 if (uio->uio_resid == 0)
582 return 0;
583
584 if (uio->uio_resid < 0 || uio->uio_resid > TUNMRU) {
02b6afba 585 TUNDEBUG(ifp, "len=%d!\n", uio->uio_resid);
984263bc
MD
586 return EIO;
587 }
588 tlen = uio->uio_resid;
589
590 /* get a header mbuf */
74f1caca 591 MGETHDR(m, MB_DONTWAIT, MT_DATA);
984263bc
MD
592 if (m == NULL)
593 return ENOBUFS;
594 mlen = MHLEN;
595
596 top = 0;
597 mp = &top;
598 while (error == 0 && uio->uio_resid > 0) {
599 m->m_len = min(mlen, uio->uio_resid);
600 error = uiomove(mtod (m, caddr_t), m->m_len, uio);
601 *mp = m;
602 mp = &m->m_next;
603 if (uio->uio_resid > 0) {
74f1caca 604 MGET (m, MB_DONTWAIT, MT_DATA);
984263bc
MD
605 if (m == 0) {
606 error = ENOBUFS;
607 break;
608 }
609 mlen = MLEN;
610 }
611 }
612 if (error) {
613 if (top)
614 m_freem (top);
615 ifp->if_ierrors++;
616 return error;
617 }
618
619 top->m_pkthdr.len = tlen;
620 top->m_pkthdr.rcvif = ifp;
621
622 if (ifp->if_bpf) {
623 if (tp->tun_flags & TUN_IFHEAD) {
624 /*
625 * Conveniently, we already have a 4-byte address
626 * family prepended to our packet !
627 * Inconveniently, it's in the wrong byte order !
628 */
629 if ((top = m_pullup(top, sizeof(family))) == NULL)
630 return ENOBUFS;
631 *mtod(top, u_int32_t *) =
632 ntohl(*mtod(top, u_int32_t *));
1f8e62c9 633 bpf_mtap(ifp->if_bpf, top);
984263bc
MD
634 *mtod(top, u_int32_t *) =
635 htonl(*mtod(top, u_int32_t *));
636 } else {
637 /*
638 * We need to prepend the address family as
1f8e62c9 639 * a four byte field.
984263bc 640 */
1f8e62c9 641 static const uint32_t af = AF_INET;
984263bc 642
1f8e62c9 643 bpf_ptap(ifp->if_bpf, top, &af, sizeof(af));
984263bc
MD
644 }
645 }
646
647 if (tp->tun_flags & TUN_IFHEAD) {
648 if (top->m_len < sizeof(family) &&
649 (top = m_pullup(top, sizeof(family))) == NULL)
650 return ENOBUFS;
651 family = ntohl(*mtod(top, u_int32_t *));
652 m_adj(top, sizeof(family));
653 } else
654 family = AF_INET;
655
656 ifp->if_ibytes += top->m_pkthdr.len;
657 ifp->if_ipackets++;
658
8bde602d
JH
659 switch (family) {
660#ifdef INET
661 case AF_INET:
662 isr = NETISR_IP;
663 break;
664#endif
665#ifdef INET6
666 case AF_INET6:
667 isr = NETISR_IPV6;
668 break;
669#endif
670#ifdef IPX
671 case AF_IPX:
672 isr = NETISR_IPX;
673 break;
674#endif
675#ifdef NETATALK
676 case AF_APPLETALK:
677 isr = NETISR_ATALK2;
678 break;
679#endif
680 default:
681 m_freem(m);
682 return (EAFNOSUPPORT);
683 }
684
685 netisr_dispatch(isr, top);
686 return (0);
984263bc
MD
687}
688
689/*
690 * tunpoll - the poll interface, this is only useful on reads
691 * really. The write detect always returns true, write never blocks
692 * anyway, it either accepts the packet or drops it.
693 */
694static int
41c20dac 695tunpoll(dev_t dev, int events, struct thread *td)
984263bc 696{
984263bc
MD
697 struct tun_softc *tp = dev->si_drv1;
698 struct ifnet *ifp = &tp->tun_if;
699 int revents = 0;
700
02b6afba 701 TUNDEBUG(ifp, "tunpoll\n");
984263bc 702
78195a76 703 lwkt_serialize_enter(ifp->if_serializer);
03522324 704
984263bc 705 if (events & (POLLIN | POLLRDNORM)) {
4d723e5a 706 if (!ifq_is_empty(&ifp->if_snd)) {
02b6afba 707 TUNDEBUG(ifp, "tunpoll q=%d\n", ifp->if_snd.ifq_len);
984263bc
MD
708 revents |= events & (POLLIN | POLLRDNORM);
709 } else {
02b6afba 710 TUNDEBUG(ifp, "tunpoll waiting\n");
41c20dac 711 selrecord(td, &tp->tun_rsel);
984263bc
MD
712 }
713 }
714 if (events & (POLLOUT | POLLWRNORM))
715 revents |= events & (POLLOUT | POLLWRNORM);
716
78195a76 717 lwkt_serialize_exit(ifp->if_serializer);
03522324 718
984263bc
MD
719 return (revents);
720}
4d723e5a
JS
721
722/*
723 * Start packet transmission on the interface.
724 * when the interface queue is rate-limited by ALTQ,
725 * if_start is needed to drain packets from the queue in order
726 * to notify readers when outgoing packets become ready.
727 */
728static void
729tunstart(struct ifnet *ifp)
730{
731 struct tun_softc *tp = ifp->if_softc;
732 struct mbuf *m;
733
734 if (!ifq_is_enabled(&ifp->if_snd))
735 return;
736
737 m = ifq_poll(&ifp->if_snd);
738 if (m != NULL) {
739 if (tp->tun_flags & TUN_RWAIT) {
740 tp->tun_flags &= ~TUN_RWAIT;
741 wakeup((caddr_t)tp);
742 }
743 if (tp->tun_flags & TUN_ASYNC && tp->tun_sigio)
744 pgsigio(tp->tun_sigio, SIGIO, 0);
745 selwakeup(&tp->tun_rsel);
746 }
747}