|
|
1.1 root 1: /* UNFINISHED CONVERSION TO 386BSD -wfj */
2:
3: /* if_tun.c - tunnel interface module & driver */
4:
5: /*
6: * Copyright (c) 1988, Julian Onions.
7: *
8: * This source may be freely distributed, however I would be interested
9: * in any changes that are made.
10: */
11:
12: /*
13: * 90/02/06 15:03 - Fixed a bug in where TIOCGPGRP and TIOCSPGRP were
14: * mixed up. Anders Klemets - [email protected]
15: *
1.1.1.3 ! root 16: * if_tun.c,v 1.3.2.1 1993/07/31 12:23:09 cgd Exp
1.1 root 17: *
1.1.1.3 ! root 18: * if_tun.c,v
! 19: * Revision 1.3.2.1 1993/07/31 12:23:09 cgd
! 20: * give names, err, wmesg's, to my "pain" -- i.e. convert sleep() to tsleep()
! 21: *
! 22: * Revision 1.3 1993/05/22 11:42:13 cgd
! 23: * add include of select.h if necessary for protos, or delete if extraneous
! 24: *
! 25: * Revision 1.2 1993/05/18 18:19:58 cgd
! 26: * make kernel select interface be one-stop shopping & clean it all up.
! 27: *
! 28: * Revision 1.1.1.1 1993/03/21 09:46:06 cgd
1.1.1.2 root 29: * initial import of 386bsd-0.1 sources
30: *
1.1 root 31: * Revision 1.13 88/07/11 08:28:51 jpo
32: * Some tidying up
33: *
34: * Revision 1.12 87/12/10 09:16:29 jpo
35: * Decided the vax/mtpr was unnecessay.
36: *
37: * Revision 1.11 87/12/10 09:10:36 jpo
38: * Fixed some minor things & 1 major bug.
39: *
40: * Revision 1.10 87/11/04 14:27:41 jpo
41: * A few sanity checks added.
42: *
43: * Revision 1.9 87/11/04 14:13:45 jpo
44: * Added some ioctls for non-blocking & async I/O
45: *
46: * Revision 1.8 87/10/19 10:28:14 jpo
47: * Another touch up (sigh)
48: *
49: * Revision 1.7 87/10/19 10:25:48 jpo
50: * Touch up.
51: *
52: * Revision 1.6 87/10/19 09:15:14 jpo
53: * Touch up.
54: *
55: * Revision 1.5 87/10/19 08:34:51 jpo
56: * General clean up - plus sun specific fixes
57: *
58: * Revision 1.4 87/10/16 17:10:12 jpo
59: * Purged all ioctl read/writes and non-standard routing stuff.
60: *
61: * Revision 1.3 87/10/05 11:57:09 jpo
62: * More debugging - in error mainly.
63: *
64: * Revision 1.2 87/10/04 18:29:45 jpo
65: * Select & read/write working.
66: */
67:
68: #include "tun.h"
69: #if NTUN > 0
70:
71: /*
72: * Tunnel driver.
73: *
74: * This driver takes packets off the IP i/f and hands them up to a
75: * user process to have it's wicked way with. This driver has it's
76: * roots in a similar driver written by Phil Cockcroft (formerly) at
77: * UCL. This driver is based much more on read/write/select mode of
78: * operation though.
79: *
80: * Julian Onions <[email protected]>
81: * Nottingham University 1987.
82: */
83:
84: #include "param.h"
85: #include "systm.h"
86: #include "mbuf.h"
87: #include "buf.h"
88: #include "protosw.h"
89: #include "socket.h"
90: #include "ioctl.h"
91: #include "errno.h"
92: #include "syslog.h"
1.1.1.3 ! root 93: #include "select.h"
1.1 root 94:
95: #include "net/if.h"
96: #include "net/netisr.h"
97: #include "net/route.h"
98:
99: #ifdef INET
100: #include "netinet/in.h"
101: #include "netinet/in_systm.h"
102: #include "netinet/in_var.h"
103: #include "netinet/ip.h"
104: #include "netinet/if_ether.h"
105: #endif
106:
107: #ifdef NS
108: #include "netns/ns.h"
109: #include "netns/ns_if.h"
110: #endif
111:
112: #define TUNDEBUG if (tundebug) printf
113:
114: int tundebug = 0;
115: struct tunctl
116: {
117: u_short tun_flags; /* misc flags */
118: struct ifnet tun_if; /* the interface */
119: int tun_pgrp; /* the process group - if any */
1.1.1.3 ! root 120: struct selinfo tun_rsel; /* read select */
! 121: struct selinfo tun_wsel; /* write select (not used) */
1.1 root 122: } tunctl[NTUN];
123:
124: extern int ifqmaxlen;
125:
126: int tunoutput (), tunioctl (), tuninit ();
127:
128: /* tunnel open - must be superuser & the device must be configured in */
129: tunopen (dev, flag)
130: dev_t dev;
131: {
132: register int unit;
133: struct tunctl *tp;
134: register struct ifnet *ifp;
135:
136: if (!suser ())
137: return EACCES;
138: if ((unit = minor (dev)) >= NTUN)
139: return (ENXIO);
140: tp = &tunctl[unit];
141: if (tp->tun_flags & TUN_OPEN)
142: return ENXIO;
143: if ((tp->tun_flags & TUN_INITED) == 0) {
144: tp->tun_flags = TUN_INITED;
145: tunattach (unit);
146: }
147: ifp = &tp->tun_if;
148: tp->tun_flags |= TUN_OPEN;
149: TUNDEBUG ("%s%d: open\n", ifp->if_name, ifp->if_unit);
150: return (0);
151: }
152:
153: /* tunclose - close the device - mark i/f down & delete routing info */
154: tunclose (dev, flag)
155: dev_t dev;
156: {
157: int s;
158: register int unit = minor (dev);
159: register struct tunctl *tp = &tunctl[unit];
160: register struct ifnet *ifp = &tp->tun_if;
161: register struct mbuf *m;
162:
163: tp->tun_flags &= TUN_INITED;
164:
165: /*
166: * junk all pending output
167: */
168: do {
169: s = splimp ();
170: IF_DEQUEUE (&ifp->if_snd, m);
171: splx (s);
172: if (m) /* actually - m_freem checks this - but what the hell */
173: m_freem (m);
174: } while (m != 0);
175: if (ifp->if_flags & IFF_UP) {
176: s = splimp ();
177: if_down (ifp);
178: if (ifp->if_flags & IFF_RUNNING)
179: rtinit (ifp->if_addrlist, (int)SIOCDELRT, RTF_HOST);
180: splx (s);
181: }
182: tp -> tun_pgrp = 0;
183: if (tp -> tun_rsel)
1.1.1.3 ! root 184: selwakeup (&tp->tun_rsel);
1.1 root 185:
186: tp -> tun_rsel = tp -> tun_wsel = (struct proc *)0;
187:
188: TUNDEBUG ("%s%d: closed\n", ifp->if_name, ifp->if_unit);
189: return (0);
190: }
191:
192: /*
193: * attach an interface N.B. argument is not same as other drivers
194: */
195: int
196: tunattach (unit)
197: int unit;
198: {
199: register struct ifnet *ifp = &tunctl[unit].tun_if;
200: register struct sockaddr_in *sin;
201:
202: ifp->if_unit = unit;
203: ifp->if_name = "tun";
204: ifp->if_mtu = TUNMTU;
205: ifp->if_ioctl = tunioctl;
206: ifp->if_output = tunoutput;
207: ifp->if_init = tuninit;
208: #ifndef BSD4_3
209: sin = (struct sockaddr_in *) & ifp->if_addr;
210: sin->sin_family = AF_INET;
211: #endif
212: ifp->if_flags = IFF_POINTOPOINT;
213: ifp->if_snd.ifq_maxlen = ifqmaxlen;
214: ifp->if_collisions = ifp->if_ierrors = ifp->if_oerrors = 0;
215: ifp->if_ipackets = ifp->if_opackets = 0;
216: if_attach (ifp);
217: TUNDEBUG ("%s%d: tunattach\n", ifp->if_name, ifp->if_unit);
218: return 0;
219: }
220:
221: int
222: tuninit (unit)
223: int unit;
224: {
225: register struct tunctl *tp = &tunctl[unit];
226: register struct ifnet *ifp = &tp->tun_if;
227: #ifndef BSD4_3
228: register struct sockaddr_in *sin;
229:
230: sin = (struct sockaddr_in *) & ifp->if_addr;
231: if (sin->sin_addr.s_addr == 0) /* if address still unknown */
232: return;
233: if_rtinit (ifp, RTF_UP);
234: #endif
235: ifp->if_flags |= IFF_UP | IFF_RUNNING;
236: tp->tun_flags |= TUN_IASET;
237: TUNDEBUG ("%s%d: tuninit\n", ifp->if_name, ifp->if_unit);
238: return 0;
239: }
240:
241: /*
242: * Process an ioctl request.
243: * The problem here is 4.2 pass a struct ifreq * to this routine,
244: * sun only passes a struct sockaddr * since 3.2 at least. This is
245: * rather upsetting! Also, sun doesn't pass the SIOCDSTADDR ioctl through
246: * so we can't detect this being set directly. This is the reason for
247: * tuncheckready.
248: * Under 4.3 and SunOs 4.0 we now get the SIOCSIFDSTADDR ioctl, and we get a
249: * struct in_ifaddr * for data. (tte)
250: */
251:
252: #if !defined(BSD4_3) && defined(sun)
253:
254: /*
255: * workaround for not being able to detect DSTADDR being set.
256: */
257:
258: tuncheckready (ifp)
259: struct ifnet *ifp;
260: {
261: struct tunctl *tp = &tunctl[ifp->if_unit];
262: struct sockaddr_in *sin;
263:
264: sin = (struct sockaddr_in *) &ifp->if_dstaddr;
265: if (sin->sin_addr.s_addr == 0)
266: return 0;
267: tp -> tun_flags |= TUN_DSTADDR;
268: return 1;
269: }
270: #else
271: #define tuncheckready(dummy) 1
272: #endif /* !defined(BSD4_3) && defined(sun) */
273:
274: int
275: tunioctl (ifp, cmd, data)
276: register struct ifnet *ifp;
277: int cmd;
278: caddr_t data;
279: {
280: #ifndef BSD4_3
281: #ifdef sun
282: struct sockaddr_in *sin = (struct sockaddr_in *) data;
283: #else
284: struct sockaddr_in *sin;
285: struct ifreq *ifr = (struct ifreq *) data;
286: #endif
287: #endif /* BSD4_3 */
288:
289: int s = splimp (), error = 0;
290: struct tunctl *tp = &tunctl[ifp->if_unit];
291:
292: switch (cmd)
293: {
294: case SIOCSIFADDR:
295: #ifndef BSD4_3
296: if (ifp->if_flags & IFF_RUNNING)
297: if_rtinit (ifp, -1); /* delete previous route */
298: #ifndef sun
299: sin = (struct sockaddr_in *)&ifr -> ifr_addr;
300: #endif
301: ifp->if_addr = *((struct sockaddr *) sin);
302: ifp->if_net = in_netof (sin->sin_addr);
303: ifp->if_host[0] = in_lnaof (sin->sin_addr);
304: #endif
305: tuninit (ifp->if_unit);
306: break;
307: case SIOCSIFDSTADDR:
308: tp->tun_flags |= TUN_DSTADDR;
309: #ifndef BSD4_3
310: #ifndef sun
311: sin = (struct sockaddr_in *)&ifr -> ifr_addr;
312: #endif
313: ifp->if_dstaddr = *((struct sockaddr *)sin);
314: #endif BSD4_3
315: TUNDEBUG ("%s%d: destination addres set\n", ifp->if_name,
316: ifp -> if_unit);
317: break;
318: default:
319: error = EINVAL;
320: }
321: splx (s);
322: return (error);
323: }
324:
325: /*
326: * tunoutput - queue packets from higher level ready to put out.
327: */
328: tunoutput (ifp, m0, dst)
329: struct ifnet *ifp;
330: struct mbuf *m0;
331: struct sockaddr *dst;
332: {
333: struct tunctl *tp;
334: struct proc *p;
335: int s;
336:
337: TUNDEBUG ("%s%d: tunoutput\n", ifp->if_name, ifp->if_unit);
338: tp = &tunctl[ifp->if_unit];
339: if ((tp->tun_flags & TUN_READY) != TUN_READY) {
340: if(tuncheckready(ifp) == 0) {
341: TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name,
342: ifp->if_unit, tp->tun_flags);
343: m_freem (m0);
344: return EHOSTDOWN;
345: }
346: }
347:
348: switch (dst->sa_family) {
349: #ifdef INET
350: case AF_INET:
351: s = splimp ();
352: if (IF_QFULL (&ifp->if_snd))
353: {
354: IF_DROP (&ifp->if_snd);
355: m_freem (m0);
356: splx (s);
357: ifp->if_collisions++;
358: return (ENOBUFS);
359: }
360: IF_ENQUEUE (&ifp->if_snd, m0);
361: splx (s);
362: ifp->if_opackets++;
363: break;
364: #endif
365: default:
366: m_freem (m0);
367: return EAFNOSUPPORT;
368: }
369:
370: if (tp->tun_flags & TUN_RWAIT) {
371: tp->tun_flags &= ~TUN_RWAIT;
372: wakeup ((caddr_t) tp);
373: }
374: if (tp->tun_flags & TUN_ASYNC && tp -> tun_pgrp != 0) {
375: if (tp->tun_pgrp > 0)
376: gsignal (tp->tun_pgrp, SIGIO);
377: else if ((p = pfind (-tp->tun_pgrp)) != 0)
378: psignal (p, SIGIO);
379: }
1.1.1.3 ! root 380: selwakeup (&tp->tun_rsel);
1.1 root 381: return 0;
382: }
383:
384: /*
385: * the cdevsw interface is now pretty minimal.
386: */
387:
388: tuncioctl (dev, cmd, data, flag)
389: dev_t dev;
390: caddr_t data;
391: {
392: int unit = minor(dev);
393: struct tunctl *tp = &tunctl[unit];
394: int s;
395:
396: switch (cmd) {
397: case TUNSDEBUG:
398: tundebug = *(int *)data;
399: break;
400:
401: case TUNGDEBUG:
402: *(int *)data = tundebug;
403: break;
404:
405: case FIONBIO:
406: if (*(int *)data)
407: tp->tun_flags |= TUN_NBIO;
408: else
409: tp->tun_flags &= ~TUN_NBIO;
410: break;
411:
412: case FIOASYNC:
413: if (*(int *)data)
414: tp->tun_flags |= TUN_ASYNC;
415: else
416: tp->tun_flags &= ~TUN_ASYNC;
417: break;
418:
419: case FIONREAD:
420: s = splimp ();
421: if (tp->tun_if.if_snd.ifq_head)
422: *(int *)data = tp->tun_if.if_snd.ifq_head->m_len;
423: else *(int *)data = 0;
424: splx (s);
425: break;
426:
427: case TIOCSPGRP:
428: tp->tun_pgrp = *(int *)data;
429: break;
430:
431: case TIOCGPGRP:
432: *(int *)data = tp->tun_pgrp;
433: break;
434:
435: default:
436: return (ENOTTY);
437: }
438: return (0);
439: }
440:
441: /*
442: * The cdevsw read interface - reads a packet at a time, or at least as much
443: * of a packet as can be read.
444: */
445: tunread (dev, uio)
446: dev_t dev;
447: struct uio *uio;
448: {
449: register struct ifnet *ifp;
450: register struct mbuf *m, *m0;
451: int unit = minor (dev);
452: int len, s;
453: int error = 0;
454: struct tunctl *tp;
455:
456: tp = &tunctl[unit];
457: ifp = &tp->tun_if;
458: TUNDEBUG ("%s%d: read\n", ifp->if_name, ifp->if_unit);
459: if ((tp->tun_flags & TUN_READY) != TUN_READY) {
460: if(tuncheckready(ifp) == 0) {
461: TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name,
462: ifp->if_unit, tp->tun_flags);
463: return EHOSTDOWN;
464: }
465: }
466:
467: tp->tun_flags &= ~TUN_RWAIT;
468:
469: s = splimp ();
470: do {
471: IF_DEQUEUE (&ifp->if_snd, m0);
472: if (m0 == 0) {
473: if (tp -> tun_flags & TUN_NBIO) {
474: splx (s);
475: return EWOULDBLOCK;
476: }
477: tp->tun_flags |= TUN_RWAIT;
1.1.1.3 ! root 478: tsleep ((caddr_t) tp, PZERO + 1, "tunread", 0);
1.1 root 479: }
480: } while (m0 == 0);
481: splx (s);
482:
483: while (m0 && uio->uio_resid > 0 && error == 0) {
484: len = MIN (uio->uio_resid, m0->m_len);
485: if (len == 0)
486: break;
487: error = uiomove (mtod (m0, caddr_t), len,
488: UIO_READ, uio);
489: MFREE (m0, m);
490: m0 = m;
491: }
492:
493: if (m0 != 0) {
494: TUNDEBUG ("Dropping mbuf\n");
495: m_freem (m0);
496: }
497: return error;
498: }
499:
500: /*
501: * the cdevsw write interface - an atomic write is a packet - or else!
502: */
503:
504: tunwrite (dev, uio)
505: int dev;
506: struct uio *uio;
507: {
508: int error = 0;
509: int unit = minor (dev);
510: struct mbuf *top, **mp, *m;
511: struct ifnet *ifp = &(tunctl[unit].tun_if);
512: int s;
513:
514: TUNDEBUG ("%s%d: tunwrite\n", ifp->if_name, ifp->if_unit);
515:
516: if (uio->uio_resid < 0 || uio->uio_resid > TUNMTU) {
517: TUNDEBUG ("%s%d: len=%d!\n", ifp->if_name, ifp->if_unit,
518: uio->uio_resid);
519: return EIO;
520: }
521: top = 0;
522: mp = ⊤
523: while (error == 0 && uio->uio_resid > 0) {
524: MGET (m, M_DONTWAIT, MT_DATA);
525: if (m == 0) {
526: error = ENOBUFS;
527: break;
528: }
529: m->m_len = MIN (MLEN, uio->uio_resid);
530: error = uiomove (mtod (m, caddr_t), m->m_len, UIO_WRITE, uio);
531: *mp = m;
532: mp = &m->m_next;
533: }
534: if (error) {
535: if (top)
536: m_freem (top);
537: return error;
538: }
539:
540: #ifdef BSD4_3
541: /*
542: * Place interface pointer before the data
543: * for the receiving protocol.
544: */
545: if (top->m_off <= MMAXOFF &&
546: top->m_off >= MMINOFF + sizeof(struct ifnet *)) {
547: top->m_off -= sizeof(struct ifnet *);
548: top->m_len += sizeof(struct ifnet *);
549: } else {
550: MGET(m, M_DONTWAIT, MT_HEADER);
551: if (m == (struct mbuf *)0)
552: return (ENOBUFS);
553: m->m_len = sizeof(struct ifnet *);
554: m->m_next = top;
555: top = m;
556: }
557: *(mtod(top, struct ifnet **)) = ifp;
558: #endif /* BSD4_3 */
559:
560: s = splimp ();
561: if (IF_QFULL (&ipintrq)) {
562: IF_DROP (&ipintrq);
563: splx (s);
564: ifp->if_collisions++;
565: m_freem (top);
566: return ENOBUFS;
567: }
568: IF_ENQUEUE (&ipintrq, top);
569: splx (s);
570: ifp->if_ipackets++;
571: schednetisr (NETISR_IP);
572: return error;
573: }
574:
575: /*
576: * tunselect - the select interface, this is only useful on reads really.
577: * The write detect always returns true, write never blocks anyway, it either
578: * accepts the packet or drops it.
579: */
580: tunselect (dev, rw)
581: dev_t dev;
582: int rw;
583: {
584: int unit = minor (dev);
585: register struct tunctl *tp = &tunctl[unit];
586: struct ifnet *ifp = &tp->tun_if;
587: int s = splimp ();
588:
589: TUNDEBUG ("%s%d: tunselect\n", ifp->if_name, ifp->if_unit);
590: switch (rw) {
591: case FREAD:
592: if (ifp->if_snd.ifq_len > 0) {
593: splx (s);
594: TUNDEBUG ("%s%d: tunselect q=%d\n", ifp->if_name,
595: ifp->if_unit, ifp->if_snd.ifq_len);
596: return 1;
597: }
1.1.1.3 ! root 598: selrecord(p, &tp->tun_rsel);
1.1 root 599: break;
600: case FWRITE:
601: splx (s);
602: return 1;
603: }
604: splx (s);
605: TUNDEBUG ("%s%d: tunselect waiting\n", ifp->if_name, ifp->if_unit);
606: return 0;
607: }
608: #endif NTUN
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.