Annotation of src/sys/net/if_tun.c, Revision 1.100
1.100 ! pooka 1: /* $NetBSD: if_tun.c,v 1.99 2007/10/19 12:16:45 ad Exp $ */
1.14 cgd 2:
1.1 cgd 3: /*
1.8 deraadt 4: * Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk>
5: * Nottingham University 1987.
1.1 cgd 6: *
7: * This source may be freely distributed, however I would be interested
8: * in any changes that are made.
1.6 deraadt 9: *
1.1 cgd 10: * This driver takes packets off the IP i/f and hands them up to a
1.21 scottr 11: * user process to have its wicked way with. This driver has its
1.1 cgd 12: * roots in a similar driver written by Phil Cockcroft (formerly) at
1.27 mycroft 13: * UCL. This driver is based much more on read/write/poll mode of
1.1 cgd 14: * operation though.
15: */
1.48 lukem 16:
17: #include <sys/cdefs.h>
1.100 ! pooka 18: __KERNEL_RCSID(0, "$NetBSD: if_tun.c,v 1.99 2007/10/19 12:16:45 ad Exp $");
1.33 jonathan 19:
20: #include "opt_inet.h"
1.8 deraadt 21:
1.6 deraadt 22: #include <sys/param.h>
1.8 deraadt 23: #include <sys/proc.h>
1.6 deraadt 24: #include <sys/systm.h>
25: #include <sys/mbuf.h>
26: #include <sys/buf.h>
27: #include <sys/protosw.h>
28: #include <sys/socket.h>
29: #include <sys/ioctl.h>
30: #include <sys/errno.h>
31: #include <sys/syslog.h>
32: #include <sys/select.h>
1.27 mycroft 33: #include <sys/poll.h>
1.8 deraadt 34: #include <sys/file.h>
1.22 christos 35: #include <sys/signalvar.h>
1.23 christos 36: #include <sys/conf.h>
1.89 elad 37: #include <sys/kauth.h>
1.9 deraadt 38:
1.99 ad 39: #include <sys/cpu.h>
1.6 deraadt 40:
41: #include <net/if.h>
1.69 tron 42: #include <net/if_types.h>
1.6 deraadt 43: #include <net/netisr.h>
44: #include <net/route.h>
1.1 cgd 45:
1.30 is 46:
1.1 cgd 47: #ifdef INET
1.6 deraadt 48: #include <netinet/in.h>
49: #include <netinet/in_systm.h>
50: #include <netinet/in_var.h>
51: #include <netinet/ip.h>
1.30 is 52: #include <netinet/if_inarp.h>
1.1 cgd 53: #endif
54:
55:
1.8 deraadt 56: #include "bpfilter.h"
57: #if NBPFILTER > 0
58: #include <sys/time.h>
59: #include <net/bpf.h>
60: #endif
61:
62: #include <net/if_tun.h>
63:
1.29 christos 64: #define TUNDEBUG if (tundebug) printf
1.6 deraadt 65: int tundebug = 0;
1.1 cgd 66:
1.6 deraadt 67: extern int ifqmaxlen;
1.78 thorpej 68: void tunattach(int);
69:
70: static LIST_HEAD(, tun_softc) tun_softc_list;
71: static LIST_HEAD(, tun_softc) tunz_softc_list;
1.46 atatat 72: static struct simplelock tun_softc_lock;
1.6 deraadt 73:
1.97 christos 74: static int tun_ioctl(struct ifnet *, u_long, void *);
1.96 dyoung 75: static int tun_output(struct ifnet *, struct mbuf *,
76: const struct sockaddr *, struct rtentry *rt);
1.78 thorpej 77: static int tun_clone_create(struct if_clone *, int);
78: static int tun_clone_destroy(struct ifnet *);
1.6 deraadt 79:
1.78 thorpej 80: static struct if_clone tun_cloner =
1.46 atatat 81: IF_CLONE_INITIALIZER("tun", tun_clone_create, tun_clone_destroy);
82:
1.78 thorpej 83: static void tunattach0(struct tun_softc *);
84: static void tuninit(struct tun_softc *);
1.50 itojun 85: #ifdef ALTQ
1.78 thorpej 86: static void tunstart(struct ifnet *);
1.50 itojun 87: #endif
1.78 thorpej 88: static struct tun_softc *tun_find_unit(dev_t);
89: static struct tun_softc *tun_find_zunit(int);
1.53 gehenna 90:
1.78 thorpej 91: static dev_type_open(tunopen);
92: static dev_type_close(tunclose);
93: static dev_type_read(tunread);
94: static dev_type_write(tunwrite);
95: static dev_type_ioctl(tunioctl);
96: static dev_type_poll(tunpoll);
97: static dev_type_kqfilter(tunkqfilter);
1.53 gehenna 98:
99: const struct cdevsw tun_cdevsw = {
100: tunopen, tunclose, tunread, tunwrite, tunioctl,
1.91 christos 101: nostop, notty, tunpoll, nommap, tunkqfilter, D_OTHER,
1.53 gehenna 102: };
1.6 deraadt 103:
1.8 deraadt 104: void
1.94 christos 105: tunattach(int unused)
1.8 deraadt 106: {
1.46 atatat 107:
108: simple_lock_init(&tun_softc_lock);
109: LIST_INIT(&tun_softc_list);
1.70 pk 110: LIST_INIT(&tunz_softc_list);
1.46 atatat 111: if_clone_attach(&tun_cloner);
112: }
113:
1.70 pk 114: /*
115: * Find driver instance from dev_t.
116: * Call at splnet().
117: * Returns with tp locked (if found).
118: */
119: static struct tun_softc *
1.78 thorpej 120: tun_find_unit(dev_t dev)
1.70 pk 121: {
122: struct tun_softc *tp;
123: int unit = minor(dev);
124:
125: simple_lock(&tun_softc_lock);
126: LIST_FOREACH(tp, &tun_softc_list, tun_list)
127: if (unit == tp->tun_unit)
128: break;
129: if (tp)
130: simple_lock(&tp->tun_lock);
131: simple_unlock(&tun_softc_lock);
132:
133: return (tp);
134: }
135:
136: /*
137: * Find zombie driver instance by unit number.
138: * Call at splnet().
139: * Remove tp from list and return it unlocked (if found).
140: */
141: static struct tun_softc *
1.78 thorpej 142: tun_find_zunit(int unit)
1.70 pk 143: {
144: struct tun_softc *tp;
145:
146: simple_lock(&tun_softc_lock);
147: LIST_FOREACH(tp, &tunz_softc_list, tun_list)
148: if (unit == tp->tun_unit)
149: break;
150: if (tp)
151: LIST_REMOVE(tp, tun_list);
152: simple_unlock(&tun_softc_lock);
153: #ifdef DIAGNOSTIC
154: if (tp != NULL && (tp->tun_flags & (TUN_INITED|TUN_OPEN)) != TUN_OPEN)
155: printf("tun%d: inconsistent flags: %x\n", unit, tp->tun_flags);
156: #endif
157:
158: return (tp);
159: }
160:
1.78 thorpej 161: static int
162: tun_clone_create(struct if_clone *ifc, int unit)
1.46 atatat 163: {
1.70 pk 164: struct tun_softc *tp;
1.46 atatat 165:
1.70 pk 166: if ((tp = tun_find_zunit(unit)) == NULL) {
167: /* Allocate a new instance */
168: tp = malloc(sizeof(struct tun_softc), M_DEVBUF, M_WAITOK);
169: (void)memset(tp, 0, sizeof(struct tun_softc));
1.46 atatat 170:
1.70 pk 171: tp->tun_unit = unit;
172: simple_lock_init(&tp->tun_lock);
173: } else {
174: /* Revive tunnel instance; clear ifp part */
175: (void)memset(&tp->tun_if, 0, sizeof(struct ifnet));
176: }
1.46 atatat 177:
1.70 pk 178: (void)snprintf(tp->tun_if.if_xname, sizeof(tp->tun_if.if_xname),
179: "%s%d", ifc->ifc_name, unit);
180: tunattach0(tp);
181: tp->tun_flags |= TUN_INITED;
1.46 atatat 182:
183: simple_lock(&tun_softc_lock);
1.70 pk 184: LIST_INSERT_HEAD(&tun_softc_list, tp, tun_list);
1.46 atatat 185: simple_unlock(&tun_softc_lock);
186:
187: return (0);
188: }
189:
1.78 thorpej 190: static void
191: tunattach0(struct tun_softc *tp)
1.46 atatat 192: {
1.70 pk 193: struct ifnet *ifp;
1.46 atatat 194:
1.70 pk 195: ifp = &tp->tun_if;
196: ifp->if_softc = tp;
1.46 atatat 197: ifp->if_mtu = TUNMTU;
198: ifp->if_ioctl = tun_ioctl;
199: ifp->if_output = tun_output;
1.50 itojun 200: #ifdef ALTQ
201: ifp->if_start = tunstart;
202: #endif
1.46 atatat 203: ifp->if_flags = IFF_POINTOPOINT;
1.69 tron 204: ifp->if_type = IFT_TUNNEL;
1.46 atatat 205: ifp->if_snd.ifq_maxlen = ifqmaxlen;
206: ifp->if_collisions = 0;
207: ifp->if_ierrors = 0;
208: ifp->if_oerrors = 0;
209: ifp->if_ipackets = 0;
210: ifp->if_opackets = 0;
1.58 jdolecek 211: ifp->if_ibytes = 0;
212: ifp->if_obytes = 0;
1.46 atatat 213: ifp->if_dlt = DLT_NULL;
1.50 itojun 214: IFQ_SET_READY(&ifp->if_snd);
1.46 atatat 215: if_attach(ifp);
216: if_alloc_sadl(ifp);
217: #if NBPFILTER > 0
218: bpfattach(ifp, DLT_NULL, sizeof(u_int32_t));
219: #endif
220: }
221:
1.78 thorpej 222: static int
223: tun_clone_destroy(struct ifnet *ifp)
1.46 atatat 224: {
225: struct tun_softc *tp = (void *)ifp;
1.70 pk 226: int s, zombie = 0;
1.8 deraadt 227:
1.70 pk 228: s = splnet();
1.46 atatat 229: simple_lock(&tun_softc_lock);
230: simple_lock(&tp->tun_lock);
231: LIST_REMOVE(tp, tun_list);
1.70 pk 232: if (tp->tun_flags & TUN_OPEN) {
233: /* Hang on to storage until last close */
234: zombie = 1;
235: tp->tun_flags &= ~TUN_INITED;
236: LIST_INSERT_HEAD(&tunz_softc_list, tp, tun_list);
237: }
1.46 atatat 238: simple_unlock(&tun_softc_lock);
239:
1.70 pk 240: IF_PURGE(&ifp->if_snd);
241: ifp->if_flags &= ~IFF_RUNNING;
242:
1.46 atatat 243: if (tp->tun_flags & TUN_RWAIT) {
244: tp->tun_flags &= ~TUN_RWAIT;
1.97 christos 245: wakeup((void *)tp);
1.46 atatat 246: }
1.64 jdolecek 247: if (tp->tun_flags & TUN_ASYNC && tp->tun_pgid)
1.66 christos 248: fownsignal(tp->tun_pgid, SIGIO, POLL_HUP, 0, NULL);
1.64 jdolecek 249:
1.46 atatat 250: selwakeup(&tp->tun_rsel);
1.8 deraadt 251:
1.70 pk 252: simple_unlock(&tp->tun_lock);
253: splx(s);
254:
1.8 deraadt 255: #if NBPFILTER > 0
1.46 atatat 256: bpfdetach(ifp);
1.8 deraadt 257: #endif
1.46 atatat 258: if_detach(ifp);
259:
1.70 pk 260: if (!zombie)
261: free(tp, M_DEVBUF);
1.73 peter 262:
263: return (0);
1.8 deraadt 264: }
265:
1.6 deraadt 266: /*
267: * tunnel open - must be superuser & the device must be
268: * configured in
269: */
1.78 thorpej 270: static int
1.94 christos 271: tunopen(dev_t dev, int flag, int mode, struct lwp *l)
1.6 deraadt 272: {
273: struct ifnet *ifp;
1.8 deraadt 274: struct tun_softc *tp;
1.70 pk 275: int s, error;
1.1 cgd 276:
1.90 ad 277: if ((error = kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER,
1.95 elad 278: NULL)) != 0)
1.5 deraadt 279: return (error);
280:
1.70 pk 281: s = splnet();
1.46 atatat 282: tp = tun_find_unit(dev);
1.52 atatat 283:
1.70 pk 284: if (tp == NULL) {
1.52 atatat 285: (void)tun_clone_create(&tun_cloner, minor(dev));
286: tp = tun_find_unit(dev);
1.70 pk 287: if (tp == NULL) {
288: error = ENXIO;
289: goto out_nolock;
290: }
1.52 atatat 291: }
1.46 atatat 292:
293: if (tp->tun_flags & TUN_OPEN) {
1.70 pk 294: error = EBUSY;
295: goto out;
1.46 atatat 296: }
297:
1.6 deraadt 298: ifp = &tp->tun_if;
299: tp->tun_flags |= TUN_OPEN;
1.24 thorpej 300: TUNDEBUG("%s: open\n", ifp->if_xname);
1.70 pk 301: out:
1.46 atatat 302: simple_unlock(&tp->tun_lock);
1.70 pk 303: out_nolock:
304: splx(s);
305: return (error);
1.1 cgd 306: }
307:
1.6 deraadt 308: /*
309: * tunclose - close the device - mark i/f down & delete
310: * routing info
311: */
312: int
1.94 christos 313: tunclose(dev_t dev, int flag, int mode,
314: struct lwp *l)
1.6 deraadt 315: {
1.46 atatat 316: int s;
317: struct tun_softc *tp;
318: struct ifnet *ifp;
1.6 deraadt 319:
1.70 pk 320: s = splnet();
321: if ((tp = tun_find_zunit(minor(dev))) != NULL) {
322: /* interface was "destroyed" before the close */
323: free(tp, M_DEVBUF);
324: goto out_nolock;
325: }
1.46 atatat 326:
1.70 pk 327: if ((tp = tun_find_unit(dev)) == NULL)
328: goto out_nolock;
1.46 atatat 329:
330: ifp = &tp->tun_if;
331:
1.10 andrew 332: tp->tun_flags &= ~TUN_OPEN;
1.6 deraadt 333:
334: /*
335: * junk all pending output
336: */
1.50 itojun 337: IFQ_PURGE(&ifp->if_snd);
1.6 deraadt 338:
339: if (ifp->if_flags & IFF_UP) {
340: if_down(ifp);
1.8 deraadt 341: if (ifp->if_flags & IFF_RUNNING) {
1.17 mycroft 342: /* find internet addresses and delete routes */
1.39 augustss 343: struct ifaddr *ifa;
1.76 matt 344: IFADDR_FOREACH(ifa, ifp) {
1.80 rpaulo 345: #if defined(INET) || defined(INET6)
346: if (ifa->ifa_addr->sa_family == AF_INET ||
347: ifa->ifa_addr->sa_family == AF_INET6) {
1.18 mycroft 348: rtinit(ifa, (int)RTM_DELETE,
1.26 pk 349: tp->tun_flags & TUN_DSTADDR
350: ? RTF_HOST
351: : 0);
1.18 mycroft 352: }
1.38 itojun 353: #endif
1.11 deraadt 354: }
1.8 deraadt 355: }
1.6 deraadt 356: }
1.64 jdolecek 357: tp->tun_pgid = 0;
1.56 jdolecek 358: selnotify(&tp->tun_rsel, 0);
1.70 pk 359:
1.24 thorpej 360: TUNDEBUG ("%s: closed\n", ifp->if_xname);
1.46 atatat 361: simple_unlock(&tp->tun_lock);
1.70 pk 362: out_nolock:
363: splx(s);
1.6 deraadt 364: return (0);
1.1 cgd 365: }
366:
1.70 pk 367: /*
368: * Call at splnet() with tp locked.
369: */
1.26 pk 370: static void
1.78 thorpej 371: tuninit(struct tun_softc *tp)
1.6 deraadt 372: {
373: struct ifnet *ifp = &tp->tun_if;
1.46 atatat 374: struct ifaddr *ifa;
1.8 deraadt 375:
1.24 thorpej 376: TUNDEBUG("%s: tuninit\n", ifp->if_xname);
1.6 deraadt 377:
378: ifp->if_flags |= IFF_UP | IFF_RUNNING;
1.8 deraadt 379:
1.26 pk 380: tp->tun_flags &= ~(TUN_IASET|TUN_DSTADDR);
1.76 matt 381: IFADDR_FOREACH(ifa, ifp) {
1.38 itojun 382: #ifdef INET
1.11 deraadt 383: if (ifa->ifa_addr->sa_family == AF_INET) {
1.17 mycroft 384: struct sockaddr_in *sin;
1.11 deraadt 385:
1.17 mycroft 386: sin = satosin(ifa->ifa_addr);
387: if (sin && sin->sin_addr.s_addr)
388: tp->tun_flags |= TUN_IASET;
389:
1.26 pk 390: if (ifp->if_flags & IFF_POINTOPOINT) {
391: sin = satosin(ifa->ifa_dstaddr);
392: if (sin && sin->sin_addr.s_addr)
393: tp->tun_flags |= TUN_DSTADDR;
394: }
1.11 deraadt 395: }
1.38 itojun 396: #endif
1.80 rpaulo 397: #ifdef INET6
398: if (ifa->ifa_addr->sa_family == AF_INET6) {
399: struct sockaddr_in6 *sin;
400:
401: sin = (struct sockaddr_in6 *)ifa->ifa_addr;
402: if (!IN6_IS_ADDR_UNSPECIFIED(&sin->sin6_addr))
403: tp->tun_flags |= TUN_IASET;
404:
405: if (ifp->if_flags & IFF_POINTOPOINT) {
406: sin = (struct sockaddr_in6 *)ifa->ifa_dstaddr;
407: if (sin &&
408: !IN6_IS_ADDR_UNSPECIFIED(&sin->sin6_addr))
409: tp->tun_flags |= TUN_DSTADDR;
410: } else
411: tp->tun_flags &= ~TUN_DSTADDR;
412: }
413: #endif /* INET6 */
1.18 mycroft 414: }
1.8 deraadt 415:
1.26 pk 416: return;
1.1 cgd 417: }
418:
419: /*
420: * Process an ioctl request.
421: */
1.78 thorpej 422: static int
1.97 christos 423: tun_ioctl(struct ifnet *ifp, u_long cmd, void *data)
1.6 deraadt 424: {
425: int error = 0, s;
1.46 atatat 426: struct tun_softc *tp = (struct tun_softc *)(ifp->if_softc);
427:
1.70 pk 428: s = splnet();
1.46 atatat 429: simple_lock(&tp->tun_lock);
1.6 deraadt 430:
1.61 itojun 431: switch (cmd) {
1.6 deraadt 432: case SIOCSIFADDR:
1.70 pk 433: tuninit(tp);
1.24 thorpej 434: TUNDEBUG("%s: address set\n", ifp->if_xname);
1.6 deraadt 435: break;
436: case SIOCSIFDSTADDR:
1.70 pk 437: tuninit(tp);
1.24 thorpej 438: TUNDEBUG("%s: destination address set\n", ifp->if_xname);
1.6 deraadt 439: break;
1.26 pk 440: case SIOCSIFBRDADDR:
441: TUNDEBUG("%s: broadcast address set\n", ifp->if_xname);
442: break;
1.31 matt 443: case SIOCSIFMTU: {
444: struct ifreq *ifr = (struct ifreq *) data;
445: if (ifr->ifr_mtu > TUNMTU || ifr->ifr_mtu < 576) {
446: error = EINVAL;
447: break;
448: }
449: TUNDEBUG("%s: interface mtu set\n", ifp->if_xname);
450: ifp->if_mtu = ifr->ifr_mtu;
1.32 matt 451: break;
452: }
453: case SIOCADDMULTI:
454: case SIOCDELMULTI: {
455: struct ifreq *ifr = (struct ifreq *) data;
456: if (ifr == 0) {
457: error = EAFNOSUPPORT; /* XXX */
458: break;
459: }
1.98 dyoung 460: switch (ifreq_getaddr(cmd, ifr)->sa_family) {
1.32 matt 461: #ifdef INET
462: case AF_INET:
463: break;
464: #endif
1.80 rpaulo 465: #ifdef INET6
466: case AF_INET6:
467: break;
468: #endif
1.32 matt 469: default:
470: error = EAFNOSUPPORT;
471: break;
472: }
1.31 matt 473: break;
474: }
1.38 itojun 475: case SIOCSIFFLAGS:
476: break;
1.6 deraadt 477: default:
478: error = EINVAL;
479: }
1.70 pk 480:
481: simple_unlock(&tp->tun_lock);
1.6 deraadt 482: splx(s);
483: return (error);
1.1 cgd 484: }
485:
486: /*
1.22 christos 487: * tun_output - queue packets from higher level ready to put out.
1.1 cgd 488: */
1.78 thorpej 489: static int
1.96 dyoung 490: tun_output(struct ifnet *ifp, struct mbuf *m0, const struct sockaddr *dst,
1.94 christos 491: struct rtentry *rt)
1.6 deraadt 492: {
1.24 thorpej 493: struct tun_softc *tp = ifp->if_softc;
1.6 deraadt 494: int s;
1.51 itojun 495: int error;
1.80 rpaulo 496: #if defined(INET) || defined(INET6)
1.75 christos 497: int mlen;
1.80 rpaulo 498: uint32_t *af;
1.38 itojun 499: #endif
1.50 itojun 500: ALTQ_DECL(struct altq_pktattr pktattr;)
1.6 deraadt 501:
1.70 pk 502: s = splnet();
1.46 atatat 503: simple_lock(&tp->tun_lock);
1.24 thorpej 504: TUNDEBUG ("%s: tun_output\n", ifp->if_xname);
1.1 cgd 505:
1.8 deraadt 506: if ((tp->tun_flags & TUN_READY) != TUN_READY) {
1.24 thorpej 507: TUNDEBUG ("%s: not ready 0%o\n", ifp->if_xname,
508: tp->tun_flags);
1.8 deraadt 509: m_freem (m0);
1.70 pk 510: error = EHOSTDOWN;
511: goto out;
1.8 deraadt 512: }
513:
1.50 itojun 514: /*
515: * if the queueing discipline needs packet classification,
516: * do it before prepending link headers.
517: */
518: IFQ_CLASSIFY(&ifp->if_snd, m0, dst->sa_family, &pktattr);
1.70 pk 519:
1.8 deraadt 520: #if NBPFILTER > 0
1.72 christos 521: if (ifp->if_bpf)
522: bpf_mtap_af(ifp->if_bpf, dst->sa_family, m0);
1.8 deraadt 523: #endif
524:
1.6 deraadt 525: switch(dst->sa_family) {
1.79 rpaulo 526: #ifdef INET6
527: case AF_INET6:
528: #endif
1.1 cgd 529: #ifdef INET
1.6 deraadt 530: case AF_INET:
1.79 rpaulo 531: #endif
532: #if defined(INET) || defined(INET6)
1.26 pk 533: if (tp->tun_flags & TUN_PREPADDR) {
534: /* Simple link-layer header */
535: M_PREPEND(m0, dst->sa_len, M_DONTWAIT);
536: if (m0 == NULL) {
537: IF_DROP(&ifp->if_snd);
1.70 pk 538: error = ENOBUFS;
539: goto out;
1.26 pk 540: }
541: bcopy(dst, mtod(m0, char *), dst->sa_len);
1.85 rpaulo 542: }
543:
544: if (tp->tun_flags & TUN_IFHEAD) {
1.81 rpaulo 545: /* Prepend the address family */
1.82 rpaulo 546: M_PREPEND(m0, sizeof(*af), M_DONTWAIT);
1.80 rpaulo 547: if (m0 == NULL) {
548: IF_DROP(&ifp->if_snd);
549: error = ENOBUFS;
550: goto out;
551: }
552: af = mtod(m0,uint32_t *);
553: *af = htonl(dst->sa_family);
1.86 rpaulo 554: } else {
555: #ifdef INET
556: if (dst->sa_family != AF_INET)
557: #endif
558: {
559: m_freem(m0);
560: error = EAFNOSUPPORT;
561: goto out;
562: }
1.26 pk 563: }
1.36 sommerfe 564: /* FALLTHROUGH */
565: case AF_UNSPEC:
1.50 itojun 566: IFQ_ENQUEUE(&ifp->if_snd, m0, &pktattr, error);
567: if (error) {
1.6 deraadt 568: ifp->if_collisions++;
1.70 pk 569: error = EAFNOSUPPORT;
570: goto out;
1.6 deraadt 571: }
1.58 jdolecek 572: mlen = m0->m_pkthdr.len;
1.6 deraadt 573: ifp->if_opackets++;
1.58 jdolecek 574: ifp->if_obytes += mlen;
1.6 deraadt 575: break;
1.1 cgd 576: #endif
1.6 deraadt 577: default:
578: m_freem(m0);
1.70 pk 579: error = EAFNOSUPPORT;
580: goto out;
1.6 deraadt 581: }
582:
583: if (tp->tun_flags & TUN_RWAIT) {
584: tp->tun_flags &= ~TUN_RWAIT;
1.97 christos 585: wakeup((void *)tp);
1.6 deraadt 586: }
1.64 jdolecek 587: if (tp->tun_flags & TUN_ASYNC && tp->tun_pgid)
1.66 christos 588: fownsignal(tp->tun_pgid, SIGIO, POLL_IN, POLLIN|POLLRDNORM,
589: NULL);
1.64 jdolecek 590:
1.56 jdolecek 591: selnotify(&tp->tun_rsel, 0);
1.70 pk 592: out:
1.46 atatat 593: simple_unlock(&tp->tun_lock);
1.70 pk 594: splx(s);
1.26 pk 595: return (0);
1.1 cgd 596: }
597:
598: /*
599: * the cdevsw interface is now pretty minimal.
600: */
1.6 deraadt 601: int
1.97 christos 602: tunioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
1.6 deraadt 603: {
1.46 atatat 604: struct tun_softc *tp;
1.70 pk 605: int s, error = 0;
1.46 atatat 606:
1.70 pk 607: s = splnet();
1.46 atatat 608: tp = tun_find_unit(dev);
609:
610: /* interface was "destroyed" already */
1.70 pk 611: if (tp == NULL) {
612: error = ENXIO;
613: goto out_nolock;
614: }
1.6 deraadt 615:
616: switch (cmd) {
617: case TUNSDEBUG:
618: tundebug = *(int *)data;
619: break;
1.26 pk 620:
1.6 deraadt 621: case TUNGDEBUG:
622: *(int *)data = tundebug;
623: break;
1.26 pk 624:
625: case TUNSIFMODE:
1.31 matt 626: switch (*(int *)data & (IFF_POINTOPOINT|IFF_BROADCAST)) {
1.26 pk 627: case IFF_POINTOPOINT:
628: case IFF_BROADCAST:
629: if (tp->tun_if.if_flags & IFF_UP) {
1.70 pk 630: error = EBUSY;
631: goto out;
1.26 pk 632: }
633: tp->tun_if.if_flags &=
1.31 matt 634: ~(IFF_BROADCAST|IFF_POINTOPOINT|IFF_MULTICAST);
1.26 pk 635: tp->tun_if.if_flags |= *(int *)data;
636: break;
637: default:
1.70 pk 638: error = EINVAL;
639: goto out;
1.26 pk 640: }
641: break;
642:
643: case TUNSLMODE:
1.87 rpaulo 644: if (*(int *)data) {
1.26 pk 645: tp->tun_flags |= TUN_PREPADDR;
1.87 rpaulo 646: tp->tun_flags &= ~TUN_IFHEAD;
647: } else
1.26 pk 648: tp->tun_flags &= ~TUN_PREPADDR;
649: break;
650:
1.84 rpaulo 651: case TUNSIFHEAD:
1.87 rpaulo 652: if (*(int *)data) {
1.84 rpaulo 653: tp->tun_flags |= TUN_IFHEAD;
1.88 rpaulo 654: tp->tun_flags &= ~TUN_PREPADDR;
1.87 rpaulo 655: } else
1.84 rpaulo 656: tp->tun_flags &= ~TUN_IFHEAD;
657: break;
658:
659: case TUNGIFHEAD:
660: *(int *)data = (tp->tun_flags & TUN_IFHEAD);
661: break;
662:
1.6 deraadt 663: case FIONBIO:
664: if (*(int *)data)
665: tp->tun_flags |= TUN_NBIO;
666: else
667: tp->tun_flags &= ~TUN_NBIO;
668: break;
1.26 pk 669:
1.6 deraadt 670: case FIOASYNC:
671: if (*(int *)data)
672: tp->tun_flags |= TUN_ASYNC;
673: else
674: tp->tun_flags &= ~TUN_ASYNC;
675: break;
1.26 pk 676:
1.6 deraadt 677: case FIONREAD:
678: if (tp->tun_if.if_snd.ifq_head)
1.19 pk 679: *(int *)data = tp->tun_if.if_snd.ifq_head->m_pkthdr.len;
1.70 pk 680: else
1.6 deraadt 681: *(int *)data = 0;
682: break;
1.26 pk 683:
1.6 deraadt 684: case TIOCSPGRP:
1.64 jdolecek 685: case FIOSETOWN:
1.77 christos 686: error = fsetown(l->l_proc, &tp->tun_pgid, cmd, data);
1.6 deraadt 687: break;
1.26 pk 688:
1.6 deraadt 689: case TIOCGPGRP:
1.64 jdolecek 690: case FIOGETOWN:
1.77 christos 691: error = fgetown(l->l_proc, tp->tun_pgid, cmd, data);
1.6 deraadt 692: break;
1.26 pk 693:
1.6 deraadt 694: default:
1.70 pk 695: error = ENOTTY;
1.6 deraadt 696: }
1.70 pk 697:
698: out:
1.46 atatat 699: simple_unlock(&tp->tun_lock);
1.70 pk 700: out_nolock:
701: splx(s);
1.64 jdolecek 702: return (error);
1.1 cgd 703: }
704:
705: /*
1.6 deraadt 706: * The cdevsw read interface - reads a packet at a time, or at
707: * least as much of a packet as can be read.
1.1 cgd 708: */
1.6 deraadt 709: int
1.94 christos 710: tunread(dev_t dev, struct uio *uio, int ioflag)
1.6 deraadt 711: {
1.46 atatat 712: struct tun_softc *tp;
713: struct ifnet *ifp;
1.6 deraadt 714: struct mbuf *m, *m0;
1.70 pk 715: int error = 0, len, s, index;
1.46 atatat 716:
1.70 pk 717: s = splnet();
1.46 atatat 718: tp = tun_find_unit(dev);
719:
720: /* interface was "destroyed" already */
1.70 pk 721: if (tp == NULL) {
722: error = ENXIO;
723: goto out_nolock;
724: }
1.46 atatat 725:
726: index = tp->tun_if.if_index;
727: ifp = &tp->tun_if;
1.6 deraadt 728:
1.24 thorpej 729: TUNDEBUG ("%s: read\n", ifp->if_xname);
1.8 deraadt 730: if ((tp->tun_flags & TUN_READY) != TUN_READY) {
1.26 pk 731: TUNDEBUG ("%s: not ready 0%o\n", ifp->if_xname, tp->tun_flags);
1.70 pk 732: error = EHOSTDOWN;
733: goto out;
1.8 deraadt 734: }
735:
1.6 deraadt 736: tp->tun_flags &= ~TUN_RWAIT;
737:
738: do {
1.50 itojun 739: IFQ_DEQUEUE(&ifp->if_snd, m0);
1.6 deraadt 740: if (m0 == 0) {
741: if (tp->tun_flags & TUN_NBIO) {
1.70 pk 742: error = EWOULDBLOCK;
743: goto out;
1.6 deraadt 744: }
745: tp->tun_flags |= TUN_RWAIT;
1.97 christos 746: if (ltsleep((void *)tp, PZERO|PCATCH|PNORELOCK,
1.70 pk 747: "tunread", 0, &tp->tun_lock) != 0) {
748: error = EINTR;
749: goto out_nolock;
1.46 atatat 750: } else {
751: /*
752: * Maybe the interface was destroyed while
753: * we were sleeping, so let's ensure that
754: * we're looking at the same (valid) tun
755: * interface before looping.
756: */
757: tp = tun_find_unit(dev);
1.70 pk 758: if (tp == NULL) {
759: error = ENXIO;
760: goto out_nolock;
761: }
762: if (tp->tun_if.if_index != index) {
763: error = ENXIO;
764: goto out;
1.46 atatat 765: }
1.26 pk 766: }
1.6 deraadt 767: }
768: } while (m0 == 0);
1.70 pk 769:
770: simple_unlock(&tp->tun_lock);
1.6 deraadt 771: splx(s);
772:
1.70 pk 773: /* Copy the mbuf chain */
1.6 deraadt 774: while (m0 && uio->uio_resid > 0 && error == 0) {
1.13 deraadt 775: len = min(uio->uio_resid, m0->m_len);
1.45 itojun 776: if (len != 0)
1.97 christos 777: error = uiomove(mtod(m0, void *), len, uio);
1.6 deraadt 778: MFREE(m0, m);
779: m0 = m;
780: }
781:
782: if (m0) {
783: TUNDEBUG("Dropping mbuf\n");
784: m_freem(m0);
785: }
1.19 pk 786: if (error)
787: ifp->if_ierrors++;
1.70 pk 788:
789: return (error);
790:
791: out:
1.46 atatat 792: simple_unlock(&tp->tun_lock);
1.70 pk 793: out_nolock:
794: splx(s);
1.26 pk 795: return (error);
1.1 cgd 796: }
797:
798: /*
799: * the cdevsw write interface - an atomic write is a packet - or else!
800: */
1.6 deraadt 801: int
1.94 christos 802: tunwrite(dev_t dev, struct uio *uio, int ioflag)
1.6 deraadt 803: {
1.46 atatat 804: struct tun_softc *tp;
805: struct ifnet *ifp;
1.6 deraadt 806: struct mbuf *top, **mp, *m;
1.26 pk 807: struct ifqueue *ifq;
808: struct sockaddr dst;
1.70 pk 809: int isr, error = 0, s, tlen, mlen;
1.80 rpaulo 810: uint32_t family;
1.6 deraadt 811:
1.70 pk 812: s = splnet();
1.46 atatat 813: tp = tun_find_unit(dev);
814:
815: /* interface was "destroyed" already */
1.70 pk 816: if (tp == NULL) {
817: error = ENXIO;
818: goto out_nolock;
819: }
820:
821: /* Unlock until we've got the data */
822: simple_unlock(&tp->tun_lock);
823: splx(s);
1.46 atatat 824:
825: ifp = &tp->tun_if;
826:
1.24 thorpej 827: TUNDEBUG("%s: tunwrite\n", ifp->if_xname);
1.6 deraadt 828:
1.26 pk 829: if (tp->tun_flags & TUN_PREPADDR) {
1.46 atatat 830: if (uio->uio_resid < sizeof(dst)) {
1.70 pk 831: error = EIO;
832: goto out0;
1.46 atatat 833: }
1.97 christos 834: error = uiomove((void *)&dst, sizeof(dst), uio);
1.26 pk 835: if (dst.sa_len > sizeof(dst)) {
836: /* Duh.. */
837: char discard;
838: int n = dst.sa_len - sizeof(dst);
839: while (n--)
1.46 atatat 840: if ((error = uiomove(&discard, 1, uio)) != 0) {
1.70 pk 841: goto out0;
1.46 atatat 842: }
1.26 pk 843: }
1.85 rpaulo 844: } else if (tp->tun_flags & TUN_IFHEAD) {
1.80 rpaulo 845: if (uio->uio_resid < sizeof(family)){
846: error = EIO;
847: goto out0;
848: }
1.97 christos 849: error = uiomove((void *)&family, sizeof(family), uio);
1.80 rpaulo 850: dst.sa_family = ntohl(family);
1.85 rpaulo 851: } else {
852: #ifdef INET
853: dst.sa_family = AF_INET;
854: #endif
1.26 pk 855: }
856:
1.54 simonb 857: if (uio->uio_resid > TUNMTU) {
1.37 mjacob 858: TUNDEBUG("%s: len=%lu!\n", ifp->if_xname,
859: (unsigned long)uio->uio_resid);
1.70 pk 860: error = EIO;
861: goto out0;
1.6 deraadt 862: }
1.26 pk 863:
864: switch (dst.sa_family) {
865: #ifdef INET
866: case AF_INET:
867: ifq = &ipintrq;
868: isr = NETISR_IP;
869: break;
870: #endif
1.79 rpaulo 871: #ifdef INET6
872: case AF_INET6:
873: ifq = &ip6intrq;
874: isr = NETISR_IPV6;
1.83 rpaulo 875: break;
1.79 rpaulo 876: #endif
1.26 pk 877: default:
1.70 pk 878: error = EAFNOSUPPORT;
879: goto out0;
1.26 pk 880: }
881:
1.8 deraadt 882: tlen = uio->uio_resid;
883:
884: /* get a header mbuf */
885: MGETHDR(m, M_DONTWAIT, MT_DATA);
1.46 atatat 886: if (m == NULL) {
1.70 pk 887: error = ENOBUFS;
888: goto out0;
1.46 atatat 889: }
1.8 deraadt 890: mlen = MHLEN;
891:
1.68 tron 892: top = NULL;
1.6 deraadt 893: mp = ⊤
894: while (error == 0 && uio->uio_resid > 0) {
1.13 deraadt 895: m->m_len = min(mlen, uio->uio_resid);
1.97 christos 896: error = uiomove(mtod(m, void *), m->m_len, uio);
1.6 deraadt 897: *mp = m;
898: mp = &m->m_next;
1.68 tron 899: if (error == 0 && uio->uio_resid > 0) {
900: MGET(m, M_DONTWAIT, MT_DATA);
901: if (m == NULL) {
1.8 deraadt 902: error = ENOBUFS;
903: break;
904: }
905: mlen = MLEN;
906: }
1.6 deraadt 907: }
908: if (error) {
1.68 tron 909: if (top != NULL)
1.8 deraadt 910: m_freem (top);
1.19 pk 911: ifp->if_ierrors++;
1.70 pk 912: goto out0;
1.6 deraadt 913: }
914:
1.8 deraadt 915: top->m_pkthdr.len = tlen;
916: top->m_pkthdr.rcvif = ifp;
917:
918: #if NBPFILTER > 0
1.72 christos 919: if (ifp->if_bpf)
1.80 rpaulo 920: bpf_mtap_af(ifp->if_bpf, dst.sa_family, top);
1.8 deraadt 921: #endif
1.6 deraadt 922:
1.43 thorpej 923: s = splnet();
1.70 pk 924: simple_lock(&tp->tun_lock);
925: if ((tp->tun_flags & TUN_INITED) == 0) {
926: /* Interface was destroyed */
927: error = ENXIO;
928: goto out;
929: }
1.26 pk 930: if (IF_QFULL(ifq)) {
931: IF_DROP(ifq);
1.6 deraadt 932: ifp->if_collisions++;
933: m_freem(top);
1.70 pk 934: error = ENOBUFS;
935: goto out;
1.6 deraadt 936: }
1.70 pk 937:
1.26 pk 938: IF_ENQUEUE(ifq, top);
1.6 deraadt 939: ifp->if_ipackets++;
1.58 jdolecek 940: ifp->if_ibytes += tlen;
1.26 pk 941: schednetisr(isr);
1.70 pk 942: out:
1.46 atatat 943: simple_unlock(&tp->tun_lock);
1.70 pk 944: out_nolock:
945: splx(s);
946: out0:
1.26 pk 947: return (error);
1.1 cgd 948: }
949:
1.50 itojun 950: #ifdef ALTQ
951: /*
952: * Start packet transmission on the interface.
953: * when the interface queue is rate-limited by ALTQ or TBR,
954: * if_start is needed to drain packets from the queue in order
955: * to notify readers when outgoing packets become ready.
1.70 pk 956: *
957: * Should be called at splnet.
1.50 itojun 958: */
959: static void
1.78 thorpej 960: tunstart(struct ifnet *ifp)
1.50 itojun 961: {
962: struct tun_softc *tp = ifp->if_softc;
963:
964: if (!ALTQ_IS_ENABLED(&ifp->if_snd) && !TBR_IS_ENABLED(&ifp->if_snd))
965: return;
966:
1.70 pk 967: simple_lock(&tp->tun_lock);
968: if (!IF_IS_EMPTY(&ifp->if_snd)) {
1.50 itojun 969: if (tp->tun_flags & TUN_RWAIT) {
970: tp->tun_flags &= ~TUN_RWAIT;
1.97 christos 971: wakeup((void *)tp);
1.50 itojun 972: }
1.64 jdolecek 973: if (tp->tun_flags & TUN_ASYNC && tp->tun_pgid)
1.67 cl 974: fownsignal(tp->tun_pgid, SIGIO, POLL_OUT,
975: POLLOUT|POLLWRNORM, NULL);
1.70 pk 976:
1.50 itojun 977: selwakeup(&tp->tun_rsel);
978: }
1.70 pk 979: simple_unlock(&tp->tun_lock);
1.50 itojun 980: }
981: #endif /* ALTQ */
1.1 cgd 982: /*
1.27 mycroft 983: * tunpoll - the poll interface, this is only useful on reads
1.6 deraadt 984: * really. The write detect always returns true, write never blocks
985: * anyway, it either accepts the packet or drops it.
986: */
987: int
1.78 thorpej 988: tunpoll(dev_t dev, int events, struct lwp *l)
1.6 deraadt 989: {
1.46 atatat 990: struct tun_softc *tp;
991: struct ifnet *ifp;
992: int s, revents = 0;
993:
1.70 pk 994: s = splnet();
1.46 atatat 995: tp = tun_find_unit(dev);
996:
997: /* interface was "destroyed" already */
998: if (tp == NULL)
1.70 pk 999: goto out_nolock;
1.46 atatat 1000:
1001: ifp = &tp->tun_if;
1.6 deraadt 1002:
1.27 mycroft 1003: TUNDEBUG("%s: tunpoll\n", ifp->if_xname);
1.6 deraadt 1004:
1.35 veego 1005: if (events & (POLLIN | POLLRDNORM)) {
1.70 pk 1006: if (!IFQ_IS_EMPTY(&ifp->if_snd)) {
1.27 mycroft 1007: TUNDEBUG("%s: tunpoll q=%d\n", ifp->if_xname,
1.24 thorpej 1008: ifp->if_snd.ifq_len);
1.27 mycroft 1009: revents |= events & (POLLIN | POLLRDNORM);
1010: } else {
1011: TUNDEBUG("%s: tunpoll waiting\n", ifp->if_xname);
1.77 christos 1012: selrecord(l, &tp->tun_rsel);
1.6 deraadt 1013: }
1.35 veego 1014: }
1.27 mycroft 1015:
1016: if (events & (POLLOUT | POLLWRNORM))
1017: revents |= events & (POLLOUT | POLLWRNORM);
1018:
1.70 pk 1019: simple_unlock(&tp->tun_lock);
1020: out_nolock:
1.6 deraadt 1021: splx(s);
1.27 mycroft 1022: return (revents);
1.56 jdolecek 1023: }
1024:
1025: static void
1026: filt_tunrdetach(struct knote *kn)
1027: {
1028: struct tun_softc *tp = kn->kn_hook;
1029: int s;
1030:
1031: s = splnet();
1.57 christos 1032: SLIST_REMOVE(&tp->tun_rsel.sel_klist, kn, knote, kn_selnext);
1.56 jdolecek 1033: splx(s);
1034: }
1035:
1036: static int
1.94 christos 1037: filt_tunread(struct knote *kn, long hint)
1.56 jdolecek 1038: {
1039: struct tun_softc *tp = kn->kn_hook;
1040: struct ifnet *ifp = &tp->tun_if;
1041: struct mbuf *m;
1042: int s;
1043:
1044: s = splnet();
1045: IF_POLL(&ifp->if_snd, m);
1046: if (m == NULL) {
1047: splx(s);
1048: return (0);
1049: }
1050:
1051: for (kn->kn_data = 0; m != NULL; m = m->m_next)
1052: kn->kn_data += m->m_len;
1053:
1054: splx(s);
1055: return (1);
1056: }
1057:
1058: static const struct filterops tunread_filtops =
1059: { 1, NULL, filt_tunrdetach, filt_tunread };
1060:
1061: static const struct filterops tun_seltrue_filtops =
1062: { 1, NULL, filt_tunrdetach, filt_seltrue };
1063:
1064: int
1065: tunkqfilter(dev_t dev, struct knote *kn)
1066: {
1.70 pk 1067: struct tun_softc *tp;
1.56 jdolecek 1068: struct klist *klist;
1.70 pk 1069: int rv = 0, s;
1070:
1071: s = splnet();
1072: tp = tun_find_unit(dev);
1073: if (tp == NULL)
1074: goto out_nolock;
1.56 jdolecek 1075:
1076: switch (kn->kn_filter) {
1077: case EVFILT_READ:
1.57 christos 1078: klist = &tp->tun_rsel.sel_klist;
1.56 jdolecek 1079: kn->kn_fop = &tunread_filtops;
1080: break;
1081:
1082: case EVFILT_WRITE:
1.57 christos 1083: klist = &tp->tun_rsel.sel_klist;
1.56 jdolecek 1084: kn->kn_fop = &tun_seltrue_filtops;
1085: break;
1086:
1087: default:
1.100 ! pooka 1088: rv = EINVAL;
1.70 pk 1089: goto out;
1.56 jdolecek 1090: }
1091:
1092: kn->kn_hook = tp;
1093:
1094: SLIST_INSERT_HEAD(klist, kn, kn_selnext);
1.70 pk 1095:
1096: out:
1097: simple_unlock(&tp->tun_lock);
1098: out_nolock:
1.56 jdolecek 1099: splx(s);
1.70 pk 1100: return (rv);
1.1 cgd 1101: }
CVSweb <webmaster@jp.NetBSD.org>