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