Annotation of sys/net/if_tun.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: if_tun.c,v 1.89 2007/06/06 10:04:36 henning Exp $ */
2: /* $NetBSD: if_tun.c,v 1.24 1996/05/07 02:40:48 thorpej Exp $ */
3:
4: /*
5: * Copyright (c) 1988, Julian Onions <Julian.Onions@nexor.co.uk>
6: * Nottingham University 1987.
7: * All rights reserved.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: *
18: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28: */
29:
30: /*
31: * This driver takes packets off the IP i/f and hands them up to a
32: * user process to have its wicked way with. This driver has its
33: * roots in a similar driver written by Phil Cockcroft (formerly) at
34: * UCL. This driver is based much more on read/write/select mode of
35: * operation though.
36: */
37:
38: /* #define TUN_DEBUG 9 */
39:
40: #include <sys/param.h>
41: #include <sys/kernel.h>
42: #include <sys/proc.h>
43: #include <sys/systm.h>
44: #include <sys/mbuf.h>
45: #include <sys/protosw.h>
46: #include <sys/socket.h>
47: #include <sys/ioctl.h>
48: #include <sys/errno.h>
49: #include <sys/syslog.h>
50: #include <sys/selinfo.h>
51: #include <sys/file.h>
52: #include <sys/time.h>
53: #include <sys/device.h>
54: #include <sys/vnode.h>
55: #include <sys/signalvar.h>
56: #include <sys/poll.h>
57: #include <sys/conf.h>
58:
59: #include <machine/cpu.h>
60:
61: #include <net/if.h>
62: #include <net/if_types.h>
63: #include <net/netisr.h>
64: #include <net/route.h>
65:
66: #ifdef INET
67: #include <netinet/in.h>
68: #include <netinet/in_systm.h>
69: #include <netinet/in_var.h>
70: #include <netinet/ip.h>
71: #include <netinet/if_ether.h>
72: #endif
73:
74: #ifdef NETATALK
75: #include <netatalk/at.h>
76: #include <netatalk/at_var.h>
77: #endif
78:
79: #include "bpfilter.h"
80: #if NBPFILTER > 0
81: #include <net/bpf.h>
82: #endif
83:
84: /* for arc4random() */
85: #include <dev/rndvar.h>
86:
87: #include <net/if_tun.h>
88:
89: struct tun_softc {
90: struct arpcom arpcom; /* ethernet common data */
91: u_short tun_flags; /* misc flags */
92: pid_t tun_pgid; /* the process group - if any */
93: uid_t tun_siguid; /* uid for process that set tun_pgid */
94: uid_t tun_sigeuid; /* euid for process that set tun_pgid */
95: struct selinfo tun_rsel; /* read select */
96: struct selinfo tun_wsel; /* write select (not used) */
97: int tun_unit;
98: LIST_ENTRY(tun_softc) tun_list; /* all tunnel interfaces */
99: #define tun_if arpcom.ac_if
100: };
101:
102: #ifdef TUN_DEBUG
103: int tundebug = TUN_DEBUG;
104: #define TUNDEBUG(a) (tundebug? printf a : 0)
105: #else
106: #define TUNDEBUG(a) /* (tundebug? printf a : 0) */
107: #endif
108:
109: /* Only these IFF flags are changeable by TUNSIFINFO */
110: #define TUN_IFF_FLAGS (IFF_UP|IFF_POINTOPOINT|IFF_MULTICAST|IFF_BROADCAST)
111:
112: void tunattach(int);
113: int tunopen(dev_t, int, int, struct proc *);
114: int tunclose(dev_t, int, int, struct proc *);
115: int tun_ioctl(struct ifnet *, u_long, caddr_t);
116: int tun_output(struct ifnet *, struct mbuf *, struct sockaddr *,
117: struct rtentry *);
118: int tunioctl(dev_t, u_long, caddr_t, int, struct proc *);
119: int tunread(dev_t, struct uio *, int);
120: int tunwrite(dev_t, struct uio *, int);
121: int tunpoll(dev_t, int, struct proc *);
122: int tunkqfilter(dev_t, struct knote *);
123: int tun_clone_create(struct if_clone *, int);
124: int tun_create(struct if_clone *, int, int);
125: int tun_clone_destroy(struct ifnet *);
126: struct tun_softc *tun_lookup(int);
127: void tun_wakeup(struct tun_softc *);
128: int tun_switch(struct tun_softc *, int);
129:
130: static int tuninit(struct tun_softc *);
131: static void tunstart(struct ifnet *);
132: int filt_tunread(struct knote *, long);
133: int filt_tunwrite(struct knote *, long);
134: void filt_tunrdetach(struct knote *);
135: void filt_tunwdetach(struct knote *);
136:
137: struct filterops tunread_filtops =
138: { 1, NULL, filt_tunrdetach, filt_tunread};
139:
140: struct filterops tunwrite_filtops =
141: { 1, NULL, filt_tunwdetach, filt_tunwrite};
142:
143: LIST_HEAD(, tun_softc) tun_softc_list;
144:
145: struct if_clone tun_cloner =
146: IF_CLONE_INITIALIZER("tun", tun_clone_create, tun_clone_destroy);
147:
148: void
149: tunattach(int n)
150: {
151: LIST_INIT(&tun_softc_list);
152: if_clone_attach(&tun_cloner);
153: }
154:
155: int
156: tun_clone_create(struct if_clone *ifc, int unit)
157: {
158: return (tun_create(ifc, unit, 0));
159: }
160:
161: int
162: tun_create(struct if_clone *ifc, int unit, int flags)
163: {
164: struct tun_softc *tp;
165: struct ifnet *ifp;
166: u_int32_t macaddr_rnd;
167: int s;
168:
169: tp = malloc(sizeof(*tp), M_DEVBUF, M_NOWAIT);
170: if (!tp)
171: return (ENOMEM);
172: bzero(tp, sizeof(*tp));
173:
174: tp->tun_unit = unit;
175: tp->tun_flags = TUN_INITED|TUN_STAYUP;
176:
177: /* generate fake MAC address: 00 bd xx xx xx unit_no */
178: tp->arpcom.ac_enaddr[0] = 0x00;
179: tp->arpcom.ac_enaddr[1] = 0xbd;
180: /*
181: * This no longer happens pre-scheduler so let's use the real
182: * random subsystem instead of random().
183: */
184: macaddr_rnd = arc4random();
185: bcopy(&macaddr_rnd, &tp->arpcom.ac_enaddr[2], sizeof(u_int32_t));
186: tp->arpcom.ac_enaddr[5] = (u_char)unit + 1;
187:
188: ifp = &tp->tun_if;
189: snprintf(ifp->if_xname, sizeof ifp->if_xname, "%s%d", ifc->ifc_name,
190: unit);
191: ifp->if_softc = tp;
192: ifp->if_ioctl = tun_ioctl;
193: ifp->if_output = tun_output;
194: ifp->if_start = tunstart;
195: IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
196: IFQ_SET_READY(&ifp->if_snd);
197: if ((flags & TUN_LAYER2) == 0) {
198: tp->tun_flags &= ~TUN_LAYER2;
199: ifp->if_mtu = ETHERMTU;
200: ifp->if_flags = IFF_POINTOPOINT;
201: ifp->if_type = IFT_TUNNEL;
202: ifp->if_hdrlen = sizeof(u_int32_t);
203: if_attach(ifp);
204: if_alloc_sadl(ifp);
205: #if NBPFILTER > 0
206: bpfattach(&ifp->if_bpf, ifp, DLT_LOOP, sizeof(u_int32_t));
207: #endif
208: } else {
209: tp->tun_flags |= TUN_LAYER2;
210: ifp->if_flags =
211: (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST|IFF_LINK0);
212: if_attach(ifp);
213: ether_ifattach(ifp);
214: }
215: /* force output function to our function */
216: ifp->if_output = tun_output;
217:
218: s = splnet();
219: LIST_INSERT_HEAD(&tun_softc_list, tp, tun_list);
220: splx(s);
221:
222: return (0);
223: }
224:
225: int
226: tun_clone_destroy(struct ifnet *ifp)
227: {
228: struct tun_softc *tp = ifp->if_softc;
229: int s;
230:
231: tun_wakeup(tp);
232:
233: s = splhigh();
234: klist_invalidate(&tp->tun_rsel.si_note);
235: klist_invalidate(&tp->tun_wsel.si_note);
236: splx(s);
237:
238: s = splnet();
239: LIST_REMOVE(tp, tun_list);
240: splx(s);
241:
242: if (tp->tun_flags & TUN_LAYER2)
243: ether_ifdetach(ifp);
244:
245: if_detach(ifp);
246:
247: free(tp, M_DEVBUF);
248: return (0);
249: }
250:
251: struct tun_softc *
252: tun_lookup(int unit)
253: {
254: struct tun_softc *tp;
255:
256: LIST_FOREACH(tp, &tun_softc_list, tun_list)
257: if (tp->tun_unit == unit)
258: return (tp);
259: return (NULL);
260: }
261:
262: int
263: tun_switch(struct tun_softc *tp, int flags)
264: {
265: struct ifnet *ifp = &tp->tun_if;
266: int unit, open, r;
267:
268: if ((tp->tun_flags & TUN_LAYER2) == (flags & TUN_LAYER2))
269: return (0);
270:
271: /* tp will be removed so store unit number */
272: unit = tp->tun_unit;
273: open = tp->tun_flags & (TUN_OPEN|TUN_NBIO|TUN_ASYNC);
274: TUNDEBUG(("%s: switching to layer %d\n", ifp->if_xname,
275: flags & TUN_LAYER2 ? 2 : 3));
276:
277: /* remove old device and ... */
278: tun_clone_destroy(ifp);
279: /* attach new interface */
280: r = tun_create(&tun_cloner, unit, flags);
281:
282: if (open && r == 0) {
283: /* already opened before ifconfig tunX link0 */
284: if ((tp = tun_lookup(unit)) == NULL)
285: /* this should never fail */
286: return (ENXIO);
287: tp->tun_flags |= open;
288: TUNDEBUG(("%s: already open\n", tp->tun_if.if_xname));
289: }
290: return (r);
291: }
292:
293: /*
294: * tunnel open - must be superuser & the device must be
295: * configured in
296: */
297: int
298: tunopen(dev_t dev, int flag, int mode, struct proc *p)
299: {
300: struct tun_softc *tp;
301: struct ifnet *ifp;
302: int error, s;
303:
304: if ((error = suser(p, 0)) != 0)
305: return (error);
306:
307: if ((tp = tun_lookup(minor(dev))) == NULL) { /* create on demand */
308: char xname[IFNAMSIZ];
309:
310: snprintf(xname, sizeof(xname), "%s%d", "tun", minor(dev));
311: if ((error = if_clone_create(xname)) != 0)
312: return (error);
313:
314: if ((tp = tun_lookup(minor(dev))) == NULL)
315: return (ENXIO);
316: tp->tun_flags &= ~TUN_STAYUP;
317: }
318:
319: if (tp->tun_flags & TUN_OPEN)
320: return (EBUSY);
321:
322: ifp = &tp->tun_if;
323: tp->tun_flags |= TUN_OPEN;
324:
325: /* automatically UP the interface on open */
326: s = splnet();
327: if_up(ifp);
328: ifp->if_flags |= IFF_RUNNING;
329: splx(s);
330:
331: TUNDEBUG(("%s: open\n", ifp->if_xname));
332: return (0);
333: }
334:
335: /*
336: * tunclose - close the device; if closing the real device, flush pending
337: * output and unless STAYUP bring down and destroy the interface.
338: */
339: int
340: tunclose(dev_t dev, int flag, int mode, struct proc *p)
341: {
342: int s;
343: struct tun_softc *tp;
344: struct ifnet *ifp;
345:
346: if ((tp = tun_lookup(minor(dev))) == NULL)
347: return (ENXIO);
348:
349: ifp = &tp->tun_if;
350: tp->tun_flags &= ~(TUN_OPEN|TUN_NBIO|TUN_ASYNC);
351: ifp->if_flags &= ~IFF_RUNNING;
352:
353: /*
354: * junk all pending output
355: */
356: s = splnet();
357: IFQ_PURGE(&ifp->if_snd);
358: splx(s);
359:
360: TUNDEBUG(("%s: closed\n", ifp->if_xname));
361:
362: if (!(tp->tun_flags & TUN_STAYUP))
363: return (if_clone_destroy(ifp->if_xname));
364: else {
365: tp->tun_pgid = 0;
366: selwakeup(&tp->tun_rsel);
367: KNOTE(&tp->tun_rsel.si_note, 0);
368: }
369:
370: return (0);
371: }
372:
373: static int
374: tuninit(struct tun_softc *tp)
375: {
376: struct ifnet *ifp = &tp->tun_if;
377: struct ifaddr *ifa;
378:
379: TUNDEBUG(("%s: tuninit\n", ifp->if_xname));
380:
381: ifp->if_flags |= IFF_UP | IFF_RUNNING;
382: ifp->if_flags &= ~IFF_OACTIVE; /* we are never active */
383:
384: tp->tun_flags &= ~(TUN_IASET|TUN_DSTADDR|TUN_BRDADDR);
385: TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
386: #ifdef INET
387: if (ifa->ifa_addr->sa_family == AF_INET) {
388: struct sockaddr_in *sin;
389:
390: sin = satosin(ifa->ifa_addr);
391: if (sin && sin->sin_addr.s_addr)
392: tp->tun_flags |= TUN_IASET;
393:
394: if (ifp->if_flags & IFF_POINTOPOINT) {
395: sin = satosin(ifa->ifa_dstaddr);
396: if (sin && sin->sin_addr.s_addr)
397: tp->tun_flags |= TUN_DSTADDR;
398: } else
399: tp->tun_flags &= ~TUN_DSTADDR;
400:
401: if (ifp->if_flags & IFF_BROADCAST) {
402: sin = satosin(ifa->ifa_broadaddr);
403: if (sin && sin->sin_addr.s_addr)
404: tp->tun_flags |= TUN_BRDADDR;
405: } else
406: tp->tun_flags &= ~TUN_BRDADDR;
407: }
408: #endif
409: #ifdef INET6
410: if (ifa->ifa_addr->sa_family == AF_INET6) {
411: struct sockaddr_in6 *sin;
412:
413: sin = (struct sockaddr_in6 *)ifa->ifa_addr;
414: if (!IN6_IS_ADDR_UNSPECIFIED(&sin->sin6_addr))
415: tp->tun_flags |= TUN_IASET;
416:
417: if (ifp->if_flags & IFF_POINTOPOINT) {
418: sin = (struct sockaddr_in6 *)ifa->ifa_dstaddr;
419: if (sin &&
420: !IN6_IS_ADDR_UNSPECIFIED(&sin->sin6_addr))
421: tp->tun_flags |= TUN_DSTADDR;
422: } else
423: tp->tun_flags &= ~TUN_DSTADDR;
424: }
425: #endif /* INET6 */
426: }
427:
428: return (0);
429: }
430:
431: /*
432: * Process an ioctl request.
433: */
434: int
435: tun_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
436: {
437: struct tun_softc *tp = (struct tun_softc *)(ifp->if_softc);
438: struct ifreq *ifr = (struct ifreq *)data;
439: int error = 0, s;
440:
441: s = splnet();
442: if (tp->tun_flags & TUN_LAYER2)
443: if ((error = ether_ioctl(ifp, &tp->arpcom, cmd, data)) > 0) {
444: splx(s);
445: return (error);
446: }
447: switch (cmd) {
448: case SIOCSIFADDR:
449: tuninit(tp);
450: TUNDEBUG(("%s: address set\n", ifp->if_xname));
451: if (tp->tun_flags & TUN_LAYER2)
452: switch (((struct ifaddr *)data)->ifa_addr->sa_family) {
453: #ifdef INET
454: case AF_INET:
455: arp_ifinit(&tp->arpcom, (struct ifaddr *)data);
456: break;
457: #endif
458: default:
459: break;
460: }
461: break;
462: case SIOCSIFDSTADDR:
463: tuninit(tp);
464: TUNDEBUG(("%s: destination address set\n", ifp->if_xname));
465: break;
466: case SIOCSIFBRDADDR:
467: tuninit(tp);
468: TUNDEBUG(("%s: broadcast address set\n", ifp->if_xname));
469: break;
470: case SIOCSIFMTU:
471: if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > TUNMRU)
472: error = EINVAL;
473: else
474: ifp->if_mtu = ifr->ifr_mtu;
475: break;
476: case SIOCADDMULTI:
477: case SIOCDELMULTI: {
478: if (ifr == 0) {
479: error = EAFNOSUPPORT; /* XXX */
480: break;
481: }
482:
483: if (tp->tun_flags & TUN_LAYER2) {
484: error = (cmd == SIOCADDMULTI) ?
485: ether_addmulti(ifr, &tp->arpcom) :
486: ether_delmulti(ifr, &tp->arpcom);
487: if (error == ENETRESET) {
488: /*
489: * Multicast list has changed; set the hardware
490: * filter accordingly. The good thing is we do
491: * not have a hardware filter (:
492: */
493: error = 0;
494: }
495: break;
496: }
497:
498: switch (ifr->ifr_addr.sa_family) {
499: #ifdef INET
500: case AF_INET:
501: break;
502: #endif
503: #ifdef INET6
504: case AF_INET6:
505: break;
506: #endif
507: default:
508: error = EAFNOSUPPORT;
509: break;
510: }
511: break;
512: }
513:
514: case SIOCSIFFLAGS:
515: error = tun_switch(tp,
516: ifp->if_flags & IFF_LINK0 ? TUN_LAYER2 : 0);
517: break;
518: default:
519: error = EINVAL;
520: }
521: splx(s);
522: return (error);
523: }
524:
525: /*
526: * tun_output - queue packets from higher level ready to put out.
527: */
528: int
529: tun_output(struct ifnet *ifp, struct mbuf *m0, struct sockaddr *dst,
530: struct rtentry *rt)
531: {
532: struct tun_softc *tp = ifp->if_softc;
533: int s, len, error;
534: u_int32_t *af;
535:
536: if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
537: m_freem(m0);
538: return (EHOSTDOWN);
539: }
540:
541: TUNDEBUG(("%s: tun_output\n", ifp->if_xname));
542:
543: if ((tp->tun_flags & TUN_READY) != TUN_READY) {
544: TUNDEBUG(("%s: not ready %#x\n", ifp->if_xname,
545: tp->tun_flags));
546: m_freem(m0);
547: return (EHOSTDOWN);
548: }
549:
550: if (tp->tun_flags & TUN_LAYER2)
551: /* call ether_output and that will call tunstart at the end */
552: return (ether_output(ifp, m0, dst, rt));
553:
554: M_PREPEND(m0, sizeof(*af), M_DONTWAIT);
555: af = mtod(m0, u_int32_t *);
556: *af = htonl(dst->sa_family);
557:
558: #if NBPFILTER > 0
559: if (ifp->if_bpf)
560: bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
561: #endif
562:
563: len = m0->m_pkthdr.len + sizeof(*af);
564: s = splnet();
565: IFQ_ENQUEUE(&ifp->if_snd, m0, NULL, error);
566: if (error) {
567: splx(s);
568: ifp->if_collisions++;
569: return (error);
570: }
571: splx(s);
572: ifp->if_opackets++;
573: ifp->if_obytes += len;
574:
575: tun_wakeup(tp);
576: return (0);
577: }
578:
579: void
580: tun_wakeup(struct tun_softc *tp)
581: {
582: if (tp->tun_flags & TUN_RWAIT) {
583: tp->tun_flags &= ~TUN_RWAIT;
584: wakeup((caddr_t)tp);
585: }
586: if (tp->tun_flags & TUN_ASYNC && tp->tun_pgid)
587: csignal(tp->tun_pgid, SIGIO,
588: tp->tun_siguid, tp->tun_sigeuid);
589: selwakeup(&tp->tun_rsel);
590: KNOTE(&tp->tun_rsel.si_note, 0);
591: }
592:
593: /*
594: * the cdevsw interface is now pretty minimal.
595: */
596: int
597: tunioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
598: {
599: int s;
600: struct tun_softc *tp;
601: struct tuninfo *tunp;
602: struct mbuf *m;
603:
604: if ((tp = tun_lookup(minor(dev))) == NULL)
605: return (ENXIO);
606:
607: s = splnet();
608: switch (cmd) {
609: case TUNSIFINFO:
610: tunp = (struct tuninfo *)data;
611: if (tunp->mtu < ETHERMIN || tunp->mtu > TUNMRU) {
612: splx(s);
613: return (EINVAL);
614: }
615: tp->tun_if.if_mtu = tunp->mtu;
616: tp->tun_if.if_type = tunp->type;
617: tp->tun_if.if_flags =
618: (tunp->flags & TUN_IFF_FLAGS) |
619: (tp->tun_if.if_flags & ~TUN_IFF_FLAGS);
620: tp->tun_if.if_baudrate = tunp->baudrate;
621: break;
622: case TUNGIFINFO:
623: tunp = (struct tuninfo *)data;
624: tunp->mtu = tp->tun_if.if_mtu;
625: tunp->type = tp->tun_if.if_type;
626: tunp->flags = tp->tun_if.if_flags;
627: tunp->baudrate = tp->tun_if.if_baudrate;
628: break;
629: #ifdef TUN_DEBUG
630: case TUNSDEBUG:
631: tundebug = *(int *)data;
632: break;
633: case TUNGDEBUG:
634: *(int *)data = tundebug;
635: break;
636: #endif
637: case TUNSIFMODE:
638: switch (*(int *)data & (IFF_POINTOPOINT|IFF_BROADCAST)) {
639: case IFF_POINTOPOINT:
640: case IFF_BROADCAST:
641: tp->tun_if.if_flags &= ~TUN_IFF_FLAGS;
642: tp->tun_if.if_flags |= *(int *)data & TUN_IFF_FLAGS;
643: break;
644: default:
645: splx(s);
646: return (EINVAL);
647: }
648: break;
649:
650: case FIONBIO:
651: if (*(int *)data)
652: tp->tun_flags |= TUN_NBIO;
653: else
654: tp->tun_flags &= ~TUN_NBIO;
655: break;
656: case FIOASYNC:
657: if (*(int *)data)
658: tp->tun_flags |= TUN_ASYNC;
659: else
660: tp->tun_flags &= ~TUN_ASYNC;
661: break;
662: case FIONREAD:
663: IFQ_POLL(&tp->tun_if.if_snd, m);
664: if (m != NULL)
665: *(int *)data = m->m_pkthdr.len;
666: else
667: *(int *)data = 0;
668: break;
669: case TIOCSPGRP:
670: tp->tun_pgid = *(int *)data;
671: tp->tun_siguid = p->p_cred->p_ruid;
672: tp->tun_sigeuid = p->p_ucred->cr_uid;
673: break;
674: case TIOCGPGRP:
675: *(int *)data = tp->tun_pgid;
676: break;
677: case OSIOCGIFADDR:
678: case SIOCGIFADDR:
679: if (!(tp->tun_flags & TUN_LAYER2)) {
680: splx(s);
681: return (EINVAL);
682: }
683: bcopy(tp->arpcom.ac_enaddr, data,
684: sizeof(tp->arpcom.ac_enaddr));
685: break;
686:
687: case SIOCSIFADDR:
688: if (!(tp->tun_flags & TUN_LAYER2)) {
689: splx(s);
690: return (EINVAL);
691: }
692: bcopy(data, tp->arpcom.ac_enaddr,
693: sizeof(tp->arpcom.ac_enaddr));
694: break;
695: default:
696: splx(s);
697: return (ENOTTY);
698: }
699: splx(s);
700: return (0);
701: }
702:
703: /*
704: * The cdevsw read interface - reads a packet at a time, or at
705: * least as much of a packet as can be read.
706: */
707: int
708: tunread(dev_t dev, struct uio *uio, int ioflag)
709: {
710: struct tun_softc *tp;
711: struct ifnet *ifp;
712: struct mbuf *m, *m0;
713: int error = 0, len, s;
714:
715: if ((tp = tun_lookup(minor(dev))) == NULL)
716: return (ENXIO);
717:
718: ifp = &tp->tun_if;
719: TUNDEBUG(("%s: read\n", ifp->if_xname));
720: if ((tp->tun_flags & TUN_READY) != TUN_READY) {
721: TUNDEBUG(("%s: not ready %#x\n", ifp->if_xname, tp->tun_flags));
722: return (EHOSTDOWN);
723: }
724:
725: tp->tun_flags &= ~TUN_RWAIT;
726:
727: s = splnet();
728: do {
729: while ((tp->tun_flags & TUN_READY) != TUN_READY)
730: if ((error = tsleep((caddr_t)tp,
731: (PZERO + 1)|PCATCH, "tunread", 0)) != 0) {
732: splx(s);
733: return (error);
734: }
735: IFQ_DEQUEUE(&ifp->if_snd, m0);
736: if (m0 == NULL) {
737: if (tp->tun_flags & TUN_NBIO && ioflag & IO_NDELAY) {
738: splx(s);
739: return (EWOULDBLOCK);
740: }
741: tp->tun_flags |= TUN_RWAIT;
742: if ((error = tsleep((caddr_t)tp,
743: (PZERO + 1)|PCATCH, "tunread", 0)) != 0) {
744: splx(s);
745: return (error);
746: }
747: }
748: } while (m0 == NULL);
749: splx(s);
750:
751: while (m0 != NULL && uio->uio_resid > 0 && error == 0) {
752: len = min(uio->uio_resid, m0->m_len);
753: if (len != 0)
754: error = uiomove(mtod(m0, caddr_t), len, uio);
755: MFREE(m0, m);
756: m0 = m;
757: }
758:
759: if (m0 != NULL) {
760: TUNDEBUG(("Dropping mbuf\n"));
761: m_freem(m0);
762: }
763: if (error)
764: ifp->if_ierrors++;
765:
766: return (error);
767: }
768:
769: /*
770: * the cdevsw write interface - an atomic write is a packet - or else!
771: */
772: int
773: tunwrite(dev_t dev, struct uio *uio, int ioflag)
774: {
775: struct tun_softc *tp;
776: struct ifnet *ifp;
777: struct ifqueue *ifq;
778: u_int32_t *th;
779: struct mbuf *top, **mp, *m;
780: int isr;
781: int error=0, s, tlen, mlen;
782:
783: if ((tp = tun_lookup(minor(dev))) == NULL)
784: return (ENXIO);
785:
786: ifp = &tp->tun_if;
787: TUNDEBUG(("%s: tunwrite\n", ifp->if_xname));
788:
789: if (uio->uio_resid == 0 || uio->uio_resid > ifp->if_mtu +
790: (tp->tun_flags & TUN_LAYER2 ? ETHER_HDR_LEN : sizeof(*th))) {
791: TUNDEBUG(("%s: len=%d!\n", ifp->if_xname, uio->uio_resid));
792: return (EMSGSIZE);
793: }
794: tlen = uio->uio_resid;
795:
796: /* get a header mbuf */
797: MGETHDR(m, M_DONTWAIT, MT_DATA);
798: if (m == NULL)
799: return (ENOBUFS);
800: mlen = MHLEN;
801: if (uio->uio_resid >= MINCLSIZE) {
802: MCLGET(m, M_DONTWAIT);
803: if (!(m->m_flags & M_EXT)) {
804: m_free(m);
805: return (ENOBUFS);
806: }
807: mlen = MCLBYTES;
808: }
809:
810: top = NULL;
811: mp = ⊤
812: if (tp->tun_flags & TUN_LAYER2) {
813: /*
814: * Pad so that IP header is correctly aligned
815: * this is necessary for all strict aligned architectures.
816: */
817: mlen -= ETHER_ALIGN;
818: m->m_data += ETHER_ALIGN;
819: }
820: while (error == 0 && uio->uio_resid > 0) {
821: m->m_len = min(mlen, uio->uio_resid);
822: error = uiomove(mtod (m, caddr_t), m->m_len, uio);
823: *mp = m;
824: mp = &m->m_next;
825: if (error == 0 && uio->uio_resid > 0) {
826: MGET(m, M_DONTWAIT, MT_DATA);
827: if (m == NULL) {
828: error = ENOBUFS;
829: break;
830: }
831: mlen = MLEN;
832: if (uio->uio_resid >= MINCLSIZE) {
833: MCLGET(m, M_DONTWAIT);
834: if (!(m->m_flags & M_EXT)) {
835: error = ENOBUFS;
836: m_free(m);
837: break;
838: }
839: mlen = MCLBYTES;
840: }
841: }
842: }
843: if (error) {
844: if (top != NULL)
845: m_freem(top);
846: ifp->if_ierrors++;
847: return (error);
848: }
849:
850: top->m_pkthdr.len = tlen;
851: top->m_pkthdr.rcvif = ifp;
852:
853: #if NBPFILTER > 0
854: if (ifp->if_bpf)
855: bpf_mtap(ifp->if_bpf, top, BPF_DIRECTION_IN);
856: #endif
857:
858: if (tp->tun_flags & TUN_LAYER2) {
859: ether_input_mbuf(ifp, top);
860: ifp->if_ipackets++; /* ibytes are counted in ether_input */
861: return (0);
862: }
863:
864: th = mtod(top, u_int32_t *);
865: /* strip the tunnel header */
866: top->m_data += sizeof(*th);
867: top->m_len -= sizeof(*th);
868: top->m_pkthdr.len -= sizeof(*th);
869:
870: switch (ntohl(*th)) {
871: #ifdef INET
872: case AF_INET:
873: ifq = &ipintrq;
874: isr = NETISR_IP;
875: break;
876: #endif
877: #ifdef INET6
878: case AF_INET6:
879: ifq = &ip6intrq;
880: isr = NETISR_IPV6;
881: break;
882: #endif
883: #ifdef NETATALK
884: case AF_APPLETALK:
885: ifq = &atintrq2;
886: isr = NETISR_ATALK;
887: break;
888: #endif
889: default:
890: m_freem(top);
891: return (EAFNOSUPPORT);
892: }
893:
894: s = splnet();
895: if (IF_QFULL(ifq)) {
896: IF_DROP(ifq);
897: splx(s);
898: ifp->if_collisions++;
899: m_freem(top);
900: if (!ifq->ifq_congestion)
901: if_congestion(ifq);
902: return (ENOBUFS);
903: }
904: IF_ENQUEUE(ifq, top);
905: schednetisr(isr);
906: ifp->if_ipackets++;
907: ifp->if_ibytes += top->m_pkthdr.len;
908: splx(s);
909: return (error);
910: }
911:
912: /*
913: * tunpoll - the poll interface, this is only useful on reads
914: * really. The write detect always returns true, write never blocks
915: * anyway, it either accepts the packet or drops it.
916: */
917: int
918: tunpoll(dev_t dev, int events, struct proc *p)
919: {
920: int revents, s;
921: struct tun_softc *tp;
922: struct ifnet *ifp;
923: struct mbuf *m;
924:
925: if ((tp = tun_lookup(minor(dev))) == NULL)
926: return (POLLERR);
927:
928: ifp = &tp->tun_if;
929: revents = 0;
930: s = splnet();
931: TUNDEBUG(("%s: tunpoll\n", ifp->if_xname));
932:
933: if (events & (POLLIN | POLLRDNORM)) {
934: IFQ_POLL(&ifp->if_snd, m);
935: if (m != NULL) {
936: TUNDEBUG(("%s: tunselect q=%d\n", ifp->if_xname,
937: ifp->if_snd.ifq_len));
938: revents |= events & (POLLIN | POLLRDNORM);
939: } else {
940: TUNDEBUG(("%s: tunpoll waiting\n", ifp->if_xname));
941: selrecord(p, &tp->tun_rsel);
942: }
943: }
944: if (events & (POLLOUT | POLLWRNORM))
945: revents |= events & (POLLOUT | POLLWRNORM);
946: splx(s);
947: return (revents);
948: }
949:
950: /*
951: * kqueue(2) support.
952: *
953: * The tun driver uses an array of tun_softc's based on the minor number
954: * of the device. kn->kn_hook gets set to the specific tun_softc.
955: *
956: * filt_tunread() sets kn->kn_data to the iface qsize
957: * filt_tunwrite() sets kn->kn_data to the MTU size
958: */
959: int
960: tunkqfilter(dev_t dev, struct knote *kn)
961: {
962: int s;
963: struct klist *klist;
964: struct tun_softc *tp;
965: struct ifnet *ifp;
966:
967: if ((tp = tun_lookup(minor(dev))) == NULL)
968: return (ENXIO);
969:
970: ifp = &tp->tun_if;
971:
972: s = splnet();
973: TUNDEBUG(("%s: tunkqfilter\n", ifp->if_xname));
974: splx(s);
975:
976: switch (kn->kn_filter) {
977: case EVFILT_READ:
978: klist = &tp->tun_rsel.si_note;
979: kn->kn_fop = &tunread_filtops;
980: break;
981: case EVFILT_WRITE:
982: klist = &tp->tun_wsel.si_note;
983: kn->kn_fop = &tunwrite_filtops;
984: break;
985: default:
986: return (EPERM); /* 1 */
987: }
988:
989: kn->kn_hook = (caddr_t)tp;
990:
991: s = splhigh();
992: SLIST_INSERT_HEAD(klist, kn, kn_selnext);
993: splx(s);
994:
995: return (0);
996: }
997:
998: void
999: filt_tunrdetach(struct knote *kn)
1000: {
1001: int s;
1002: struct tun_softc *tp;
1003:
1004: tp = (struct tun_softc *)kn->kn_hook;
1005: s = splhigh();
1006: if (!(kn->kn_status & KN_DETACHED))
1007: SLIST_REMOVE(&tp->tun_rsel.si_note, kn, knote, kn_selnext);
1008: splx(s);
1009: }
1010:
1011: int
1012: filt_tunread(struct knote *kn, long hint)
1013: {
1014: int s;
1015: struct tun_softc *tp;
1016: struct ifnet *ifp;
1017: struct mbuf *m;
1018:
1019: if (kn->kn_status & KN_DETACHED) {
1020: kn->kn_data = 0;
1021: return (1);
1022: }
1023:
1024: tp = (struct tun_softc *)kn->kn_hook;
1025: ifp = &tp->tun_if;
1026:
1027: s = splnet();
1028: IFQ_POLL(&ifp->if_snd, m);
1029: if (m != NULL) {
1030: splx(s);
1031: kn->kn_data = ifp->if_snd.ifq_len;
1032:
1033: TUNDEBUG(("%s: tunkqread q=%d\n", ifp->if_xname,
1034: ifp->if_snd.ifq_len));
1035: return (1);
1036: }
1037: splx(s);
1038: TUNDEBUG(("%s: tunkqread waiting\n", ifp->if_xname));
1039: return (0);
1040: }
1041:
1042: void
1043: filt_tunwdetach(struct knote *kn)
1044: {
1045: int s;
1046: struct tun_softc *tp;
1047:
1048: tp = (struct tun_softc *)kn->kn_hook;
1049: s = splhigh();
1050: if (!(kn->kn_status & KN_DETACHED))
1051: SLIST_REMOVE(&tp->tun_wsel.si_note, kn, knote, kn_selnext);
1052: splx(s);
1053: }
1054:
1055: int
1056: filt_tunwrite(struct knote *kn, long hint)
1057: {
1058: struct tun_softc *tp;
1059: struct ifnet *ifp;
1060:
1061: if (kn->kn_status & KN_DETACHED) {
1062: kn->kn_data = 0;
1063: return (1);
1064: }
1065:
1066: tp = (struct tun_softc *)kn->kn_hook;
1067: ifp = &tp->tun_if;
1068:
1069: kn->kn_data = ifp->if_mtu;
1070:
1071: return (1);
1072: }
1073:
1074: /*
1075: * Start packet transmission on the interface.
1076: * when the interface queue is rate-limited by ALTQ or TBR,
1077: * if_start is needed to drain packets from the queue in order
1078: * to notify readers when outgoing packets become ready.
1079: * In layer 2 mode this function is called from ether_output.
1080: */
1081: static void
1082: tunstart(struct ifnet *ifp)
1083: {
1084: struct tun_softc *tp = ifp->if_softc;
1085: struct mbuf *m;
1086:
1087: if (!(tp->tun_flags & TUN_LAYER2) &&
1088: !ALTQ_IS_ENABLED(&ifp->if_snd) &&
1089: !TBR_IS_ENABLED(&ifp->if_snd))
1090: return;
1091:
1092: IFQ_POLL(&ifp->if_snd, m);
1093: if (m != NULL) {
1094: if (tp->tun_flags & TUN_LAYER2) {
1095: #if NBPFILTER > 0
1096: if (ifp->if_bpf)
1097: bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
1098: #endif
1099: ifp->if_opackets++;
1100: }
1101: tun_wakeup(tp);
1102: }
1103: }
CVSweb