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 its 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/poll mode of
14 * operation though.
15 *
16 * $FreeBSD: head/sys/net/if_tun.c 111742 2003-03-02 15:56:49Z des $
17 */
18
19#include "opt_inet.h"
20#include "opt_mac.h"
21
22#include <sys/param.h>
23#include <sys/proc.h>
24#include <sys/systm.h>
--- 105 unchanged lines hidden (view full) ---
130 tunbasedev = (*dev)->si_udev;
131 else {
132 (*dev)->si_flags |= SI_CHEAPCLONE;
133 dev_depends(udev2dev(tunbasedev, 0), *dev);
134 }
135}
136
137static int
138tunmodevent(module_t mod, int type, void *data)
139{
140 static eventhandler_tag tag;
141 struct tun_softc *tp;
142 dev_t dev;
143 int err;
144
145 switch (type) {
146 case MOD_LOAD:
147 tag = EVENTHANDLER_REGISTER(dev_clone, tunclone, 0, 1000);
148 if (tag == NULL)
149 return (ENOMEM);
150 tununits.rm_type = RMAN_ARRAY;
151 tununits.rm_descr = "open if_tun units";
152 err = rman_init(&tununits);
153 if (err != 0) {
154 EVENTHANDLER_DEREGISTER(dev_clone, tag);
155 return (err);
156 }
157 err = rman_manage_region(&tununits, 0, TUN_MAXUNIT);
158 if (err != 0) {
159 printf("%s: tununits: rman_manage_region: Failed %d\n",
160 TUNNAME, err);
161 rman_fini(&tununits);
162 EVENTHANDLER_DEREGISTER(dev_clone, tag);
163 return (err);
164 }
165 break;
166 case MOD_UNLOAD:
167 err = rman_fini(&tununits);
168 if (err != 0)
169 return (err);
170 EVENTHANDLER_DEREGISTER(dev_clone, tag);
171
172 while (tunhead != NULL) {
173 KASSERT((tunhead->tun_flags & TUN_OPEN) == 0,
174 ("tununits is out of sync - unit %d",
--- 12 unchanged lines hidden (view full) ---
187 /*
188 * Destroying tunbasedev results in all of our make_dev()s
189 * conveniently going away.
190 */
191 if (tunbasedev != NOUDEV)
192 destroy_dev(udev2dev(tunbasedev, 0));
193
194 break;
195 }
196 return 0;
197}
198
199static moduledata_t tun_mod = {
200 "if_tun",
201 tunmodevent,
202 0
203};
204
205DECLARE_MODULE(if_tun, tun_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
206
207static void
208tunstart(struct ifnet *ifp)
209{
210 struct tun_softc *tp = ifp->if_softc;
211
--- 97 unchanged lines hidden (view full) ---
309
310 if (ifp->if_flags & IFF_UP) {
311 s = splimp();
312 if_down(ifp);
313 splx(s);
314 }
315
316 if (ifp->if_flags & IFF_RUNNING) {
317 struct ifaddr *ifa;
318
319 s = splimp();
320 /* find internet addresses and delete routes */
321 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
322 if (ifa->ifa_addr->sa_family == AF_INET)
323 rtinit(ifa, (int)RTM_DELETE,
324 tp->tun_flags & TUN_DSTADDR ? RTF_HOST : 0);
325 ifp->if_flags &= ~IFF_RUNNING;
--- 9 unchanged lines hidden (view full) ---
335
336 return (0);
337}
338
339static int
340tuninit(struct ifnet *ifp)
341{
342 struct tun_softc *tp = ifp->if_softc;
343 struct ifaddr *ifa;
344 int error = 0;
345
346 TUNDEBUG("%s%d: tuninit\n", ifp->if_name, ifp->if_unit);
347
348 ifp->if_flags |= IFF_UP | IFF_RUNNING;
349 getmicrotime(&ifp->if_lastchange);
350
351 for (ifa = TAILQ_FIRST(&ifp->if_addrhead); ifa;
352 ifa = TAILQ_NEXT(ifa, ifa_link)) {
353 if (ifa->ifa_addr == NULL)
354 error = EFAULT;
355 /* XXX: Should maybe return straight off? */
356 else {
357#ifdef INET
358 if (ifa->ifa_addr->sa_family == AF_INET) {
359 struct sockaddr_in *si;
--- 167 unchanged lines hidden (view full) ---
527 * the cdevsw interface is now pretty minimal.
528 */
529static int
530tunioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
531{
532 int s;
533 int error;
534 struct tun_softc *tp = dev->si_drv1;
535 struct tuninfo *tunp;
536
537 switch (cmd) {
538 case TUNSIFINFO:
539 tunp = (struct tuninfo *)data;
540 if (tunp->mtu < IF_MINMTU)
541 return (EINVAL);
542 if (tp->tun_if.if_mtu != tunp->mtu
543 && (error = suser(td)) != 0)
544 return (error);
545 tp->tun_if.if_mtu = tunp->mtu;
546 tp->tun_if.if_type = tunp->type;
547 tp->tun_if.if_baudrate = tunp->baudrate;
548 break;
549 case TUNGIFINFO:
550 tunp = (struct tuninfo *)data;
551 tunp->mtu = tp->tun_if.if_mtu;
552 tunp->type = tp->tun_if.if_type;
553 tunp->baudrate = tp->tun_if.if_baudrate;
554 break;
555 case TUNSDEBUG:
556 tundebug = *(int *)data;
557 break;
558 case TUNGDEBUG:
559 *(int *)data = tundebug;
560 break;
561 case TUNSLMODE:
562 if (*(int *)data) {
563 tp->tun_flags |= TUN_LMODE;
564 tp->tun_flags &= ~TUN_IFHEAD;
565 } else
566 tp->tun_flags &= ~TUN_LMODE;
567 break;
568 case TUNSIFHEAD:
569 if (*(int *)data) {
570 tp->tun_flags |= TUN_IFHEAD;
571 tp->tun_flags &= ~TUN_LMODE;
572 } else
573 tp->tun_flags &= ~TUN_IFHEAD;
574 break;
575 case TUNGIFHEAD:
576 *(int *)data = (tp->tun_flags & TUN_IFHEAD) ? 1 : 0;
577 break;
578 case TUNSIFMODE:
579 /* deny this if UP */
580 if (tp->tun_if.if_flags & IFF_UP)
--- 20 unchanged lines hidden (view full) ---
601 tp->tun_flags |= TUN_ASYNC;
602 else
603 tp->tun_flags &= ~TUN_ASYNC;
604 break;
605 case FIONREAD:
606 s = splimp();
607 if (tp->tun_if.if_snd.ifq_head) {
608 struct mbuf *mb = tp->tun_if.if_snd.ifq_head;
609 for( *(int *)data = 0; mb != 0; mb = mb->m_next)
610 *(int *)data += mb->m_len;
611 } else
612 *(int *)data = 0;
613 splx(s);
614 break;
615 case FIOSETOWN:
616 return (fsetown(*(int *)data, &tp->tun_sigio));
617
--- 216 unchanged lines hidden ---
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 its 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/poll mode of
14 * operation though.
15 *
16 * $FreeBSD: head/sys/net/if_tun.c 111742 2003-03-02 15:56:49Z des $
17 */
18
19#include "opt_inet.h"
20#include "opt_mac.h"
21
22#include <sys/param.h>
23#include <sys/proc.h>
24#include <sys/systm.h>
--- 105 unchanged lines hidden (view full) ---
130 tunbasedev = (*dev)->si_udev;
131 else {
132 (*dev)->si_flags |= SI_CHEAPCLONE;
133 dev_depends(udev2dev(tunbasedev, 0), *dev);
134 }
135}
136
137static int
138tunmodevent(module_t mod, int type, void *data)
139{
140 static eventhandler_tag tag;
141 struct tun_softc *tp;
142 dev_t dev;
143 int err;
144
145 switch (type) {
146 case MOD_LOAD:
147 tag = EVENTHANDLER_REGISTER(dev_clone, tunclone, 0, 1000);
148 if (tag == NULL)
149 return (ENOMEM);
150 tununits.rm_type = RMAN_ARRAY;
151 tununits.rm_descr = "open if_tun units";
152 err = rman_init(&tununits);
153 if (err != 0) {
154 EVENTHANDLER_DEREGISTER(dev_clone, tag);
155 return (err);
156 }
157 err = rman_manage_region(&tununits, 0, TUN_MAXUNIT);
158 if (err != 0) {
159 printf("%s: tununits: rman_manage_region: Failed %d\n",
160 TUNNAME, err);
161 rman_fini(&tununits);
162 EVENTHANDLER_DEREGISTER(dev_clone, tag);
163 return (err);
164 }
165 break;
166 case MOD_UNLOAD:
167 err = rman_fini(&tununits);
168 if (err != 0)
169 return (err);
170 EVENTHANDLER_DEREGISTER(dev_clone, tag);
171
172 while (tunhead != NULL) {
173 KASSERT((tunhead->tun_flags & TUN_OPEN) == 0,
174 ("tununits is out of sync - unit %d",
--- 12 unchanged lines hidden (view full) ---
187 /*
188 * Destroying tunbasedev results in all of our make_dev()s
189 * conveniently going away.
190 */
191 if (tunbasedev != NOUDEV)
192 destroy_dev(udev2dev(tunbasedev, 0));
193
194 break;
195 }
196 return 0;
197}
198
199static moduledata_t tun_mod = {
200 "if_tun",
201 tunmodevent,
202 0
203};
204
205DECLARE_MODULE(if_tun, tun_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
206
207static void
208tunstart(struct ifnet *ifp)
209{
210 struct tun_softc *tp = ifp->if_softc;
211
--- 97 unchanged lines hidden (view full) ---
309
310 if (ifp->if_flags & IFF_UP) {
311 s = splimp();
312 if_down(ifp);
313 splx(s);
314 }
315
316 if (ifp->if_flags & IFF_RUNNING) {
317 struct ifaddr *ifa;
318
319 s = splimp();
320 /* find internet addresses and delete routes */
321 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
322 if (ifa->ifa_addr->sa_family == AF_INET)
323 rtinit(ifa, (int)RTM_DELETE,
324 tp->tun_flags & TUN_DSTADDR ? RTF_HOST : 0);
325 ifp->if_flags &= ~IFF_RUNNING;
--- 9 unchanged lines hidden (view full) ---
335
336 return (0);
337}
338
339static int
340tuninit(struct ifnet *ifp)
341{
342 struct tun_softc *tp = ifp->if_softc;
343 struct ifaddr *ifa;
344 int error = 0;
345
346 TUNDEBUG("%s%d: tuninit\n", ifp->if_name, ifp->if_unit);
347
348 ifp->if_flags |= IFF_UP | IFF_RUNNING;
349 getmicrotime(&ifp->if_lastchange);
350
351 for (ifa = TAILQ_FIRST(&ifp->if_addrhead); ifa;
352 ifa = TAILQ_NEXT(ifa, ifa_link)) {
353 if (ifa->ifa_addr == NULL)
354 error = EFAULT;
355 /* XXX: Should maybe return straight off? */
356 else {
357#ifdef INET
358 if (ifa->ifa_addr->sa_family == AF_INET) {
359 struct sockaddr_in *si;
--- 167 unchanged lines hidden (view full) ---
527 * the cdevsw interface is now pretty minimal.
528 */
529static int
530tunioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
531{
532 int s;
533 int error;
534 struct tun_softc *tp = dev->si_drv1;
535 struct tuninfo *tunp;
536
537 switch (cmd) {
538 case TUNSIFINFO:
539 tunp = (struct tuninfo *)data;
540 if (tunp->mtu < IF_MINMTU)
541 return (EINVAL);
542 if (tp->tun_if.if_mtu != tunp->mtu
543 && (error = suser(td)) != 0)
544 return (error);
545 tp->tun_if.if_mtu = tunp->mtu;
546 tp->tun_if.if_type = tunp->type;
547 tp->tun_if.if_baudrate = tunp->baudrate;
548 break;
549 case TUNGIFINFO:
550 tunp = (struct tuninfo *)data;
551 tunp->mtu = tp->tun_if.if_mtu;
552 tunp->type = tp->tun_if.if_type;
553 tunp->baudrate = tp->tun_if.if_baudrate;
554 break;
555 case TUNSDEBUG:
556 tundebug = *(int *)data;
557 break;
558 case TUNGDEBUG:
559 *(int *)data = tundebug;
560 break;
561 case TUNSLMODE:
562 if (*(int *)data) {
563 tp->tun_flags |= TUN_LMODE;
564 tp->tun_flags &= ~TUN_IFHEAD;
565 } else
566 tp->tun_flags &= ~TUN_LMODE;
567 break;
568 case TUNSIFHEAD:
569 if (*(int *)data) {
570 tp->tun_flags |= TUN_IFHEAD;
571 tp->tun_flags &= ~TUN_LMODE;
572 } else
573 tp->tun_flags &= ~TUN_IFHEAD;
574 break;
575 case TUNGIFHEAD:
576 *(int *)data = (tp->tun_flags & TUN_IFHEAD) ? 1 : 0;
577 break;
578 case TUNSIFMODE:
579 /* deny this if UP */
580 if (tp->tun_if.if_flags & IFF_UP)
--- 20 unchanged lines hidden (view full) ---
601 tp->tun_flags |= TUN_ASYNC;
602 else
603 tp->tun_flags &= ~TUN_ASYNC;
604 break;
605 case FIONREAD:
606 s = splimp();
607 if (tp->tun_if.if_snd.ifq_head) {
608 struct mbuf *mb = tp->tun_if.if_snd.ifq_head;
609 for( *(int *)data = 0; mb != 0; mb = mb->m_next)
610 *(int *)data += mb->m_len;
611 } else
612 *(int *)data = 0;
613 splx(s);
614 break;
615 case FIOSETOWN:
616 return (fsetown(*(int *)data, &tp->tun_sigio));
617
--- 216 unchanged lines hidden ---