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