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 *
| 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 111741 2003-03-02 15:50:23Z des $
| 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> 25#include <sys/mac.h> 26#include <sys/mbuf.h> 27#include <sys/module.h> 28#include <sys/socket.h> 29#include <sys/filio.h> 30#include <sys/sockio.h> 31#include <sys/ttycom.h> 32#include <sys/poll.h> 33#include <sys/signalvar.h> 34#include <sys/filedesc.h> 35#include <sys/kernel.h> 36#include <sys/sysctl.h> 37#include <sys/conf.h> 38#include <sys/uio.h> 39#include <sys/vnode.h> 40#include <sys/malloc.h> 41#include <machine/bus.h> /* XXX Shouldn't really be required ! */ 42#include <sys/rman.h> 43 44#include <net/if.h> 45#include <net/if_types.h> 46#include <net/route.h> 47#include <net/intrq.h> 48#ifdef INET 49#include <netinet/in.h> 50#endif 51#include <net/bpf.h> 52#include <net/if_tunvar.h> 53#include <net/if_tun.h> 54 55#define TUNDEBUG if (tundebug) printf 56#define TUNNAME "tun" 57#define TUN_MAXUNIT 0x7fff /* ifp->if_unit is only 15 bits */ 58 59static MALLOC_DEFINE(M_TUN, TUNNAME, "Tunnel Interface"); 60static int tundebug = 0; 61static struct tun_softc *tunhead = NULL; 62static struct rman tununits; 63static udev_t tunbasedev = NOUDEV; 64SYSCTL_INT(_debug, OID_AUTO, if_tun_debug, CTLFLAG_RW, &tundebug, 0, ""); 65 66static void tunclone(void *arg, char *name, int namelen, dev_t *dev); 67static void tuncreate(dev_t dev); 68static int tunifioctl(struct ifnet *, u_long, caddr_t); 69static int tuninit(struct ifnet *); 70static int tunmodevent(module_t, int, void *); 71static int tunoutput(struct ifnet *, struct mbuf *, struct sockaddr *, 72 struct rtentry *rt); 73static void tunstart(struct ifnet *); 74 75static d_open_t tunopen; 76static d_close_t tunclose; 77static d_read_t tunread; 78static d_write_t tunwrite; 79static d_ioctl_t tunioctl; 80static d_poll_t tunpoll; 81 82#define CDEV_MAJOR 52 83static struct cdevsw tun_cdevsw = { 84 /* open */ tunopen, 85 /* close */ tunclose, 86 /* read */ tunread, 87 /* write */ tunwrite, 88 /* ioctl */ tunioctl, 89 /* poll */ tunpoll, 90 /* mmap */ nommap, 91 /* strategy */ nostrategy, 92 /* name */ TUNNAME, 93 /* maj */ CDEV_MAJOR, 94 /* dump */ nodump, 95 /* psize */ nopsize, 96 /* flags */ 0, 97}; 98 99static void 100tunclone(void *arg, char *name, int namelen, dev_t *dev) 101{ 102 struct resource *r; 103 int err; 104 int u; 105 106 if (*dev != NODEV) 107 return; 108 109 if (strcmp(name, TUNNAME) == 0) { 110 r = rman_reserve_resource(&tununits, 0, TUN_MAXUNIT, 1, 111 RF_ALLOCATED | RF_ACTIVE, NULL); 112 u = rman_get_start(r); 113 err = rman_release_resource(r); 114 KASSERT(err == 0, ("Unexpected failure releasing resource")); 115 *dev = makedev(CDEV_MAJOR, unit2minor(u)); 116 if ((*dev)->si_flags & SI_NAMED) 117 return; /* Already make_dev()d */ 118 } else if (dev_stdclone(name, NULL, TUNNAME, &u) != 1) 119 return; /* Don't recognise the name */ 120 121 *dev = make_dev(&tun_cdevsw, unit2minor(u), 122 UID_ROOT, GID_WHEEL, 0600, "tun%d", u); 123 124 /* 125 * All devices depend on tunbasedev so that we can simply 126 * destroy_dev() this device at module unload time to get 127 * rid of all our make_dev()d resources. 128 */ 129 if (tunbasedev == NOUDEV) 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
| 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> 25#include <sys/mac.h> 26#include <sys/mbuf.h> 27#include <sys/module.h> 28#include <sys/socket.h> 29#include <sys/filio.h> 30#include <sys/sockio.h> 31#include <sys/ttycom.h> 32#include <sys/poll.h> 33#include <sys/signalvar.h> 34#include <sys/filedesc.h> 35#include <sys/kernel.h> 36#include <sys/sysctl.h> 37#include <sys/conf.h> 38#include <sys/uio.h> 39#include <sys/vnode.h> 40#include <sys/malloc.h> 41#include <machine/bus.h> /* XXX Shouldn't really be required ! */ 42#include <sys/rman.h> 43 44#include <net/if.h> 45#include <net/if_types.h> 46#include <net/route.h> 47#include <net/intrq.h> 48#ifdef INET 49#include <netinet/in.h> 50#endif 51#include <net/bpf.h> 52#include <net/if_tunvar.h> 53#include <net/if_tun.h> 54 55#define TUNDEBUG if (tundebug) printf 56#define TUNNAME "tun" 57#define TUN_MAXUNIT 0x7fff /* ifp->if_unit is only 15 bits */ 58 59static MALLOC_DEFINE(M_TUN, TUNNAME, "Tunnel Interface"); 60static int tundebug = 0; 61static struct tun_softc *tunhead = NULL; 62static struct rman tununits; 63static udev_t tunbasedev = NOUDEV; 64SYSCTL_INT(_debug, OID_AUTO, if_tun_debug, CTLFLAG_RW, &tundebug, 0, ""); 65 66static void tunclone(void *arg, char *name, int namelen, dev_t *dev); 67static void tuncreate(dev_t dev); 68static int tunifioctl(struct ifnet *, u_long, caddr_t); 69static int tuninit(struct ifnet *); 70static int tunmodevent(module_t, int, void *); 71static int tunoutput(struct ifnet *, struct mbuf *, struct sockaddr *, 72 struct rtentry *rt); 73static void tunstart(struct ifnet *); 74 75static d_open_t tunopen; 76static d_close_t tunclose; 77static d_read_t tunread; 78static d_write_t tunwrite; 79static d_ioctl_t tunioctl; 80static d_poll_t tunpoll; 81 82#define CDEV_MAJOR 52 83static struct cdevsw tun_cdevsw = { 84 /* open */ tunopen, 85 /* close */ tunclose, 86 /* read */ tunread, 87 /* write */ tunwrite, 88 /* ioctl */ tunioctl, 89 /* poll */ tunpoll, 90 /* mmap */ nommap, 91 /* strategy */ nostrategy, 92 /* name */ TUNNAME, 93 /* maj */ CDEV_MAJOR, 94 /* dump */ nodump, 95 /* psize */ nopsize, 96 /* flags */ 0, 97}; 98 99static void 100tunclone(void *arg, char *name, int namelen, dev_t *dev) 101{ 102 struct resource *r; 103 int err; 104 int u; 105 106 if (*dev != NODEV) 107 return; 108 109 if (strcmp(name, TUNNAME) == 0) { 110 r = rman_reserve_resource(&tununits, 0, TUN_MAXUNIT, 1, 111 RF_ALLOCATED | RF_ACTIVE, NULL); 112 u = rman_get_start(r); 113 err = rman_release_resource(r); 114 KASSERT(err == 0, ("Unexpected failure releasing resource")); 115 *dev = makedev(CDEV_MAJOR, unit2minor(u)); 116 if ((*dev)->si_flags & SI_NAMED) 117 return; /* Already make_dev()d */ 118 } else if (dev_stdclone(name, NULL, TUNNAME, &u) != 1) 119 return; /* Don't recognise the name */ 120 121 *dev = make_dev(&tun_cdevsw, unit2minor(u), 122 UID_ROOT, GID_WHEEL, 0600, "tun%d", u); 123 124 /* 125 * All devices depend on tunbasedev so that we can simply 126 * destroy_dev() this device at module unload time to get 127 * rid of all our make_dev()d resources. 128 */ 129 if (tunbasedev == NOUDEV) 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)
| 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
| 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:
| 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 }
| 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:
| 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", 175 tunhead->tun_if.if_unit)); 176 tp = tunhead; 177 dev = makedev(tun_cdevsw.d_maj, 178 unit2minor(tp->tun_if.if_unit)); 179 KASSERT(dev->si_drv1 == tp, ("Bad makedev result")); 180 tunhead = tp->next; 181 bpfdetach(&tp->tun_if); 182 if_detach(&tp->tun_if); 183 KASSERT(dev->si_flags & SI_NAMED, ("Missing make_dev")); 184 free(tp, M_TUN); 185 } 186 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;
| 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", 175 tunhead->tun_if.if_unit)); 176 tp = tunhead; 177 dev = makedev(tun_cdevsw.d_maj, 178 unit2minor(tp->tun_if.if_unit)); 179 KASSERT(dev->si_drv1 == tp, ("Bad makedev result")); 180 tunhead = tp->next; 181 bpfdetach(&tp->tun_if); 182 if_detach(&tp->tun_if); 183 KASSERT(dev->si_flags & SI_NAMED, ("Missing make_dev")); 184 free(tp, M_TUN); 185 } 186 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}
| 195 } 196 return 0; 197}
|
198
| 198
|
199static moduledata_t tun_mod = { 200 "if_tun", 201 tunmodevent,
| 199static moduledata_t tun_mod = { 200 "if_tun", 201 tunmodevent,
|
202 0
| 202 0
|
203};
| 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 212 if (tp->tun_flags & TUN_RWAIT) { 213 tp->tun_flags &= ~TUN_RWAIT; 214 wakeup((caddr_t)tp); 215 } 216 if (tp->tun_flags & TUN_ASYNC && tp->tun_sigio) 217 pgsigio(&tp->tun_sigio, SIGIO, 0); 218 selwakeup(&tp->tun_rsel); 219} 220 221static void 222tuncreate(dev_t dev) 223{ 224 struct tun_softc *sc; 225 struct ifnet *ifp; 226 227 if (!(dev->si_flags & SI_NAMED)) 228 dev = make_dev(&tun_cdevsw, minor(dev), 229 UID_UUCP, GID_DIALER, 0600, "tun%d", dev2unit(dev)); 230 231 MALLOC(sc, struct tun_softc *, sizeof(*sc), M_TUN, M_WAITOK | M_ZERO); 232 sc->tun_flags = TUN_INITED; 233 sc->next = tunhead; 234 tunhead = sc; 235 236 ifp = &sc->tun_if; 237 ifp->if_unit = dev2unit(dev); 238 ifp->if_name = TUNNAME; 239 ifp->if_mtu = TUNMTU; 240 ifp->if_ioctl = tunifioctl; 241 ifp->if_output = tunoutput; 242 ifp->if_start = tunstart; 243 ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 244 ifp->if_type = IFT_PPP; 245 ifp->if_snd.ifq_maxlen = ifqmaxlen; 246 ifp->if_softc = sc; 247 if_attach(ifp); 248 bpfattach(ifp, DLT_NULL, sizeof(u_int)); 249 dev->si_drv1 = sc; 250} 251 252static int 253tunopen(dev_t dev, int flag, int mode, struct thread *td) 254{ 255 struct resource *r; 256 struct ifnet *ifp; 257 struct tun_softc *tp; 258 int unit; 259 260 unit = dev2unit(dev); 261 if (unit > TUN_MAXUNIT) 262 return (ENXIO); 263 264 r = rman_reserve_resource(&tununits, unit, unit, 1, 265 RF_ALLOCATED | RF_ACTIVE, NULL); 266 if (r == NULL) 267 return (EBUSY); 268 269 dev->si_flags &= ~SI_CHEAPCLONE; 270 271 tp = dev->si_drv1; 272 if (!tp) { 273 tuncreate(dev); 274 tp = dev->si_drv1; 275 } 276 KASSERT(!(tp->tun_flags & TUN_OPEN), ("Resource & flags out-of-sync")); 277 tp->r_unit = r; 278 tp->tun_pid = td->td_proc->p_pid; 279 ifp = &tp->tun_if; 280 tp->tun_flags |= TUN_OPEN; 281 TUNDEBUG("%s%d: open\n", ifp->if_name, ifp->if_unit); 282 283 return (0); 284} 285 286/* 287 * tunclose - close the device - mark i/f down & delete 288 * routing info 289 */ 290static int 291tunclose(dev_t dev, int foo, int bar, struct thread *td) 292{ 293 struct tun_softc *tp; 294 struct ifnet *ifp; 295 int s; 296 int err; 297 298 tp = dev->si_drv1; 299 ifp = &tp->tun_if; 300 301 KASSERT(tp->r_unit, ("Unit %d not marked open", ifp->if_unit)); 302 tp->tun_flags &= ~TUN_OPEN; 303 tp->tun_pid = 0; 304 305 /* 306 * junk all pending output 307 */ 308 IF_DRAIN(&ifp->if_snd); 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) {
| 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 212 if (tp->tun_flags & TUN_RWAIT) { 213 tp->tun_flags &= ~TUN_RWAIT; 214 wakeup((caddr_t)tp); 215 } 216 if (tp->tun_flags & TUN_ASYNC && tp->tun_sigio) 217 pgsigio(&tp->tun_sigio, SIGIO, 0); 218 selwakeup(&tp->tun_rsel); 219} 220 221static void 222tuncreate(dev_t dev) 223{ 224 struct tun_softc *sc; 225 struct ifnet *ifp; 226 227 if (!(dev->si_flags & SI_NAMED)) 228 dev = make_dev(&tun_cdevsw, minor(dev), 229 UID_UUCP, GID_DIALER, 0600, "tun%d", dev2unit(dev)); 230 231 MALLOC(sc, struct tun_softc *, sizeof(*sc), M_TUN, M_WAITOK | M_ZERO); 232 sc->tun_flags = TUN_INITED; 233 sc->next = tunhead; 234 tunhead = sc; 235 236 ifp = &sc->tun_if; 237 ifp->if_unit = dev2unit(dev); 238 ifp->if_name = TUNNAME; 239 ifp->if_mtu = TUNMTU; 240 ifp->if_ioctl = tunifioctl; 241 ifp->if_output = tunoutput; 242 ifp->if_start = tunstart; 243 ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 244 ifp->if_type = IFT_PPP; 245 ifp->if_snd.ifq_maxlen = ifqmaxlen; 246 ifp->if_softc = sc; 247 if_attach(ifp); 248 bpfattach(ifp, DLT_NULL, sizeof(u_int)); 249 dev->si_drv1 = sc; 250} 251 252static int 253tunopen(dev_t dev, int flag, int mode, struct thread *td) 254{ 255 struct resource *r; 256 struct ifnet *ifp; 257 struct tun_softc *tp; 258 int unit; 259 260 unit = dev2unit(dev); 261 if (unit > TUN_MAXUNIT) 262 return (ENXIO); 263 264 r = rman_reserve_resource(&tununits, unit, unit, 1, 265 RF_ALLOCATED | RF_ACTIVE, NULL); 266 if (r == NULL) 267 return (EBUSY); 268 269 dev->si_flags &= ~SI_CHEAPCLONE; 270 271 tp = dev->si_drv1; 272 if (!tp) { 273 tuncreate(dev); 274 tp = dev->si_drv1; 275 } 276 KASSERT(!(tp->tun_flags & TUN_OPEN), ("Resource & flags out-of-sync")); 277 tp->r_unit = r; 278 tp->tun_pid = td->td_proc->p_pid; 279 ifp = &tp->tun_if; 280 tp->tun_flags |= TUN_OPEN; 281 TUNDEBUG("%s%d: open\n", ifp->if_name, ifp->if_unit); 282 283 return (0); 284} 285 286/* 287 * tunclose - close the device - mark i/f down & delete 288 * routing info 289 */ 290static int 291tunclose(dev_t dev, int foo, int bar, struct thread *td) 292{ 293 struct tun_softc *tp; 294 struct ifnet *ifp; 295 int s; 296 int err; 297 298 tp = dev->si_drv1; 299 ifp = &tp->tun_if; 300 301 KASSERT(tp->r_unit, ("Unit %d not marked open", ifp->if_unit)); 302 tp->tun_flags &= ~TUN_OPEN; 303 tp->tun_pid = 0; 304 305 /* 306 * junk all pending output 307 */ 308 IF_DRAIN(&ifp->if_snd); 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 register struct ifaddr *ifa;
| 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; 326 splx(s); 327 } 328 329 funsetown(&tp->tun_sigio); 330 selwakeup(&tp->tun_rsel); 331 332 TUNDEBUG ("%s%d: closed\n", ifp->if_name, ifp->if_unit); 333 err = rman_release_resource(tp->r_unit); 334 KASSERT(err == 0, ("Unit %d failed to release", ifp->if_unit)); 335 336 return (0); 337} 338 339static int 340tuninit(struct ifnet *ifp) 341{ 342 struct tun_softc *tp = ifp->if_softc;
| 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; 326 splx(s); 327 } 328 329 funsetown(&tp->tun_sigio); 330 selwakeup(&tp->tun_rsel); 331 332 TUNDEBUG ("%s%d: closed\n", ifp->if_name, ifp->if_unit); 333 err = rman_release_resource(tp->r_unit); 334 KASSERT(err == 0, ("Unit %d failed to release", ifp->if_unit)); 335 336 return (0); 337} 338 339static int 340tuninit(struct ifnet *ifp) 341{ 342 struct tun_softc *tp = ifp->if_softc;
|
343 register struct ifaddr *ifa;
| 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
| 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;
| 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; 360 361 si = (struct sockaddr_in *)ifa->ifa_addr; 362 if (si->sin_addr.s_addr) 363 tp->tun_flags |= TUN_IASET; 364 365 si = (struct sockaddr_in *)ifa->ifa_dstaddr; 366 if (si && si->sin_addr.s_addr) 367 tp->tun_flags |= TUN_DSTADDR; 368 } 369#endif 370 } 371 } 372 return (error); 373} 374 375/* 376 * Process an ioctl request. 377 */ 378static int 379tunifioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 380{ 381 struct ifreq *ifr = (struct ifreq *)data; 382 struct tun_softc *tp = ifp->if_softc; 383 struct ifstat *ifs; 384 int error = 0, s; 385 386 s = splimp(); 387 switch(cmd) { 388 case SIOCGIFSTATUS: 389 ifs = (struct ifstat *)data; 390 if (tp->tun_pid) 391 sprintf(ifs->ascii + strlen(ifs->ascii), 392 "\tOpened by PID %d\n", tp->tun_pid); 393 break; 394 case SIOCSIFADDR: 395 error = tuninit(ifp); 396 TUNDEBUG("%s%d: address set, error=%d\n", 397 ifp->if_name, ifp->if_unit, error); 398 break; 399 case SIOCSIFDSTADDR: 400 error = tuninit(ifp); 401 TUNDEBUG("%s%d: destination address set, error=%d\n", 402 ifp->if_name, ifp->if_unit, error); 403 break; 404 case SIOCSIFMTU: 405 ifp->if_mtu = ifr->ifr_mtu; 406 TUNDEBUG("%s%d: mtu set\n", ifp->if_name, ifp->if_unit); 407 break; 408 case SIOCSIFFLAGS: 409 case SIOCADDMULTI: 410 case SIOCDELMULTI: 411 break; 412 default: 413 error = EINVAL; 414 } 415 splx(s); 416 return (error); 417} 418 419/* 420 * tunoutput - queue packets from higher level ready to put out. 421 */ 422static int 423tunoutput( 424 struct ifnet *ifp, 425 struct mbuf *m0, 426 struct sockaddr *dst, 427 struct rtentry *rt) 428{ 429 struct tun_softc *tp = ifp->if_softc; 430#ifdef MAC 431 int error; 432#endif 433 434 TUNDEBUG ("%s%d: tunoutput\n", ifp->if_name, ifp->if_unit); 435 436#ifdef MAC 437 error = mac_check_ifnet_transmit(ifp, m0); 438 if (error) { 439 m_freem(m0); 440 return (error); 441 } 442#endif 443 444 if ((tp->tun_flags & TUN_READY) != TUN_READY) { 445 TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name, 446 ifp->if_unit, tp->tun_flags); 447 m_freem (m0); 448 return (EHOSTDOWN); 449 } 450 451 if ((ifp->if_flags & IFF_UP) != IFF_UP) { 452 m_freem (m0); 453 return (EHOSTDOWN); 454 } 455 456 /* BPF write needs to be handled specially */ 457 if (dst->sa_family == AF_UNSPEC) { 458 dst->sa_family = *(mtod(m0, int *)); 459 m0->m_len -= sizeof(int); 460 m0->m_pkthdr.len -= sizeof(int); 461 m0->m_data += sizeof(int); 462 } 463 464 if (ifp->if_bpf) { 465 /* 466 * We need to prepend the address family as 467 * a four byte field. Cons up a dummy header 468 * to pacify bpf. This is safe because bpf 469 * will only read from the mbuf (i.e., it won't 470 * try to free it or keep a pointer to it). 471 */ 472 struct mbuf m; 473 uint32_t af = dst->sa_family; 474 475 m.m_next = m0; 476 m.m_len = 4; 477 m.m_data = (char *)⁡ 478 479 BPF_MTAP(ifp, &m); 480 } 481 482 /* prepend sockaddr? this may abort if the mbuf allocation fails */ 483 if (tp->tun_flags & TUN_LMODE) { 484 /* allocate space for sockaddr */ 485 M_PREPEND(m0, dst->sa_len, M_DONTWAIT); 486 487 /* if allocation failed drop packet */ 488 if (m0 == NULL) { 489 ifp->if_iqdrops++; 490 ifp->if_oerrors++; 491 return (ENOBUFS); 492 } else { 493 bcopy(dst, m0->m_data, dst->sa_len); 494 } 495 } 496 497 if (tp->tun_flags & TUN_IFHEAD) { 498 /* Prepend the address family */ 499 M_PREPEND(m0, 4, M_DONTWAIT); 500 501 /* if allocation failed drop packet */ 502 if (m0 == NULL) { 503 ifp->if_iqdrops++; 504 ifp->if_oerrors++; 505 return (ENOBUFS); 506 } else 507 *(u_int32_t *)m0->m_data = htonl(dst->sa_family); 508 } else { 509#ifdef INET 510 if (dst->sa_family != AF_INET) 511#endif 512 { 513 m_freem(m0); 514 return (EAFNOSUPPORT); 515 } 516 } 517 518 if (! IF_HANDOFF(&ifp->if_snd, m0, ifp)) { 519 ifp->if_collisions++; 520 return (ENOBUFS); 521 } 522 ifp->if_opackets++; 523 return (0); 524} 525 526/* 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;
| 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; 360 361 si = (struct sockaddr_in *)ifa->ifa_addr; 362 if (si->sin_addr.s_addr) 363 tp->tun_flags |= TUN_IASET; 364 365 si = (struct sockaddr_in *)ifa->ifa_dstaddr; 366 if (si && si->sin_addr.s_addr) 367 tp->tun_flags |= TUN_DSTADDR; 368 } 369#endif 370 } 371 } 372 return (error); 373} 374 375/* 376 * Process an ioctl request. 377 */ 378static int 379tunifioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 380{ 381 struct ifreq *ifr = (struct ifreq *)data; 382 struct tun_softc *tp = ifp->if_softc; 383 struct ifstat *ifs; 384 int error = 0, s; 385 386 s = splimp(); 387 switch(cmd) { 388 case SIOCGIFSTATUS: 389 ifs = (struct ifstat *)data; 390 if (tp->tun_pid) 391 sprintf(ifs->ascii + strlen(ifs->ascii), 392 "\tOpened by PID %d\n", tp->tun_pid); 393 break; 394 case SIOCSIFADDR: 395 error = tuninit(ifp); 396 TUNDEBUG("%s%d: address set, error=%d\n", 397 ifp->if_name, ifp->if_unit, error); 398 break; 399 case SIOCSIFDSTADDR: 400 error = tuninit(ifp); 401 TUNDEBUG("%s%d: destination address set, error=%d\n", 402 ifp->if_name, ifp->if_unit, error); 403 break; 404 case SIOCSIFMTU: 405 ifp->if_mtu = ifr->ifr_mtu; 406 TUNDEBUG("%s%d: mtu set\n", ifp->if_name, ifp->if_unit); 407 break; 408 case SIOCSIFFLAGS: 409 case SIOCADDMULTI: 410 case SIOCDELMULTI: 411 break; 412 default: 413 error = EINVAL; 414 } 415 splx(s); 416 return (error); 417} 418 419/* 420 * tunoutput - queue packets from higher level ready to put out. 421 */ 422static int 423tunoutput( 424 struct ifnet *ifp, 425 struct mbuf *m0, 426 struct sockaddr *dst, 427 struct rtentry *rt) 428{ 429 struct tun_softc *tp = ifp->if_softc; 430#ifdef MAC 431 int error; 432#endif 433 434 TUNDEBUG ("%s%d: tunoutput\n", ifp->if_name, ifp->if_unit); 435 436#ifdef MAC 437 error = mac_check_ifnet_transmit(ifp, m0); 438 if (error) { 439 m_freem(m0); 440 return (error); 441 } 442#endif 443 444 if ((tp->tun_flags & TUN_READY) != TUN_READY) { 445 TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name, 446 ifp->if_unit, tp->tun_flags); 447 m_freem (m0); 448 return (EHOSTDOWN); 449 } 450 451 if ((ifp->if_flags & IFF_UP) != IFF_UP) { 452 m_freem (m0); 453 return (EHOSTDOWN); 454 } 455 456 /* BPF write needs to be handled specially */ 457 if (dst->sa_family == AF_UNSPEC) { 458 dst->sa_family = *(mtod(m0, int *)); 459 m0->m_len -= sizeof(int); 460 m0->m_pkthdr.len -= sizeof(int); 461 m0->m_data += sizeof(int); 462 } 463 464 if (ifp->if_bpf) { 465 /* 466 * We need to prepend the address family as 467 * a four byte field. Cons up a dummy header 468 * to pacify bpf. This is safe because bpf 469 * will only read from the mbuf (i.e., it won't 470 * try to free it or keep a pointer to it). 471 */ 472 struct mbuf m; 473 uint32_t af = dst->sa_family; 474 475 m.m_next = m0; 476 m.m_len = 4; 477 m.m_data = (char *)⁡ 478 479 BPF_MTAP(ifp, &m); 480 } 481 482 /* prepend sockaddr? this may abort if the mbuf allocation fails */ 483 if (tp->tun_flags & TUN_LMODE) { 484 /* allocate space for sockaddr */ 485 M_PREPEND(m0, dst->sa_len, M_DONTWAIT); 486 487 /* if allocation failed drop packet */ 488 if (m0 == NULL) { 489 ifp->if_iqdrops++; 490 ifp->if_oerrors++; 491 return (ENOBUFS); 492 } else { 493 bcopy(dst, m0->m_data, dst->sa_len); 494 } 495 } 496 497 if (tp->tun_flags & TUN_IFHEAD) { 498 /* Prepend the address family */ 499 M_PREPEND(m0, 4, M_DONTWAIT); 500 501 /* if allocation failed drop packet */ 502 if (m0 == NULL) { 503 ifp->if_iqdrops++; 504 ifp->if_oerrors++; 505 return (ENOBUFS); 506 } else 507 *(u_int32_t *)m0->m_data = htonl(dst->sa_family); 508 } else { 509#ifdef INET 510 if (dst->sa_family != AF_INET) 511#endif 512 { 513 m_freem(m0); 514 return (EAFNOSUPPORT); 515 } 516 } 517 518 if (! IF_HANDOFF(&ifp->if_snd, m0, ifp)) { 519 ifp->if_collisions++; 520 return (ENOBUFS); 521 } 522 ifp->if_opackets++; 523 return (0); 524} 525 526/* 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;
| 535 struct tuninfo *tunp;
|
536 537 switch (cmd) {
| 536 537 switch (cmd) {
|
538 case TUNSIFINFO: 539 tunp = (struct tuninfo *)data;
| 538 case TUNSIFINFO: 539 tunp = (struct tuninfo *)data;
|
540 if (tunp->mtu < IF_MINMTU) 541 return (EINVAL);
| 540 if (tunp->mtu < IF_MINMTU) 541 return (EINVAL);
|
542 if (tp->tun_if.if_mtu != tunp->mtu
| 542 if (tp->tun_if.if_mtu != tunp->mtu
|
543 && (error = suser(td)) != 0) 544 return (error);
| 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;
| 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;
| 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
| 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) 581 return(EBUSY); 582 583 switch (*(int *)data & ~IFF_MULTICAST) { 584 case IFF_POINTOPOINT: 585 case IFF_BROADCAST: 586 tp->tun_if.if_flags &= 587 ~(IFF_BROADCAST|IFF_POINTOPOINT|IFF_MULTICAST); 588 tp->tun_if.if_flags |= *(int *)data; 589 break; 590 default: 591 return(EINVAL); 592 } 593 break; 594 case TUNSIFPID: 595 tp->tun_pid = curthread->td_proc->p_pid; 596 break; 597 case FIONBIO: 598 break; 599 case FIOASYNC: 600 if (*(int *)data) 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;
| 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) 581 return(EBUSY); 582 583 switch (*(int *)data & ~IFF_MULTICAST) { 584 case IFF_POINTOPOINT: 585 case IFF_BROADCAST: 586 tp->tun_if.if_flags &= 587 ~(IFF_BROADCAST|IFF_POINTOPOINT|IFF_MULTICAST); 588 tp->tun_if.if_flags |= *(int *)data; 589 break; 590 default: 591 return(EINVAL); 592 } 593 break; 594 case TUNSIFPID: 595 tp->tun_pid = curthread->td_proc->p_pid; 596 break; 597 case FIONBIO: 598 break; 599 case FIOASYNC: 600 if (*(int *)data) 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)
| 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 618 case FIOGETOWN: 619 *(int *)data = fgetown(&tp->tun_sigio); 620 return (0); 621 622 /* This is deprecated, FIOSETOWN should be used instead. */ 623 case TIOCSPGRP: 624 return (fsetown(-(*(int *)data), &tp->tun_sigio)); 625 626 /* This is deprecated, FIOGETOWN should be used instead. */ 627 case TIOCGPGRP: 628 *(int *)data = -fgetown(&tp->tun_sigio); 629 return (0); 630 631 default: 632 return (ENOTTY); 633 } 634 return (0); 635} 636 637/* 638 * The cdevsw read interface - reads a packet at a time, or at 639 * least as much of a packet as can be read. 640 */ 641static int 642tunread(dev_t dev, struct uio *uio, int flag) 643{ 644 struct tun_softc *tp = dev->si_drv1; 645 struct ifnet *ifp = &tp->tun_if; 646 struct mbuf *m; 647 int error=0, len, s; 648 649 TUNDEBUG ("%s%d: read\n", ifp->if_name, ifp->if_unit); 650 if ((tp->tun_flags & TUN_READY) != TUN_READY) { 651 TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name, 652 ifp->if_unit, tp->tun_flags); 653 return (EHOSTDOWN); 654 } 655 656 tp->tun_flags &= ~TUN_RWAIT; 657 658 s = splimp(); 659 do { 660 IF_DEQUEUE(&ifp->if_snd, m); 661 if (m == NULL) { 662 if (flag & IO_NDELAY) { 663 splx(s); 664 return (EWOULDBLOCK); 665 } 666 tp->tun_flags |= TUN_RWAIT; 667 if((error = tsleep((caddr_t)tp, PCATCH | (PZERO + 1), 668 "tunread", 0)) != 0) { 669 splx(s); 670 return (error); 671 } 672 } 673 } while (m == NULL); 674 splx(s); 675 676 while (m && uio->uio_resid > 0 && error == 0) { 677 len = min(uio->uio_resid, m->m_len); 678 if (len != 0) 679 error = uiomove(mtod(m, void *), len, uio); 680 m = m_free(m); 681 } 682 683 if (m) { 684 TUNDEBUG("%s%d: Dropping mbuf\n", ifp->if_name, ifp->if_unit); 685 m_freem(m); 686 } 687 return (error); 688} 689 690/* 691 * the cdevsw write interface - an atomic write is a packet - or else! 692 */ 693static int 694tunwrite(dev_t dev, struct uio *uio, int flag) 695{ 696 struct tun_softc *tp = dev->si_drv1; 697 struct ifnet *ifp = &tp->tun_if; 698 struct mbuf *top, **mp, *m; 699 int error=0, tlen, mlen; 700 uint32_t family; 701 702 TUNDEBUG("%s%d: tunwrite\n", ifp->if_name, ifp->if_unit); 703 704 if ((ifp->if_flags & IFF_UP) != IFF_UP) 705 /* ignore silently */ 706 return (0); 707 708 if (uio->uio_resid == 0) 709 return (0); 710 711 if (uio->uio_resid < 0 || uio->uio_resid > TUNMRU) { 712 TUNDEBUG("%s%d: len=%d!\n", ifp->if_name, ifp->if_unit, 713 uio->uio_resid); 714 return (EIO); 715 } 716 tlen = uio->uio_resid; 717 718 /* get a header mbuf */ 719 MGETHDR(m, M_DONTWAIT, MT_DATA); 720 if (m == NULL) 721 return (ENOBUFS); 722 mlen = MHLEN; 723 724 top = 0; 725 mp = ⊤ 726 while (error == 0 && uio->uio_resid > 0) { 727 m->m_len = min(mlen, uio->uio_resid); 728 error = uiomove(mtod(m, void *), m->m_len, uio); 729 *mp = m; 730 mp = &m->m_next; 731 if (uio->uio_resid > 0) { 732 MGET (m, M_DONTWAIT, MT_DATA); 733 if (m == 0) { 734 error = ENOBUFS; 735 break; 736 } 737 mlen = MLEN; 738 } 739 } 740 if (error) { 741 if (top) 742 m_freem (top); 743 ifp->if_ierrors++; 744 return (error); 745 } 746 747 top->m_pkthdr.len = tlen; 748 top->m_pkthdr.rcvif = ifp; 749#ifdef MAC 750 mac_create_mbuf_from_ifnet(ifp, top); 751#endif 752 753 if (ifp->if_bpf) { 754 if (tp->tun_flags & TUN_IFHEAD) { 755 /* 756 * Conveniently, we already have a 4-byte address 757 * family prepended to our packet ! 758 * Inconveniently, it's in the wrong byte order ! 759 */ 760 if ((top = m_pullup(top, sizeof(family))) == NULL) 761 return (ENOBUFS); 762 *mtod(top, u_int32_t *) = 763 ntohl(*mtod(top, u_int32_t *)); 764 BPF_MTAP(ifp, top); 765 *mtod(top, u_int32_t *) = 766 htonl(*mtod(top, u_int32_t *)); 767 } else { 768 /* 769 * We need to prepend the address family as 770 * a four byte field. Cons up a dummy header 771 * to pacify bpf. This is safe because bpf 772 * will only read from the mbuf (i.e., it won't 773 * try to free it or keep a pointer to it). 774 */ 775 struct mbuf m; 776 uint32_t af = AF_INET; 777 778 m.m_next = top; 779 m.m_len = 4; 780 m.m_data = (char *)⁡ 781 782 BPF_MTAP(ifp, &m); 783 } 784 } 785 786 if (tp->tun_flags & TUN_IFHEAD) { 787 if (top->m_len < sizeof(family) && 788 (top = m_pullup(top, sizeof(family))) == NULL) 789 return (ENOBUFS); 790 family = ntohl(*mtod(top, u_int32_t *)); 791 m_adj(top, sizeof(family)); 792 } else 793 family = AF_INET; 794 795 ifp->if_ibytes += top->m_pkthdr.len; 796 ifp->if_ipackets++; 797 798 return (family_enqueue(family, top)); 799} 800 801/* 802 * tunpoll - the poll interface, this is only useful on reads 803 * really. The write detect always returns true, write never blocks 804 * anyway, it either accepts the packet or drops it. 805 */ 806static int 807tunpoll(dev_t dev, int events, struct thread *td) 808{ 809 int s; 810 struct tun_softc *tp = dev->si_drv1; 811 struct ifnet *ifp = &tp->tun_if; 812 int revents = 0; 813 814 s = splimp(); 815 TUNDEBUG("%s%d: tunpoll\n", ifp->if_name, ifp->if_unit); 816 817 if (events & (POLLIN | POLLRDNORM)) { 818 if (ifp->if_snd.ifq_len > 0) { 819 TUNDEBUG("%s%d: tunpoll q=%d\n", ifp->if_name, 820 ifp->if_unit, ifp->if_snd.ifq_len); 821 revents |= events & (POLLIN | POLLRDNORM); 822 } else { 823 TUNDEBUG("%s%d: tunpoll waiting\n", ifp->if_name, 824 ifp->if_unit); 825 selrecord(td, &tp->tun_rsel); 826 } 827 } 828 if (events & (POLLOUT | POLLWRNORM)) 829 revents |= events & (POLLOUT | POLLWRNORM); 830 831 splx(s); 832 return (revents); 833}
| 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 618 case FIOGETOWN: 619 *(int *)data = fgetown(&tp->tun_sigio); 620 return (0); 621 622 /* This is deprecated, FIOSETOWN should be used instead. */ 623 case TIOCSPGRP: 624 return (fsetown(-(*(int *)data), &tp->tun_sigio)); 625 626 /* This is deprecated, FIOGETOWN should be used instead. */ 627 case TIOCGPGRP: 628 *(int *)data = -fgetown(&tp->tun_sigio); 629 return (0); 630 631 default: 632 return (ENOTTY); 633 } 634 return (0); 635} 636 637/* 638 * The cdevsw read interface - reads a packet at a time, or at 639 * least as much of a packet as can be read. 640 */ 641static int 642tunread(dev_t dev, struct uio *uio, int flag) 643{ 644 struct tun_softc *tp = dev->si_drv1; 645 struct ifnet *ifp = &tp->tun_if; 646 struct mbuf *m; 647 int error=0, len, s; 648 649 TUNDEBUG ("%s%d: read\n", ifp->if_name, ifp->if_unit); 650 if ((tp->tun_flags & TUN_READY) != TUN_READY) { 651 TUNDEBUG ("%s%d: not ready 0%o\n", ifp->if_name, 652 ifp->if_unit, tp->tun_flags); 653 return (EHOSTDOWN); 654 } 655 656 tp->tun_flags &= ~TUN_RWAIT; 657 658 s = splimp(); 659 do { 660 IF_DEQUEUE(&ifp->if_snd, m); 661 if (m == NULL) { 662 if (flag & IO_NDELAY) { 663 splx(s); 664 return (EWOULDBLOCK); 665 } 666 tp->tun_flags |= TUN_RWAIT; 667 if((error = tsleep((caddr_t)tp, PCATCH | (PZERO + 1), 668 "tunread", 0)) != 0) { 669 splx(s); 670 return (error); 671 } 672 } 673 } while (m == NULL); 674 splx(s); 675 676 while (m && uio->uio_resid > 0 && error == 0) { 677 len = min(uio->uio_resid, m->m_len); 678 if (len != 0) 679 error = uiomove(mtod(m, void *), len, uio); 680 m = m_free(m); 681 } 682 683 if (m) { 684 TUNDEBUG("%s%d: Dropping mbuf\n", ifp->if_name, ifp->if_unit); 685 m_freem(m); 686 } 687 return (error); 688} 689 690/* 691 * the cdevsw write interface - an atomic write is a packet - or else! 692 */ 693static int 694tunwrite(dev_t dev, struct uio *uio, int flag) 695{ 696 struct tun_softc *tp = dev->si_drv1; 697 struct ifnet *ifp = &tp->tun_if; 698 struct mbuf *top, **mp, *m; 699 int error=0, tlen, mlen; 700 uint32_t family; 701 702 TUNDEBUG("%s%d: tunwrite\n", ifp->if_name, ifp->if_unit); 703 704 if ((ifp->if_flags & IFF_UP) != IFF_UP) 705 /* ignore silently */ 706 return (0); 707 708 if (uio->uio_resid == 0) 709 return (0); 710 711 if (uio->uio_resid < 0 || uio->uio_resid > TUNMRU) { 712 TUNDEBUG("%s%d: len=%d!\n", ifp->if_name, ifp->if_unit, 713 uio->uio_resid); 714 return (EIO); 715 } 716 tlen = uio->uio_resid; 717 718 /* get a header mbuf */ 719 MGETHDR(m, M_DONTWAIT, MT_DATA); 720 if (m == NULL) 721 return (ENOBUFS); 722 mlen = MHLEN; 723 724 top = 0; 725 mp = ⊤ 726 while (error == 0 && uio->uio_resid > 0) { 727 m->m_len = min(mlen, uio->uio_resid); 728 error = uiomove(mtod(m, void *), m->m_len, uio); 729 *mp = m; 730 mp = &m->m_next; 731 if (uio->uio_resid > 0) { 732 MGET (m, M_DONTWAIT, MT_DATA); 733 if (m == 0) { 734 error = ENOBUFS; 735 break; 736 } 737 mlen = MLEN; 738 } 739 } 740 if (error) { 741 if (top) 742 m_freem (top); 743 ifp->if_ierrors++; 744 return (error); 745 } 746 747 top->m_pkthdr.len = tlen; 748 top->m_pkthdr.rcvif = ifp; 749#ifdef MAC 750 mac_create_mbuf_from_ifnet(ifp, top); 751#endif 752 753 if (ifp->if_bpf) { 754 if (tp->tun_flags & TUN_IFHEAD) { 755 /* 756 * Conveniently, we already have a 4-byte address 757 * family prepended to our packet ! 758 * Inconveniently, it's in the wrong byte order ! 759 */ 760 if ((top = m_pullup(top, sizeof(family))) == NULL) 761 return (ENOBUFS); 762 *mtod(top, u_int32_t *) = 763 ntohl(*mtod(top, u_int32_t *)); 764 BPF_MTAP(ifp, top); 765 *mtod(top, u_int32_t *) = 766 htonl(*mtod(top, u_int32_t *)); 767 } else { 768 /* 769 * We need to prepend the address family as 770 * a four byte field. Cons up a dummy header 771 * to pacify bpf. This is safe because bpf 772 * will only read from the mbuf (i.e., it won't 773 * try to free it or keep a pointer to it). 774 */ 775 struct mbuf m; 776 uint32_t af = AF_INET; 777 778 m.m_next = top; 779 m.m_len = 4; 780 m.m_data = (char *)⁡ 781 782 BPF_MTAP(ifp, &m); 783 } 784 } 785 786 if (tp->tun_flags & TUN_IFHEAD) { 787 if (top->m_len < sizeof(family) && 788 (top = m_pullup(top, sizeof(family))) == NULL) 789 return (ENOBUFS); 790 family = ntohl(*mtod(top, u_int32_t *)); 791 m_adj(top, sizeof(family)); 792 } else 793 family = AF_INET; 794 795 ifp->if_ibytes += top->m_pkthdr.len; 796 ifp->if_ipackets++; 797 798 return (family_enqueue(family, top)); 799} 800 801/* 802 * tunpoll - the poll interface, this is only useful on reads 803 * really. The write detect always returns true, write never blocks 804 * anyway, it either accepts the packet or drops it. 805 */ 806static int 807tunpoll(dev_t dev, int events, struct thread *td) 808{ 809 int s; 810 struct tun_softc *tp = dev->si_drv1; 811 struct ifnet *ifp = &tp->tun_if; 812 int revents = 0; 813 814 s = splimp(); 815 TUNDEBUG("%s%d: tunpoll\n", ifp->if_name, ifp->if_unit); 816 817 if (events & (POLLIN | POLLRDNORM)) { 818 if (ifp->if_snd.ifq_len > 0) { 819 TUNDEBUG("%s%d: tunpoll q=%d\n", ifp->if_name, 820 ifp->if_unit, ifp->if_snd.ifq_len); 821 revents |= events & (POLLIN | POLLRDNORM); 822 } else { 823 TUNDEBUG("%s%d: tunpoll waiting\n", ifp->if_name, 824 ifp->if_unit); 825 selrecord(td, &tp->tun_rsel); 826 } 827 } 828 if (events & (POLLOUT | POLLWRNORM)) 829 revents |= events & (POLLOUT | POLLWRNORM); 830 831 splx(s); 832 return (revents); 833}
|