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