FreeBSD/Linux Kernel Cross Reference
sys/net/if_tun.c
1 /* $NetBSD: if_tun.c,v 1.14 1994/06/29 06:36:25 cgd Exp $ */
2
3 /*
4 * Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk>
5 * Nottingham University 1987.
6 *
7 * This source may be freely distributed, however I would be interested
8 * in any changes that are made.
9 *
10 * This driver takes packets off the IP i/f and hands them up to a
11 * user process to have it's wicked way with. This driver has it's
12 * roots in a similar driver written by Phil Cockcroft (formerly) at
13 * UCL. This driver is based much more on read/write/select mode of
14 * operation though.
15 */
16
17 #include "tun.h"
18 #if NTUN > 0
19
20 #include <sys/param.h>
21 #include <sys/proc.h>
22 #include <sys/systm.h>
23 #include <sys/mbuf.h>
24 #include <sys/buf.h>
25 #include <sys/protosw.h>
26 #include <sys/socket.h>
27 #include <sys/ioctl.h>
28 #include <sys/errno.h>
29 #include <sys/syslog.h>
30 #include <sys/select.h>
31 #include <sys/file.h>
32 #include <sys/signalvar.h>
33 #include <sys/kernel.h>
34 #include <sys/sysctl.h>
35 #ifdef DEVFS
36 #include <sys/devfsext.h>
37 #endif /*DEVFS*/
38 #include <sys/conf.h>
39
40 #include <net/if.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 #include "bpfilter.h"
58 #if NBPFILTER > 0
59 #include <sys/time.h>
60 #include <net/bpf.h>
61 #endif
62
63 #include <net/if_tunvar.h>
64 #include <net/if_tun.h>
65
66 static void tunattach __P((void *));
67 PSEUDO_SET(tunattach, if_tun);
68
69 #define TUNDEBUG if (tundebug) printf
70 static int tundebug = 0;
71 SYSCTL_INT(_debug, OID_AUTO, if_tun_debug, CTLFLAG_RW, &tundebug, 0, "");
72
73 static struct tun_softc tunctl[NTUN];
74
75 static int tunoutput __P((struct ifnet *, struct mbuf *, struct sockaddr *,
76 struct rtentry *rt));
77 static int tunifioctl __P((struct ifnet *, int, caddr_t));
78 static int tuninit __P((int));
79
80 static d_open_t tunopen;
81 static d_close_t tunclose;
82 static d_read_t tunread;
83 static d_write_t tunwrite;
84 static d_ioctl_t tunioctl;
85 static d_select_t tunselect;
86
87 #define CDEV_MAJOR 52
88 static struct cdevsw tun_cdevsw = {
89 tunopen, tunclose, tunread, tunwrite,
90 tunioctl, nullstop, noreset, nodevtotty,
91 tunselect, nommap, nostrategy, "tun", NULL, -1
92 };
93
94
95 static tun_devsw_installed = 0;
96 #ifdef DEVFS
97 static void *tun_devfs_token[NTUN];
98 #endif
99
100 static void
101 tunattach(dummy)
102 void *dummy;
103 {
104 register int i;
105 struct ifnet *ifp;
106 dev_t dev;
107
108 if ( tun_devsw_installed )
109 return;
110 dev = makedev(CDEV_MAJOR, 0);
111 cdevsw_add(&dev, &tun_cdevsw, NULL);
112 tun_devsw_installed = 1;
113 for ( i = 0; i < NTUN; i++ ) {
114 #ifdef DEVFS
115 tun_devfs_token[i] = devfs_add_devswf(&tun_cdevsw, i, DV_CHR,
116 UID_UUCP, GID_DIALER,
117 0600, "tun%d", i);
118 #endif
119 tunctl[i].tun_flags = TUN_INITED;
120
121 ifp = &tunctl[i].tun_if;
122 ifp->if_unit = i;
123 ifp->if_name = "tun";
124 ifp->if_mtu = TUNMTU;
125 ifp->if_ioctl = tunifioctl;
126 ifp->if_output = tunoutput;
127 ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
128 ifp->if_snd.ifq_maxlen = ifqmaxlen;
129 ifp->if_collisions = 0;
130 ifp->if_ierrors = 0;
131 ifp->if_oerrors = 0;
132 ifp->if_ipackets = 0;
133 ifp->if_opackets = 0;
134 if_attach(ifp);
135 #if NBPFILTER > 0
136 bpfattach(ifp, DLT_NULL, sizeof(u_int));
137 #endif
138 }
139 }
140
141 /*
142 * tunnel open - must be superuser & the device must be
143 * configured in
144 */
145 static int
146 tunopen(dev, flag, mode, p)
147 dev_t dev;
148 int flag, mode;
149 struct proc *p;
150 {
151 struct ifnet *ifp;
152 struct tun_softc *tp;
153 register int unit, error;
154
155 error = suser(p->p_ucred, &p->p_acflag);
156 if (error)
157 return (error);
158
159 if ((unit = minor(dev)) >= NTUN)
160 return (ENXIO);
161 tp = &tunctl[unit];
162 if (tp->tun_flags & TUN_OPEN)
163 return EBUSY;
164 ifp = &tp->tun_if;
165 tp->tun_flags |= TUN_OPEN;
166 TUNDEBUG("%s%d: open\n", ifp->if_name, ifp->if_unit);
167 return (0);
168 }
169
170 /*
171 * tunclose - close the device - mark i/f down & delete
172 * routing info
173 */
174 static int
175 tunclose(dev_t dev, int foo, int bar, struct proc *p)
176 {
177 register int unit = minor(dev), s;
178 struct tun_softc *tp = &tunctl[unit];
179 struct ifnet *ifp = &tp->tun_if;
180 struct mbuf *m;
181
182 tp->tun_flags &= ~TUN_OPEN;
183
184 /*
185 * junk all pending output
186 */
187 do {
188 s = splimp();
189 IF_DEQUEUE(&ifp->if_snd, m);
190 splx(s);
191 if (m)
192 m_freem(m);
193 } while (m);
194
195 if (ifp->if_flags & IFF_UP) {
196 s = splimp();
197 if_down(ifp);
198 if (ifp->if_flags & IFF_RUNNING) {
199 /* find internet addresses and delete routes */
200 register struct ifaddr *ifa;
201 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
202 if (ifa->ifa_addr->sa_family == AF_INET) {
203 rtinit(ifa, (int)RTM_DELETE,
204 tp->tun_flags & TUN_DSTADDR ? RTF_HOST : 0);
205 }
206 }
207 }
208 splx(s);
209 }
210 tp->tun_pgrp = 0;
211 selwakeup(&tp->tun_rsel);
212
213 TUNDEBUG ("%s%d: closed\n", ifp->if_name, ifp->if_unit);
214 return (0);
215 }
216
217 static int
218 tuninit(unit)
219 int unit;
220 {
221 struct tun_softc *tp = &tunctl[unit];
222 struct ifnet *ifp = &tp->tun_if;
223 register struct ifaddr *ifa;
224
225 TUNDEBUG("%s%d: tuninit\n", ifp->if_name, ifp->if_unit);
226
227 ifp->if_flags |= IFF_UP | IFF_RUNNING;
228 microtime(&ifp->if_lastchange);
229
230 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
231 if (ifa->ifa_addr->sa_family == AF_INET) {
232 struct sockaddr_in *si;
233
234 si = (struct sockaddr_in *)ifa->ifa_addr;
235 if (si && si->sin_addr.s_addr)
236 tp->tun_flags |= TUN_IASET;
237
238 si = (struct sockaddr_in *)ifa->ifa_dstaddr;
239 if (si && si->sin_addr.s_addr)
240 tp->tun_flags |= TUN_DSTADDR;
241 }
242
243 return 0;
244 }
245
246 /*
247 * Process an ioctl request.
248 */
249 int
250 tunifioctl(ifp, cmd, data)
251 struct ifnet *ifp;
252 int cmd;
253 caddr_t data;
254 {
255 register struct ifreq *ifr = (struct ifreq *)data;
256 int error = 0, s;
257
258 s = splimp();
259 switch(cmd) {
260 case SIOCSIFADDR:
261 tuninit(ifp->if_unit);
262 TUNDEBUG("%s%d: address set\n",
263 ifp->if_name, ifp->if_unit);
264 break;
265 case SIOCSIFDSTADDR:
266 tuninit(ifp->if_unit);
267 TUNDEBUG("%s%d: destination address set\n",
268 ifp->if_name, ifp->if_unit);
269 break;
270 case SIOCSIFMTU:
271 ifp->if_mtu = ifr->ifr_mtu;
272 TUNDEBUG("%s%d: mtu set\n",
273 ifp->if_name, ifp->if_unit);
274 break;
275 case SIOCADDMULTI:
276 case SIOCDELMULTI:
277 if (ifr == 0) {
278 error = EAFNOSUPPORT; /* XXX */
279 break;
280 }
281 switch (ifr->ifr_addr.sa_family) {
282
283 #ifdef INET
284 case AF_INET:
285 break;
286 #endif
287
288 default:
289 error = EAFNOSUPPORT;
290 break;
291 }
292 break;
293
294
295 default:
296 error = EINVAL;
297 }
298 splx(s);
299 return (error);
300 }
301
302 /*
303 * tunoutput - queue packets from higher level ready to put out.
304 */
305 int
306 tunoutput(ifp, m0, dst, rt)
307 struct ifnet *ifp;
308 struct mbuf *m0;
309 struct sockaddr *dst;
310 struct rtentry *rt;
311 {
312 struct tun_softc *tp = &tunctl[ifp->if_unit];
313 struct proc *p;
314 int s;
315
316 TUNDEBUG ("%s%d: tunoutput\n", ifp->if_name, ifp->if_unit);
317
318 if ((tp->tun_flags & TUN_READY) != TUN_READY) {
319 TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name,
320 ifp->if_unit, tp->tun_flags);
321 m_freem (m0);
322 return EHOSTDOWN;
323 }
324
325 #if NBPFILTER > 0
326 /* BPF write needs to be handled specially */
327 if (dst->sa_family == AF_UNSPEC) {
328 dst->sa_family = *(mtod(m0, int *));
329 m0->m_len -= sizeof(int);
330 m0->m_pkthdr.len -= sizeof(int);
331 m0->m_data += sizeof(int);
332 }
333
334 if (ifp->if_bpf) {
335 /*
336 * We need to prepend the address family as
337 * a four byte field. Cons up a dummy header
338 * to pacify bpf. This is safe because bpf
339 * will only read from the mbuf (i.e., it won't
340 * try to free it or keep a pointer to it).
341 */
342 struct mbuf m;
343 u_int af = dst->sa_family;
344
345 m.m_next = m0;
346 m.m_len = 4;
347 m.m_data = (char *)⁡
348
349 bpf_mtap(ifp, &m);
350 }
351 #endif
352
353 switch(dst->sa_family) {
354 #ifdef INET
355 case AF_INET:
356 s = splimp();
357 if (IF_QFULL(&ifp->if_snd)) {
358 IF_DROP(&ifp->if_snd);
359 m_freem(m0);
360 splx(s);
361 ifp->if_collisions++;
362 return (ENOBUFS);
363 }
364 ifp->if_obytes += m0->m_pkthdr.len;
365 IF_ENQUEUE(&ifp->if_snd, m0);
366 splx(s);
367 ifp->if_opackets++;
368 break;
369 #endif
370 default:
371 m_freem(m0);
372 return EAFNOSUPPORT;
373 }
374
375 if (tp->tun_flags & TUN_RWAIT) {
376 tp->tun_flags &= ~TUN_RWAIT;
377 wakeup((caddr_t)tp);
378 }
379 if (tp->tun_flags & TUN_ASYNC && tp->tun_pgrp) {
380 if (tp->tun_pgrp > 0)
381 gsignal(tp->tun_pgrp, SIGIO);
382 else if ((p = pfind(-tp->tun_pgrp)) != 0)
383 psignal(p, SIGIO);
384 }
385 selwakeup(&tp->tun_rsel);
386 return 0;
387 }
388
389 /*
390 * the cdevsw interface is now pretty minimal.
391 */
392 static int
393 tunioctl(dev, cmd, data, flag, p)
394 dev_t dev;
395 int cmd;
396 caddr_t data;
397 int flag;
398 struct proc *p;
399 {
400 int unit = minor(dev), s;
401 struct tun_softc *tp = &tunctl[unit];
402 struct tuninfo *tunp;
403
404 switch (cmd) {
405 case TUNSIFINFO:
406 tunp = (struct tuninfo *)data;
407 tp->tun_if.if_mtu = tunp->mtu;
408 tp->tun_if.if_type = tunp->type;
409 tp->tun_if.if_baudrate = tunp->baudrate;
410 break;
411 case TUNGIFINFO:
412 tunp = (struct tuninfo *)data;
413 tunp->mtu = tp->tun_if.if_mtu;
414 tunp->type = tp->tun_if.if_type;
415 tunp->baudrate = tp->tun_if.if_baudrate;
416 break;
417 case TUNSDEBUG:
418 tundebug = *(int *)data;
419 break;
420 case TUNGDEBUG:
421 *(int *)data = tundebug;
422 break;
423 case FIONBIO:
424 if (*(int *)data)
425 tp->tun_flags |= TUN_NBIO;
426 else
427 tp->tun_flags &= ~TUN_NBIO;
428 break;
429 case FIOASYNC:
430 if (*(int *)data)
431 tp->tun_flags |= TUN_ASYNC;
432 else
433 tp->tun_flags &= ~TUN_ASYNC;
434 break;
435 case FIONREAD:
436 s = splimp();
437 if (tp->tun_if.if_snd.ifq_head) {
438 struct mbuf *mb = tp->tun_if.if_snd.ifq_head;
439 for( *(int *)data = 0; mb != 0; mb = mb->m_next)
440 *(int *)data += mb->m_len;
441 } else
442 *(int *)data = 0;
443 splx(s);
444 break;
445 case TIOCSPGRP:
446 tp->tun_pgrp = *(int *)data;
447 break;
448 case TIOCGPGRP:
449 *(int *)data = tp->tun_pgrp;
450 break;
451 default:
452 return (ENOTTY);
453 }
454 return (0);
455 }
456
457 /*
458 * The cdevsw read interface - reads a packet at a time, or at
459 * least as much of a packet as can be read.
460 */
461 static int
462 tunread(dev_t dev, struct uio *uio, int flag)
463 {
464 int unit = minor(dev);
465 struct tun_softc *tp = &tunctl[unit];
466 struct ifnet *ifp = &tp->tun_if;
467 struct mbuf *m, *m0;
468 int error=0, len, s;
469
470 TUNDEBUG ("%s%d: read\n", ifp->if_name, ifp->if_unit);
471 if ((tp->tun_flags & TUN_READY) != TUN_READY) {
472 TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name,
473 ifp->if_unit, tp->tun_flags);
474 return EHOSTDOWN;
475 }
476
477 tp->tun_flags &= ~TUN_RWAIT;
478
479 s = splimp();
480 do {
481 IF_DEQUEUE(&ifp->if_snd, m0);
482 if (m0 == 0) {
483 if (tp->tun_flags & TUN_NBIO) {
484 splx(s);
485 return EWOULDBLOCK;
486 }
487 tp->tun_flags |= TUN_RWAIT;
488 if( error = tsleep((caddr_t)tp, PCATCH | (PZERO + 1),
489 "tunread", 0)) {
490 splx(s);
491 return error;
492 }
493 }
494 } while (m0 == 0);
495 splx(s);
496
497 while (m0 && uio->uio_resid > 0 && error == 0) {
498 len = min(uio->uio_resid, m0->m_len);
499 if (len == 0)
500 break;
501 error = uiomove(mtod(m0, caddr_t), len, uio);
502 MFREE(m0, m);
503 m0 = m;
504 }
505
506 if (m0) {
507 TUNDEBUG("Dropping mbuf\n");
508 m_freem(m0);
509 }
510 return error;
511 }
512
513 /*
514 * the cdevsw write interface - an atomic write is a packet - or else!
515 */
516 static int
517 tunwrite(dev_t dev, struct uio *uio, int flag)
518 {
519 int unit = minor (dev);
520 struct ifnet *ifp = &tunctl[unit].tun_if;
521 struct mbuf *top, **mp, *m;
522 int error=0, s, tlen, mlen;
523
524 TUNDEBUG("%s%d: tunwrite\n", ifp->if_name, ifp->if_unit);
525
526 if (uio->uio_resid < 0 || uio->uio_resid > TUNMRU) {
527 TUNDEBUG("%s%d: len=%d!\n", ifp->if_name, ifp->if_unit,
528 uio->uio_resid);
529 return EIO;
530 }
531 tlen = uio->uio_resid;
532
533 /* get a header mbuf */
534 MGETHDR(m, M_DONTWAIT, MT_DATA);
535 if (m == NULL)
536 return ENOBUFS;
537 mlen = MHLEN;
538
539 top = 0;
540 mp = ⊤
541 while (error == 0 && uio->uio_resid > 0) {
542 m->m_len = min(mlen, uio->uio_resid);
543 error = uiomove(mtod (m, caddr_t), m->m_len, uio);
544 *mp = m;
545 mp = &m->m_next;
546 if (uio->uio_resid > 0) {
547 MGET (m, M_DONTWAIT, MT_DATA);
548 if (m == 0) {
549 error = ENOBUFS;
550 break;
551 }
552 mlen = MLEN;
553 }
554 }
555 if (error) {
556 if (top)
557 m_freem (top);
558 return error;
559 }
560
561 top->m_pkthdr.len = tlen;
562 top->m_pkthdr.rcvif = ifp;
563
564 #if NBPFILTER > 0
565 if (ifp->if_bpf) {
566 /*
567 * We need to prepend the address family as
568 * a four byte field. Cons up a dummy header
569 * to pacify bpf. This is safe because bpf
570 * will only read from the mbuf (i.e., it won't
571 * try to free it or keep a pointer to it).
572 */
573 struct mbuf m;
574 u_int af = AF_INET;
575
576 m.m_next = top;
577 m.m_len = 4;
578 m.m_data = (char *)⁡
579
580 bpf_mtap(ifp, &m);
581 }
582 #endif
583
584 s = splimp();
585 if (IF_QFULL (&ipintrq)) {
586 IF_DROP(&ipintrq);
587 splx(s);
588 ifp->if_collisions++;
589 m_freem(top);
590 return ENOBUFS;
591 }
592 IF_ENQUEUE(&ipintrq, top);
593 splx(s);
594 ifp->if_ibytes += tlen;
595 ifp->if_ipackets++;
596 schednetisr(NETISR_IP);
597 return error;
598 }
599
600 /*
601 * tunselect - the select interface, this is only useful on reads
602 * really. The write detect always returns true, write never blocks
603 * anyway, it either accepts the packet or drops it.
604 */
605 static int
606 tunselect(dev_t dev, int rw, struct proc *p)
607 {
608 int unit = minor(dev), s;
609 struct tun_softc *tp = &tunctl[unit];
610 struct ifnet *ifp = &tp->tun_if;
611
612 s = splimp();
613 TUNDEBUG("%s%d: tunselect\n", ifp->if_name, ifp->if_unit);
614
615 switch (rw) {
616 case FREAD:
617 if (ifp->if_snd.ifq_len > 0) {
618 splx(s);
619 TUNDEBUG("%s%d: tunselect q=%d\n", ifp->if_name,
620 ifp->if_unit, ifp->if_snd.ifq_len);
621 return 1;
622 }
623 selrecord(p, &tp->tun_rsel);
624 break;
625 case FWRITE:
626 splx(s);
627 return 1;
628 }
629 splx(s);
630 TUNDEBUG("%s%d: tunselect waiting\n", ifp->if_name, ifp->if_unit);
631 return 0;
632 }
633
634
635 #endif /* NTUN */
Cache object: f7cc20b5c860921453198af789990f00
|