if_tun.c revision 1.115.10.2 1 1.115.10.2 rmind /* $NetBSD: if_tun.c,v 1.115.10.2 2014/05/18 17:46:12 rmind Exp $ */
2 1.14 cgd
3 1.1 cgd /*
4 1.8 deraadt * Copyright (c) 1988, Julian Onions <jpo (at) cs.nott.ac.uk>
5 1.8 deraadt * Nottingham University 1987.
6 1.1 cgd *
7 1.1 cgd * This source may be freely distributed, however I would be interested
8 1.1 cgd * in any changes that are made.
9 1.6 deraadt *
10 1.1 cgd * This driver takes packets off the IP i/f and hands them up to a
11 1.21 scottr * user process to have its wicked way with. This driver has its
12 1.1 cgd * roots in a similar driver written by Phil Cockcroft (formerly) at
13 1.27 mycroft * UCL. This driver is based much more on read/write/poll mode of
14 1.1 cgd * operation though.
15 1.1 cgd */
16 1.48 lukem
17 1.115.10.1 rmind /*
18 1.115.10.1 rmind * tun - tunnel software network interface.
19 1.115.10.1 rmind */
20 1.115.10.1 rmind
21 1.48 lukem #include <sys/cdefs.h>
22 1.115.10.2 rmind __KERNEL_RCSID(0, "$NetBSD: if_tun.c,v 1.115.10.2 2014/05/18 17:46:12 rmind Exp $");
23 1.33 jonathan
24 1.33 jonathan #include "opt_inet.h"
25 1.8 deraadt
26 1.6 deraadt #include <sys/param.h>
27 1.115.10.1 rmind
28 1.6 deraadt #include <sys/systm.h>
29 1.6 deraadt #include <sys/mbuf.h>
30 1.6 deraadt #include <sys/protosw.h>
31 1.6 deraadt #include <sys/socket.h>
32 1.6 deraadt #include <sys/ioctl.h>
33 1.6 deraadt #include <sys/select.h>
34 1.27 mycroft #include <sys/poll.h>
35 1.8 deraadt #include <sys/file.h>
36 1.22 christos #include <sys/signalvar.h>
37 1.23 christos #include <sys/conf.h>
38 1.89 elad #include <sys/kauth.h>
39 1.115.10.1 rmind #include <sys/lwp.h>
40 1.115.10.1 rmind #include <sys/kmem.h>
41 1.115 rmind #include <sys/mutex.h>
42 1.6 deraadt
43 1.6 deraadt #include <net/if.h>
44 1.69 tron #include <net/if_types.h>
45 1.6 deraadt #include <net/netisr.h>
46 1.6 deraadt #include <net/route.h>
47 1.1 cgd
48 1.1 cgd #ifdef INET
49 1.6 deraadt #include <netinet/in.h>
50 1.6 deraadt #include <netinet/in_systm.h>
51 1.6 deraadt #include <netinet/in_var.h>
52 1.6 deraadt #include <netinet/ip.h>
53 1.30 is #include <netinet/if_inarp.h>
54 1.1 cgd #endif
55 1.1 cgd
56 1.8 deraadt #include <net/bpf.h>
57 1.8 deraadt
58 1.8 deraadt #include <net/if_tun.h>
59 1.8 deraadt
60 1.115.10.1 rmind /* Tunnel structure. */
61 1.115.10.1 rmind typedef struct tun_softc {
62 1.115.10.1 rmind LIST_ENTRY(tun_softc) tun_list; /* list of all tuns */
63 1.115.10.1 rmind kmutex_t tun_lock; /* lock for this tunnel */
64 1.115.10.1 rmind kcondvar_t tun_cv; /* condition variable for tunnel */
65 1.115.10.1 rmind ifnet_t tun_if; /* the interface */
66 1.115.10.1 rmind u_short tun_flags; /* misc flags */
67 1.115.10.1 rmind pid_t tun_pgid; /* PID or process group ID */
68 1.115.10.1 rmind struct selinfo tun_rsel; /* read select */
69 1.115.10.1 rmind struct selinfo tun_wsel; /* write select (not used) */
70 1.115.10.1 rmind int tun_unit; /* the tunnel unit number */
71 1.115.10.1 rmind void * tun_osih; /* soft interrupt handle */
72 1.115.10.1 rmind void * tun_isih; /* soft interrupt handle */
73 1.115.10.1 rmind } tun_softc_t;
74 1.115.10.1 rmind
75 1.115.10.1 rmind /* Flags. */
76 1.115.10.1 rmind #define TUN_OPEN 0x0001
77 1.115.10.1 rmind #define TUN_INITED 0x0002
78 1.115.10.1 rmind #define TUN_RCOLL 0x0004
79 1.115.10.1 rmind #define TUN_IASET 0x0008
80 1.115.10.1 rmind #define TUN_DSTADDR 0x0010
81 1.115.10.1 rmind #define TUN_RWAIT 0x0040
82 1.115.10.1 rmind #define TUN_ASYNC 0x0080
83 1.115.10.1 rmind #define TUN_NBIO 0x0100
84 1.115.10.1 rmind #define TUN_PREPADDR 0x0200
85 1.115.10.1 rmind #define TUN_IFHEAD 0x0400
86 1.115.10.1 rmind #define TUN_READY (TUN_OPEN | TUN_INITED | TUN_IASET)
87 1.115.10.1 rmind
88 1.115.10.1 rmind static LIST_HEAD(, tun_softc) tun_softc_list;
89 1.115.10.1 rmind static LIST_HEAD(, tun_softc) tunz_softc_list;
90 1.115.10.1 rmind static kmutex_t tun_softc_lock;
91 1.115.10.1 rmind
92 1.29 christos #define TUNDEBUG if (tundebug) printf
93 1.6 deraadt int tundebug = 0;
94 1.1 cgd
95 1.6 deraadt extern int ifqmaxlen;
96 1.78 thorpej
97 1.115.10.2 rmind static LIST_HEAD(, tun_softc) tun_softc_list;
98 1.115.10.2 rmind static LIST_HEAD(, tun_softc) tunz_softc_list;
99 1.115.10.2 rmind static kmutex_t tun_softc_lock;
100 1.115.10.2 rmind
101 1.115.10.2 rmind static int tun_ioctl(struct ifnet *, u_long, void *);
102 1.115.10.2 rmind static int tun_output(struct ifnet *, struct mbuf *,
103 1.115.10.2 rmind const struct sockaddr *, struct rtentry *rt);
104 1.78 thorpej static int tun_clone_create(struct if_clone *, int);
105 1.115.10.1 rmind static int tun_clone_destroy(ifnet_t *);
106 1.6 deraadt
107 1.115.10.1 rmind static void tunattach0(tun_softc_t *);
108 1.115.10.1 rmind static void tuninit(tun_softc_t *);
109 1.115.10.1 rmind static void tun_i_softintr(void *);
110 1.115.10.1 rmind static void tun_o_softintr(void *);
111 1.50 itojun #ifdef ALTQ
112 1.115.10.1 rmind static void tunstart(ifnet_t *);
113 1.50 itojun #endif
114 1.115.10.1 rmind static tun_softc_t *tun_find_unit(dev_t);
115 1.115.10.1 rmind static tun_softc_t *tun_find_zunit(int);
116 1.53 gehenna
117 1.78 thorpej static dev_type_open(tunopen);
118 1.78 thorpej static dev_type_close(tunclose);
119 1.78 thorpej static dev_type_read(tunread);
120 1.78 thorpej static dev_type_write(tunwrite);
121 1.78 thorpej static dev_type_ioctl(tunioctl);
122 1.78 thorpej static dev_type_poll(tunpoll);
123 1.78 thorpej static dev_type_kqfilter(tunkqfilter);
124 1.53 gehenna
125 1.115.10.1 rmind static struct if_clone tun_cloner =
126 1.115.10.1 rmind IF_CLONE_INITIALIZER("tun", tun_clone_create, tun_clone_destroy);
127 1.115.10.1 rmind
128 1.53 gehenna const struct cdevsw tun_cdevsw = {
129 1.115.10.2 rmind .d_open = tunopen,
130 1.115.10.2 rmind .d_close = tunclose,
131 1.115.10.2 rmind .d_read = tunread,
132 1.115.10.2 rmind .d_write = tunwrite,
133 1.115.10.2 rmind .d_ioctl = tunioctl,
134 1.115.10.2 rmind .d_stop = nostop,
135 1.115.10.2 rmind .d_tty = notty,
136 1.115.10.2 rmind .d_poll = tunpoll,
137 1.115.10.2 rmind .d_mmap = nommap,
138 1.115.10.2 rmind .d_kqfilter = tunkqfilter,
139 1.115.10.2 rmind .d_flag = D_OTHER | D_MPSAFE
140 1.53 gehenna };
141 1.6 deraadt
142 1.8 deraadt void
143 1.94 christos tunattach(int unused)
144 1.8 deraadt {
145 1.115.10.1 rmind mutex_init(&tun_softc_lock, MUTEX_DEFAULT, IPL_NET);
146 1.46 atatat LIST_INIT(&tun_softc_list);
147 1.70 pk LIST_INIT(&tunz_softc_list);
148 1.46 atatat if_clone_attach(&tun_cloner);
149 1.46 atatat }
150 1.46 atatat
151 1.70 pk /*
152 1.115.10.1 rmind * tun_find_unit: find driver instance from dev_t.
153 1.115.10.1 rmind *
154 1.115.10.1 rmind * => Returns tun locked, if found.
155 1.70 pk */
156 1.70 pk static struct tun_softc *
157 1.78 thorpej tun_find_unit(dev_t dev)
158 1.70 pk {
159 1.115.10.1 rmind tun_softc_t *tp;
160 1.70 pk int unit = minor(dev);
161 1.70 pk
162 1.115.10.1 rmind mutex_enter(&tun_softc_lock);
163 1.115.10.1 rmind LIST_FOREACH(tp, &tun_softc_list, tun_list) {
164 1.115.10.1 rmind if (unit == tp->tun_unit) {
165 1.115.10.1 rmind mutex_enter(&tp->tun_lock);
166 1.70 pk break;
167 1.115.10.1 rmind }
168 1.115.10.1 rmind }
169 1.115.10.1 rmind mutex_exit(&tun_softc_lock);
170 1.115.10.1 rmind return tp;
171 1.70 pk }
172 1.70 pk
173 1.70 pk /*
174 1.115.10.1 rmind * tun_find_zunit: find zombie driver instance by unit number.
175 1.70 pk */
176 1.70 pk static struct tun_softc *
177 1.78 thorpej tun_find_zunit(int unit)
178 1.70 pk {
179 1.115.10.1 rmind tun_softc_t *tp;
180 1.70 pk
181 1.115.10.1 rmind mutex_enter(&tun_softc_lock);
182 1.115.10.1 rmind LIST_FOREACH(tp, &tunz_softc_list, tun_list) {
183 1.115.10.1 rmind if (unit == tp->tun_unit) {
184 1.115.10.1 rmind LIST_REMOVE(tp, tun_list);
185 1.70 pk break;
186 1.115.10.1 rmind }
187 1.115.10.1 rmind }
188 1.115.10.1 rmind mutex_exit(&tun_softc_lock);
189 1.70 pk
190 1.115.10.1 rmind KASSERT(!tp || (tp->tun_flags & (TUN_INITED|TUN_OPEN)) != TUN_OPEN);
191 1.115.10.1 rmind return tp;
192 1.70 pk }
193 1.70 pk
194 1.78 thorpej static int
195 1.78 thorpej tun_clone_create(struct if_clone *ifc, int unit)
196 1.46 atatat {
197 1.115.10.1 rmind tun_softc_t *tp;
198 1.46 atatat
199 1.70 pk if ((tp = tun_find_zunit(unit)) == NULL) {
200 1.115.10.1 rmind tp = kmem_zalloc(sizeof(*tp), KM_SLEEP);
201 1.46 atatat
202 1.70 pk tp->tun_unit = unit;
203 1.115 rmind mutex_init(&tp->tun_lock, MUTEX_DEFAULT, IPL_NET);
204 1.115.10.1 rmind cv_init(&tp->tun_cv, "tunread");
205 1.104 rmind selinit(&tp->tun_rsel);
206 1.104 rmind selinit(&tp->tun_wsel);
207 1.70 pk } else {
208 1.115.10.1 rmind /* Revive tunnel instance; clear ifp part. */
209 1.115.10.1 rmind memset(&tp->tun_if, 0, sizeof(ifnet_t));
210 1.70 pk }
211 1.46 atatat
212 1.107 christos if_initname(&tp->tun_if, ifc->ifc_name, unit);
213 1.70 pk tunattach0(tp);
214 1.70 pk tp->tun_flags |= TUN_INITED;
215 1.106 ad tp->tun_osih = softint_establish(SOFTINT_CLOCK, tun_o_softintr, tp);
216 1.106 ad tp->tun_isih = softint_establish(SOFTINT_CLOCK, tun_i_softintr, tp);
217 1.46 atatat
218 1.115.10.1 rmind mutex_enter(&tun_softc_lock);
219 1.70 pk LIST_INSERT_HEAD(&tun_softc_list, tp, tun_list);
220 1.115.10.1 rmind mutex_exit(&tun_softc_lock);
221 1.46 atatat
222 1.115.10.1 rmind return 0;
223 1.46 atatat }
224 1.46 atatat
225 1.78 thorpej static void
226 1.115.10.1 rmind tunattach0(tun_softc_t *tp)
227 1.46 atatat {
228 1.115.10.1 rmind ifnet_t *ifp;
229 1.46 atatat
230 1.70 pk ifp = &tp->tun_if;
231 1.70 pk ifp->if_softc = tp;
232 1.46 atatat ifp->if_mtu = TUNMTU;
233 1.46 atatat ifp->if_ioctl = tun_ioctl;
234 1.46 atatat ifp->if_output = tun_output;
235 1.50 itojun #ifdef ALTQ
236 1.50 itojun ifp->if_start = tunstart;
237 1.50 itojun #endif
238 1.46 atatat ifp->if_flags = IFF_POINTOPOINT;
239 1.69 tron ifp->if_type = IFT_TUNNEL;
240 1.46 atatat ifp->if_snd.ifq_maxlen = ifqmaxlen;
241 1.46 atatat ifp->if_collisions = 0;
242 1.46 atatat ifp->if_ierrors = 0;
243 1.46 atatat ifp->if_oerrors = 0;
244 1.46 atatat ifp->if_ipackets = 0;
245 1.46 atatat ifp->if_opackets = 0;
246 1.58 jdolecek ifp->if_ibytes = 0;
247 1.58 jdolecek ifp->if_obytes = 0;
248 1.46 atatat ifp->if_dlt = DLT_NULL;
249 1.50 itojun IFQ_SET_READY(&ifp->if_snd);
250 1.46 atatat if_attach(ifp);
251 1.46 atatat if_alloc_sadl(ifp);
252 1.113 joerg bpf_attach(ifp, DLT_NULL, sizeof(uint32_t));
253 1.46 atatat }
254 1.46 atatat
255 1.78 thorpej static int
256 1.115.10.1 rmind tun_clone_destroy(ifnet_t *ifp)
257 1.46 atatat {
258 1.115.10.1 rmind tun_softc_t *tp = (void *)ifp;
259 1.115.10.1 rmind bool zombie = false;
260 1.8 deraadt
261 1.115 rmind IF_PURGE(&ifp->if_snd);
262 1.115 rmind ifp->if_flags &= ~IFF_RUNNING;
263 1.115 rmind
264 1.115.10.1 rmind mutex_enter(&tun_softc_lock);
265 1.115 rmind mutex_enter(&tp->tun_lock);
266 1.46 atatat LIST_REMOVE(tp, tun_list);
267 1.70 pk if (tp->tun_flags & TUN_OPEN) {
268 1.115.10.1 rmind /* Hang on to storage until last close. */
269 1.70 pk tp->tun_flags &= ~TUN_INITED;
270 1.70 pk LIST_INSERT_HEAD(&tunz_softc_list, tp, tun_list);
271 1.115.10.1 rmind zombie = true;
272 1.70 pk }
273 1.115.10.1 rmind mutex_exit(&tun_softc_lock);
274 1.46 atatat
275 1.46 atatat if (tp->tun_flags & TUN_RWAIT) {
276 1.46 atatat tp->tun_flags &= ~TUN_RWAIT;
277 1.115.10.1 rmind cv_broadcast(&tp->tun_cv);
278 1.46 atatat }
279 1.104 rmind selnotify(&tp->tun_rsel, 0, 0);
280 1.115 rmind mutex_exit(&tp->tun_lock);
281 1.70 pk
282 1.115.10.1 rmind if (tp->tun_flags & TUN_ASYNC && tp->tun_pgid) {
283 1.106 ad fownsignal(tp->tun_pgid, SIGIO, POLL_HUP, 0, NULL);
284 1.115.10.1 rmind }
285 1.106 ad
286 1.113 joerg bpf_detach(ifp);
287 1.46 atatat if_detach(ifp);
288 1.46 atatat
289 1.104 rmind if (!zombie) {
290 1.104 rmind seldestroy(&tp->tun_rsel);
291 1.104 rmind seldestroy(&tp->tun_wsel);
292 1.106 ad softint_disestablish(tp->tun_osih);
293 1.106 ad softint_disestablish(tp->tun_isih);
294 1.115 rmind mutex_destroy(&tp->tun_lock);
295 1.115.10.1 rmind kmem_free(tp, sizeof(*tp));
296 1.104 rmind }
297 1.115.10.1 rmind return 0;
298 1.8 deraadt }
299 1.8 deraadt
300 1.6 deraadt /*
301 1.115.10.1 rmind * tunopen: tunnel open (must be superuser & the device must be configured).
302 1.6 deraadt */
303 1.78 thorpej static int
304 1.115.10.1 rmind tunopen(dev_t dev, int flag, int mode, lwp_t *l)
305 1.6 deraadt {
306 1.115.10.1 rmind ifnet_t *ifp;
307 1.115.10.1 rmind tun_softc_t *tp;
308 1.115.10.1 rmind int error;
309 1.1 cgd
310 1.111 elad error = kauth_authorize_network(l->l_cred, KAUTH_NETWORK_INTERFACE_TUN,
311 1.111 elad KAUTH_REQ_NETWORK_INTERFACE_TUN_ADD, NULL, NULL, NULL);
312 1.111 elad if (error)
313 1.115.10.1 rmind return error;
314 1.5 deraadt
315 1.115.10.1 rmind if ((tp = tun_find_unit(dev)) == NULL) {
316 1.52 atatat (void)tun_clone_create(&tun_cloner, minor(dev));
317 1.52 atatat tp = tun_find_unit(dev);
318 1.70 pk if (tp == NULL) {
319 1.115.10.1 rmind return ENXIO;
320 1.70 pk }
321 1.52 atatat }
322 1.46 atatat if (tp->tun_flags & TUN_OPEN) {
323 1.115.10.1 rmind mutex_exit(&tp->tun_lock);
324 1.115.10.1 rmind return EBUSY;
325 1.46 atatat }
326 1.6 deraadt ifp = &tp->tun_if;
327 1.6 deraadt tp->tun_flags |= TUN_OPEN;
328 1.115 rmind mutex_exit(&tp->tun_lock);
329 1.115.10.1 rmind
330 1.115.10.1 rmind return error;
331 1.1 cgd }
332 1.1 cgd
333 1.6 deraadt /*
334 1.115.10.1 rmind * tunclose: close the device - mark i/f down & delete routing info.
335 1.6 deraadt */
336 1.6 deraadt int
337 1.115.10.1 rmind tunclose(dev_t dev, int flag, int mode, lwp_t *l)
338 1.6 deraadt {
339 1.115.10.1 rmind tun_softc_t *tp;
340 1.115.10.1 rmind ifnet_t *ifp;
341 1.6 deraadt
342 1.115.10.1 rmind tp = tun_find_zunit(minor(dev));
343 1.115.10.1 rmind if (tp) {
344 1.115.10.1 rmind /* Interface was "destroyed" before the close. */
345 1.104 rmind seldestroy(&tp->tun_rsel);
346 1.104 rmind seldestroy(&tp->tun_wsel);
347 1.106 ad softint_disestablish(tp->tun_osih);
348 1.106 ad softint_disestablish(tp->tun_isih);
349 1.115 rmind mutex_destroy(&tp->tun_lock);
350 1.115.10.1 rmind kmem_free(tp, sizeof(*tp));
351 1.115.10.1 rmind return 0;
352 1.70 pk }
353 1.46 atatat
354 1.115.10.1 rmind tp = tun_find_unit(dev);
355 1.115.10.1 rmind if (tp == NULL) {
356 1.115.10.1 rmind return 0;
357 1.115.10.1 rmind }
358 1.46 atatat ifp = &tp->tun_if;
359 1.10 andrew tp->tun_flags &= ~TUN_OPEN;
360 1.115 rmind tp->tun_pgid = 0;
361 1.115 rmind selnotify(&tp->tun_rsel, 0, 0);
362 1.115 rmind mutex_exit(&tp->tun_lock);
363 1.115 rmind
364 1.115.10.1 rmind /* Junk all pending output. */
365 1.50 itojun IFQ_PURGE(&ifp->if_snd);
366 1.6 deraadt
367 1.6 deraadt if (ifp->if_flags & IFF_UP) {
368 1.6 deraadt if_down(ifp);
369 1.8 deraadt if (ifp->if_flags & IFF_RUNNING) {
370 1.115.10.1 rmind /* Find internet addresses and delete routes. */
371 1.39 augustss struct ifaddr *ifa;
372 1.76 matt IFADDR_FOREACH(ifa, ifp) {
373 1.80 rpaulo #if defined(INET) || defined(INET6)
374 1.115.10.1 rmind if (ifa->ifa_addr->sa_family != AF_INET &&
375 1.115.10.1 rmind ifa->ifa_addr->sa_family != AF_INET6) {
376 1.115.10.1 rmind continue;
377 1.18 mycroft }
378 1.115.10.1 rmind rtinit(ifa, (int)RTM_DELETE,
379 1.115.10.1 rmind tp->tun_flags & TUN_DSTADDR ? RTF_HOST : 0);
380 1.38 itojun #endif
381 1.11 deraadt }
382 1.8 deraadt }
383 1.6 deraadt }
384 1.115.10.1 rmind return 0;
385 1.1 cgd }
386 1.1 cgd
387 1.26 pk static void
388 1.115.10.1 rmind tuninit(tun_softc_t *tp)
389 1.6 deraadt {
390 1.115.10.1 rmind ifnet_t *ifp = &tp->tun_if;
391 1.115.10.1 rmind struct ifaddr *ifa;
392 1.6 deraadt
393 1.115 rmind mutex_enter(&tp->tun_lock);
394 1.6 deraadt ifp->if_flags |= IFF_UP | IFF_RUNNING;
395 1.26 pk tp->tun_flags &= ~(TUN_IASET|TUN_DSTADDR);
396 1.76 matt IFADDR_FOREACH(ifa, ifp) {
397 1.38 itojun #ifdef INET
398 1.11 deraadt if (ifa->ifa_addr->sa_family == AF_INET) {
399 1.17 mycroft struct sockaddr_in *sin;
400 1.11 deraadt
401 1.17 mycroft sin = satosin(ifa->ifa_addr);
402 1.17 mycroft if (sin && sin->sin_addr.s_addr)
403 1.17 mycroft tp->tun_flags |= TUN_IASET;
404 1.17 mycroft
405 1.26 pk if (ifp->if_flags & IFF_POINTOPOINT) {
406 1.26 pk sin = satosin(ifa->ifa_dstaddr);
407 1.26 pk if (sin && sin->sin_addr.s_addr)
408 1.26 pk tp->tun_flags |= TUN_DSTADDR;
409 1.26 pk }
410 1.11 deraadt }
411 1.38 itojun #endif
412 1.80 rpaulo #ifdef INET6
413 1.80 rpaulo if (ifa->ifa_addr->sa_family == AF_INET6) {
414 1.80 rpaulo struct sockaddr_in6 *sin;
415 1.80 rpaulo
416 1.80 rpaulo sin = (struct sockaddr_in6 *)ifa->ifa_addr;
417 1.80 rpaulo if (!IN6_IS_ADDR_UNSPECIFIED(&sin->sin6_addr))
418 1.80 rpaulo tp->tun_flags |= TUN_IASET;
419 1.80 rpaulo
420 1.80 rpaulo if (ifp->if_flags & IFF_POINTOPOINT) {
421 1.80 rpaulo sin = (struct sockaddr_in6 *)ifa->ifa_dstaddr;
422 1.80 rpaulo if (sin &&
423 1.80 rpaulo !IN6_IS_ADDR_UNSPECIFIED(&sin->sin6_addr))
424 1.80 rpaulo tp->tun_flags |= TUN_DSTADDR;
425 1.80 rpaulo } else
426 1.80 rpaulo tp->tun_flags &= ~TUN_DSTADDR;
427 1.80 rpaulo }
428 1.80 rpaulo #endif /* INET6 */
429 1.18 mycroft }
430 1.115 rmind mutex_exit(&tp->tun_lock);
431 1.1 cgd }
432 1.1 cgd
433 1.1 cgd /*
434 1.1 cgd * Process an ioctl request.
435 1.1 cgd */
436 1.78 thorpej static int
437 1.115.10.1 rmind tun_ioctl(ifnet_t *ifp, u_long cmd, void *data)
438 1.6 deraadt {
439 1.115.10.1 rmind tun_softc_t *tp = ifp->if_softc;
440 1.102 dyoung struct ifreq *ifr = data;
441 1.115.10.1 rmind int error = 0;
442 1.6 deraadt
443 1.61 itojun switch (cmd) {
444 1.108 dyoung case SIOCINITIFADDR:
445 1.70 pk tuninit(tp);
446 1.6 deraadt break;
447 1.26 pk case SIOCSIFBRDADDR:
448 1.26 pk break;
449 1.102 dyoung case SIOCSIFMTU:
450 1.31 matt if (ifr->ifr_mtu > TUNMTU || ifr->ifr_mtu < 576) {
451 1.102 dyoung error = EINVAL;
452 1.102 dyoung break;
453 1.31 matt }
454 1.102 dyoung if ((error = ifioctl_common(ifp, cmd, data)) == ENETRESET)
455 1.102 dyoung error = 0;
456 1.32 matt break;
457 1.32 matt case SIOCADDMULTI:
458 1.102 dyoung case SIOCDELMULTI:
459 1.102 dyoung if (ifr == NULL) {
460 1.115.10.1 rmind error = EAFNOSUPPORT; /* XXX */
461 1.32 matt break;
462 1.32 matt }
463 1.98 dyoung switch (ifreq_getaddr(cmd, ifr)->sa_family) {
464 1.32 matt #ifdef INET
465 1.32 matt case AF_INET:
466 1.32 matt break;
467 1.32 matt #endif
468 1.80 rpaulo #ifdef INET6
469 1.80 rpaulo case AF_INET6:
470 1.80 rpaulo break;
471 1.80 rpaulo #endif
472 1.32 matt default:
473 1.32 matt error = EAFNOSUPPORT;
474 1.32 matt break;
475 1.32 matt }
476 1.31 matt break;
477 1.6 deraadt default:
478 1.108 dyoung error = ifioctl_common(ifp, cmd, data);
479 1.6 deraadt }
480 1.115.10.1 rmind return error;
481 1.1 cgd }
482 1.1 cgd
483 1.1 cgd /*
484 1.22 christos * tun_output - queue packets from higher level ready to put out.
485 1.1 cgd */
486 1.78 thorpej static int
487 1.115.10.1 rmind tun_output(ifnet_t *ifp, struct mbuf *m0, const struct sockaddr *dst,
488 1.94 christos struct rtentry *rt)
489 1.6 deraadt {
490 1.115.10.1 rmind tun_softc_t *tp = ifp->if_softc;
491 1.115.10.1 rmind int error = 0;
492 1.115.10.1 rmind
493 1.50 itojun ALTQ_DECL(struct altq_pktattr pktattr;)
494 1.6 deraadt
495 1.115 rmind mutex_enter(&tp->tun_lock);
496 1.8 deraadt if ((tp->tun_flags & TUN_READY) != TUN_READY) {
497 1.70 pk error = EHOSTDOWN;
498 1.70 pk goto out;
499 1.8 deraadt }
500 1.115.10.1 rmind // XXXrmind
501 1.115.10.1 rmind mutex_exit(&tp->tun_lock);
502 1.8 deraadt
503 1.50 itojun /*
504 1.115.10.1 rmind * If the queueing discipline needs packet classification,
505 1.50 itojun * do it before prepending link headers.
506 1.50 itojun */
507 1.50 itojun IFQ_CLASSIFY(&ifp->if_snd, m0, dst->sa_family, &pktattr);
508 1.113 joerg bpf_mtap_af(ifp, dst->sa_family, m0);
509 1.8 deraadt
510 1.6 deraadt switch(dst->sa_family) {
511 1.79 rpaulo #ifdef INET6
512 1.79 rpaulo case AF_INET6:
513 1.79 rpaulo #endif
514 1.1 cgd #ifdef INET
515 1.6 deraadt case AF_INET:
516 1.79 rpaulo #endif
517 1.79 rpaulo #if defined(INET) || defined(INET6)
518 1.26 pk if (tp->tun_flags & TUN_PREPADDR) {
519 1.26 pk /* Simple link-layer header */
520 1.26 pk M_PREPEND(m0, dst->sa_len, M_DONTWAIT);
521 1.26 pk if (m0 == NULL) {
522 1.26 pk IF_DROP(&ifp->if_snd);
523 1.70 pk error = ENOBUFS;
524 1.70 pk goto out;
525 1.26 pk }
526 1.115.10.1 rmind memcpy(mtod(m0, char *), dst, dst->sa_len);
527 1.85 rpaulo }
528 1.85 rpaulo
529 1.85 rpaulo if (tp->tun_flags & TUN_IFHEAD) {
530 1.115.10.1 rmind uint32_t *af;
531 1.115.10.1 rmind
532 1.81 rpaulo /* Prepend the address family */
533 1.82 rpaulo M_PREPEND(m0, sizeof(*af), M_DONTWAIT);
534 1.80 rpaulo if (m0 == NULL) {
535 1.80 rpaulo IF_DROP(&ifp->if_snd);
536 1.80 rpaulo error = ENOBUFS;
537 1.80 rpaulo goto out;
538 1.80 rpaulo }
539 1.80 rpaulo af = mtod(m0,uint32_t *);
540 1.80 rpaulo *af = htonl(dst->sa_family);
541 1.86 rpaulo } else {
542 1.115 rmind #ifdef INET
543 1.86 rpaulo if (dst->sa_family != AF_INET)
544 1.86 rpaulo #endif
545 1.86 rpaulo {
546 1.86 rpaulo error = EAFNOSUPPORT;
547 1.86 rpaulo goto out;
548 1.86 rpaulo }
549 1.26 pk }
550 1.36 sommerfe /* FALLTHROUGH */
551 1.36 sommerfe case AF_UNSPEC:
552 1.50 itojun IFQ_ENQUEUE(&ifp->if_snd, m0, &pktattr, error);
553 1.50 itojun if (error) {
554 1.6 deraadt ifp->if_collisions++;
555 1.70 pk error = EAFNOSUPPORT;
556 1.115 rmind m0 = NULL;
557 1.70 pk goto out;
558 1.6 deraadt }
559 1.115.10.1 rmind ifp->if_obytes += m0->m_pkthdr.len;
560 1.6 deraadt ifp->if_opackets++;
561 1.6 deraadt break;
562 1.1 cgd #endif
563 1.6 deraadt default:
564 1.70 pk error = EAFNOSUPPORT;
565 1.70 pk goto out;
566 1.6 deraadt }
567 1.6 deraadt
568 1.115.10.1 rmind mutex_enter(&tp->tun_lock);
569 1.6 deraadt if (tp->tun_flags & TUN_RWAIT) {
570 1.6 deraadt tp->tun_flags &= ~TUN_RWAIT;
571 1.115.10.1 rmind cv_broadcast(&tp->tun_cv);
572 1.6 deraadt }
573 1.115.10.1 rmind if ((tp->tun_flags & TUN_ASYNC) != 0 && tp->tun_pgid) {
574 1.106 ad softint_schedule(tp->tun_isih);
575 1.115.10.1 rmind }
576 1.104 rmind selnotify(&tp->tun_rsel, 0, 0);
577 1.115 rmind mutex_exit(&tp->tun_lock);
578 1.115.10.1 rmind out:
579 1.115 rmind if (error && m0) {
580 1.115 rmind m_freem(m0);
581 1.115 rmind }
582 1.115 rmind return 0;
583 1.1 cgd }
584 1.1 cgd
585 1.106 ad static void
586 1.106 ad tun_i_softintr(void *cookie)
587 1.106 ad {
588 1.115.10.1 rmind tun_softc_t *tp = cookie;
589 1.106 ad
590 1.115.10.1 rmind if ((tp->tun_flags & TUN_ASYNC) == 0 || tp->tun_pgid == 0) {
591 1.115.10.1 rmind return;
592 1.115.10.1 rmind }
593 1.115.10.1 rmind fownsignal(tp->tun_pgid, SIGIO, POLL_IN, POLLIN | POLLRDNORM, NULL);
594 1.106 ad }
595 1.106 ad
596 1.106 ad static void
597 1.106 ad tun_o_softintr(void *cookie)
598 1.106 ad {
599 1.115.10.1 rmind tun_softc_t *tp = cookie;
600 1.106 ad
601 1.115.10.1 rmind if ((tp->tun_flags & TUN_ASYNC) == 0 || tp->tun_pgid == 0) {
602 1.115.10.1 rmind return;
603 1.115.10.1 rmind }
604 1.115.10.1 rmind fownsignal(tp->tun_pgid, SIGIO, POLL_OUT, POLLOUT | POLLWRNORM, NULL);
605 1.106 ad }
606 1.106 ad
607 1.1 cgd /*
608 1.1 cgd * the cdevsw interface is now pretty minimal.
609 1.1 cgd */
610 1.6 deraadt int
611 1.97 christos tunioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
612 1.6 deraadt {
613 1.46 atatat struct tun_softc *tp;
614 1.115.10.1 rmind int error = 0;
615 1.46 atatat
616 1.46 atatat tp = tun_find_unit(dev);
617 1.70 pk if (tp == NULL) {
618 1.115.10.1 rmind /* Interface was "destroyed" already. */
619 1.115.10.1 rmind return ENXIO;
620 1.70 pk }
621 1.6 deraadt switch (cmd) {
622 1.6 deraadt case TUNSDEBUG:
623 1.6 deraadt tundebug = *(int *)data;
624 1.6 deraadt break;
625 1.26 pk
626 1.6 deraadt case TUNGDEBUG:
627 1.6 deraadt *(int *)data = tundebug;
628 1.6 deraadt break;
629 1.26 pk
630 1.26 pk case TUNSIFMODE:
631 1.31 matt switch (*(int *)data & (IFF_POINTOPOINT|IFF_BROADCAST)) {
632 1.26 pk case IFF_POINTOPOINT:
633 1.26 pk case IFF_BROADCAST:
634 1.26 pk if (tp->tun_if.if_flags & IFF_UP) {
635 1.70 pk error = EBUSY;
636 1.70 pk goto out;
637 1.26 pk }
638 1.26 pk tp->tun_if.if_flags &=
639 1.31 matt ~(IFF_BROADCAST|IFF_POINTOPOINT|IFF_MULTICAST);
640 1.26 pk tp->tun_if.if_flags |= *(int *)data;
641 1.26 pk break;
642 1.26 pk default:
643 1.70 pk error = EINVAL;
644 1.70 pk goto out;
645 1.26 pk }
646 1.26 pk break;
647 1.26 pk
648 1.26 pk case TUNSLMODE:
649 1.87 rpaulo if (*(int *)data) {
650 1.26 pk tp->tun_flags |= TUN_PREPADDR;
651 1.87 rpaulo tp->tun_flags &= ~TUN_IFHEAD;
652 1.87 rpaulo } else
653 1.26 pk tp->tun_flags &= ~TUN_PREPADDR;
654 1.26 pk break;
655 1.26 pk
656 1.84 rpaulo case TUNSIFHEAD:
657 1.87 rpaulo if (*(int *)data) {
658 1.84 rpaulo tp->tun_flags |= TUN_IFHEAD;
659 1.88 rpaulo tp->tun_flags &= ~TUN_PREPADDR;
660 1.87 rpaulo } else
661 1.84 rpaulo tp->tun_flags &= ~TUN_IFHEAD;
662 1.84 rpaulo break;
663 1.84 rpaulo
664 1.84 rpaulo case TUNGIFHEAD:
665 1.84 rpaulo *(int *)data = (tp->tun_flags & TUN_IFHEAD);
666 1.84 rpaulo break;
667 1.84 rpaulo
668 1.6 deraadt case FIONBIO:
669 1.6 deraadt if (*(int *)data)
670 1.6 deraadt tp->tun_flags |= TUN_NBIO;
671 1.6 deraadt else
672 1.6 deraadt tp->tun_flags &= ~TUN_NBIO;
673 1.6 deraadt break;
674 1.26 pk
675 1.6 deraadt case FIOASYNC:
676 1.6 deraadt if (*(int *)data)
677 1.6 deraadt tp->tun_flags |= TUN_ASYNC;
678 1.6 deraadt else
679 1.6 deraadt tp->tun_flags &= ~TUN_ASYNC;
680 1.6 deraadt break;
681 1.26 pk
682 1.6 deraadt case FIONREAD:
683 1.6 deraadt if (tp->tun_if.if_snd.ifq_head)
684 1.19 pk *(int *)data = tp->tun_if.if_snd.ifq_head->m_pkthdr.len;
685 1.70 pk else
686 1.6 deraadt *(int *)data = 0;
687 1.6 deraadt break;
688 1.26 pk
689 1.6 deraadt case TIOCSPGRP:
690 1.64 jdolecek case FIOSETOWN:
691 1.105 ad error = fsetown(&tp->tun_pgid, cmd, data);
692 1.6 deraadt break;
693 1.26 pk
694 1.6 deraadt case TIOCGPGRP:
695 1.64 jdolecek case FIOGETOWN:
696 1.105 ad error = fgetown(tp->tun_pgid, cmd, data);
697 1.6 deraadt break;
698 1.26 pk
699 1.6 deraadt default:
700 1.70 pk error = ENOTTY;
701 1.6 deraadt }
702 1.70 pk
703 1.70 pk out:
704 1.115 rmind mutex_exit(&tp->tun_lock);
705 1.115.10.1 rmind return error;
706 1.1 cgd }
707 1.1 cgd
708 1.1 cgd /*
709 1.6 deraadt * The cdevsw read interface - reads a packet at a time, or at
710 1.6 deraadt * least as much of a packet as can be read.
711 1.1 cgd */
712 1.6 deraadt int
713 1.94 christos tunread(dev_t dev, struct uio *uio, int ioflag)
714 1.6 deraadt {
715 1.115.10.1 rmind tun_softc_t *tp;
716 1.115.10.1 rmind ifnet_t *ifp;
717 1.115.10.1 rmind struct mbuf *m;
718 1.115.10.1 rmind int error = 0, index;
719 1.46 atatat
720 1.46 atatat tp = tun_find_unit(dev);
721 1.70 pk if (tp == NULL) {
722 1.115.10.1 rmind /* Interface was "destroyed" already. */
723 1.115.10.1 rmind return ENXIO;
724 1.70 pk }
725 1.46 atatat index = tp->tun_if.if_index;
726 1.46 atatat ifp = &tp->tun_if;
727 1.6 deraadt
728 1.8 deraadt if ((tp->tun_flags & TUN_READY) != TUN_READY) {
729 1.70 pk error = EHOSTDOWN;
730 1.70 pk goto out;
731 1.8 deraadt }
732 1.6 deraadt tp->tun_flags &= ~TUN_RWAIT;
733 1.6 deraadt
734 1.6 deraadt do {
735 1.115.10.1 rmind IFQ_DEQUEUE(&ifp->if_snd, m);
736 1.115.10.1 rmind if (m != NULL) {
737 1.115.10.1 rmind break;
738 1.115.10.1 rmind }
739 1.115.10.1 rmind if (tp->tun_flags & TUN_NBIO) {
740 1.115.10.1 rmind error = EWOULDBLOCK;
741 1.115.10.1 rmind goto out;
742 1.6 deraadt }
743 1.115.10.1 rmind tp->tun_flags |= TUN_RWAIT;
744 1.115.10.1 rmind if (cv_wait_sig(&tp->tun_cv, &tp->tun_lock)) {
745 1.115.10.1 rmind mutex_exit(&tp->tun_lock);
746 1.115.10.1 rmind error = EINTR;
747 1.115.10.1 rmind goto out;
748 1.115.10.1 rmind }
749 1.115.10.1 rmind } while (m == NULL);
750 1.70 pk
751 1.115 rmind mutex_exit(&tp->tun_lock);
752 1.6 deraadt
753 1.115.10.1 rmind /* Copy the mbuf chain. */
754 1.115.10.1 rmind while (m && uio->uio_resid > 0 && error == 0) {
755 1.115.10.1 rmind size_t len = MIN(uio->uio_resid, m->m_len);
756 1.115.10.1 rmind if (len) {
757 1.115.10.1 rmind error = uiomove(mtod(m, void *), len, uio);
758 1.115.10.1 rmind }
759 1.115.10.1 rmind m = m_free(m);
760 1.6 deraadt }
761 1.115.10.1 rmind if (m) {
762 1.115.10.1 rmind m_freem(m);
763 1.6 deraadt }
764 1.115.10.1 rmind if (error) {
765 1.19 pk ifp->if_ierrors++;
766 1.115.10.1 rmind }
767 1.115.10.1 rmind return error;
768 1.70 pk
769 1.70 pk out:
770 1.115 rmind mutex_exit(&tp->tun_lock);
771 1.115.10.1 rmind return error;
772 1.1 cgd }
773 1.1 cgd
774 1.1 cgd /*
775 1.1 cgd * the cdevsw write interface - an atomic write is a packet - or else!
776 1.1 cgd */
777 1.6 deraadt int
778 1.94 christos tunwrite(dev_t dev, struct uio *uio, int ioflag)
779 1.6 deraadt {
780 1.115.10.1 rmind tun_softc_t *tp;
781 1.115.10.1 rmind ifnet_t *ifp;
782 1.115.10.1 rmind struct mbuf *top, **mp, *m;
783 1.115.10.1 rmind struct ifqueue *ifq;
784 1.115.10.1 rmind struct sockaddr dst;
785 1.115.10.1 rmind int isr, error = 0, tlen, mlen;
786 1.115.10.1 rmind uint32_t family;
787 1.6 deraadt
788 1.46 atatat tp = tun_find_unit(dev);
789 1.70 pk if (tp == NULL) {
790 1.115.10.1 rmind /* Interface was "destroyed" already. */
791 1.115.10.1 rmind return ENXIO;
792 1.70 pk }
793 1.115.10.1 rmind /* Unlock until we've got the data. */
794 1.115 rmind mutex_exit(&tp->tun_lock);
795 1.46 atatat
796 1.46 atatat ifp = &tp->tun_if;
797 1.46 atatat
798 1.26 pk if (tp->tun_flags & TUN_PREPADDR) {
799 1.46 atatat if (uio->uio_resid < sizeof(dst)) {
800 1.70 pk error = EIO;
801 1.70 pk goto out0;
802 1.46 atatat }
803 1.97 christos error = uiomove((void *)&dst, sizeof(dst), uio);
804 1.26 pk if (dst.sa_len > sizeof(dst)) {
805 1.26 pk /* Duh.. */
806 1.26 pk int n = dst.sa_len - sizeof(dst);
807 1.115.10.1 rmind while (n--) {
808 1.115.10.1 rmind char discard;
809 1.115.10.1 rmind error = uiomove(&discard, 1, uio);
810 1.115.10.1 rmind if (error) {
811 1.70 pk goto out0;
812 1.46 atatat }
813 1.115.10.1 rmind }
814 1.26 pk }
815 1.85 rpaulo } else if (tp->tun_flags & TUN_IFHEAD) {
816 1.80 rpaulo if (uio->uio_resid < sizeof(family)){
817 1.80 rpaulo error = EIO;
818 1.80 rpaulo goto out0;
819 1.80 rpaulo }
820 1.97 christos error = uiomove((void *)&family, sizeof(family), uio);
821 1.80 rpaulo dst.sa_family = ntohl(family);
822 1.85 rpaulo } else {
823 1.85 rpaulo #ifdef INET
824 1.85 rpaulo dst.sa_family = AF_INET;
825 1.85 rpaulo #endif
826 1.26 pk }
827 1.26 pk
828 1.54 simonb if (uio->uio_resid > TUNMTU) {
829 1.70 pk error = EIO;
830 1.70 pk goto out0;
831 1.6 deraadt }
832 1.26 pk
833 1.26 pk switch (dst.sa_family) {
834 1.26 pk #ifdef INET
835 1.26 pk case AF_INET:
836 1.26 pk ifq = &ipintrq;
837 1.26 pk isr = NETISR_IP;
838 1.26 pk break;
839 1.26 pk #endif
840 1.79 rpaulo #ifdef INET6
841 1.79 rpaulo case AF_INET6:
842 1.79 rpaulo ifq = &ip6intrq;
843 1.79 rpaulo isr = NETISR_IPV6;
844 1.83 rpaulo break;
845 1.79 rpaulo #endif
846 1.26 pk default:
847 1.70 pk error = EAFNOSUPPORT;
848 1.70 pk goto out0;
849 1.26 pk }
850 1.26 pk
851 1.8 deraadt tlen = uio->uio_resid;
852 1.8 deraadt
853 1.8 deraadt /* get a header mbuf */
854 1.8 deraadt MGETHDR(m, M_DONTWAIT, MT_DATA);
855 1.46 atatat if (m == NULL) {
856 1.70 pk error = ENOBUFS;
857 1.70 pk goto out0;
858 1.46 atatat }
859 1.8 deraadt mlen = MHLEN;
860 1.8 deraadt
861 1.68 tron top = NULL;
862 1.6 deraadt mp = ⊤
863 1.6 deraadt while (error == 0 && uio->uio_resid > 0) {
864 1.115.10.1 rmind m->m_len = MIN(mlen, uio->uio_resid);
865 1.97 christos error = uiomove(mtod(m, void *), m->m_len, uio);
866 1.6 deraadt *mp = m;
867 1.6 deraadt mp = &m->m_next;
868 1.68 tron if (error == 0 && uio->uio_resid > 0) {
869 1.68 tron MGET(m, M_DONTWAIT, MT_DATA);
870 1.68 tron if (m == NULL) {
871 1.8 deraadt error = ENOBUFS;
872 1.8 deraadt break;
873 1.8 deraadt }
874 1.8 deraadt mlen = MLEN;
875 1.8 deraadt }
876 1.6 deraadt }
877 1.6 deraadt if (error) {
878 1.68 tron if (top != NULL)
879 1.8 deraadt m_freem (top);
880 1.19 pk ifp->if_ierrors++;
881 1.70 pk goto out0;
882 1.6 deraadt }
883 1.6 deraadt
884 1.8 deraadt top->m_pkthdr.len = tlen;
885 1.8 deraadt top->m_pkthdr.rcvif = ifp;
886 1.8 deraadt
887 1.113 joerg bpf_mtap_af(ifp, dst.sa_family, top);
888 1.6 deraadt
889 1.115 rmind mutex_enter(&tp->tun_lock);
890 1.70 pk if ((tp->tun_flags & TUN_INITED) == 0) {
891 1.115.10.1 rmind /* Interface was destroyed. */
892 1.70 pk error = ENXIO;
893 1.70 pk goto out;
894 1.70 pk }
895 1.26 pk if (IF_QFULL(ifq)) {
896 1.26 pk IF_DROP(ifq);
897 1.6 deraadt ifp->if_collisions++;
898 1.115 rmind mutex_exit(&tp->tun_lock);
899 1.6 deraadt m_freem(top);
900 1.70 pk error = ENOBUFS;
901 1.115.10.1 rmind goto out0;
902 1.6 deraadt }
903 1.26 pk IF_ENQUEUE(ifq, top);
904 1.6 deraadt ifp->if_ipackets++;
905 1.58 jdolecek ifp->if_ibytes += tlen;
906 1.26 pk schednetisr(isr);
907 1.70 pk out:
908 1.115 rmind mutex_exit(&tp->tun_lock);
909 1.70 pk out0:
910 1.115.10.1 rmind return error;
911 1.1 cgd }
912 1.1 cgd
913 1.50 itojun #ifdef ALTQ
914 1.50 itojun /*
915 1.50 itojun * Start packet transmission on the interface.
916 1.50 itojun * when the interface queue is rate-limited by ALTQ or TBR,
917 1.50 itojun * if_start is needed to drain packets from the queue in order
918 1.50 itojun * to notify readers when outgoing packets become ready.
919 1.50 itojun */
920 1.50 itojun static void
921 1.115.10.1 rmind tunstart(ifnet_t *ifp)
922 1.50 itojun {
923 1.115.10.1 rmind tun_softc_t *tp = ifp->if_softc;
924 1.50 itojun
925 1.50 itojun if (!ALTQ_IS_ENABLED(&ifp->if_snd) && !TBR_IS_ENABLED(&ifp->if_snd))
926 1.50 itojun return;
927 1.50 itojun
928 1.115 rmind mutex_enter(&tp->tun_lock);
929 1.70 pk if (!IF_IS_EMPTY(&ifp->if_snd)) {
930 1.50 itojun if (tp->tun_flags & TUN_RWAIT) {
931 1.50 itojun tp->tun_flags &= ~TUN_RWAIT;
932 1.115.10.1 rmind cv_broadcast(&tp->tun_cv);
933 1.50 itojun }
934 1.115.10.1 rmind if (tp->tun_flags & TUN_ASYNC && tp->tun_pgid) {
935 1.106 ad softint_schedule(tp->tun_osih);
936 1.115.10.1 rmind }
937 1.104 rmind selnotify(&tp->tun_rsel, 0, 0);
938 1.50 itojun }
939 1.115 rmind mutex_exit(&tp->tun_lock);
940 1.50 itojun }
941 1.50 itojun #endif /* ALTQ */
942 1.115.10.1 rmind
943 1.1 cgd /*
944 1.27 mycroft * tunpoll - the poll interface, this is only useful on reads
945 1.6 deraadt * really. The write detect always returns true, write never blocks
946 1.6 deraadt * anyway, it either accepts the packet or drops it.
947 1.6 deraadt */
948 1.6 deraadt int
949 1.78 thorpej tunpoll(dev_t dev, int events, struct lwp *l)
950 1.6 deraadt {
951 1.115.10.1 rmind tun_softc_t *tp;
952 1.115.10.1 rmind ifnet_t *ifp;
953 1.115.10.1 rmind int revents = 0;
954 1.46 atatat
955 1.46 atatat tp = tun_find_unit(dev);
956 1.115.10.1 rmind if (tp == NULL) {
957 1.115.10.1 rmind /* Interface was "destroyed" already. */
958 1.115.10.1 rmind return 0;
959 1.115.10.1 rmind }
960 1.46 atatat ifp = &tp->tun_if;
961 1.6 deraadt
962 1.35 veego if (events & (POLLIN | POLLRDNORM)) {
963 1.70 pk if (!IFQ_IS_EMPTY(&ifp->if_snd)) {
964 1.27 mycroft revents |= events & (POLLIN | POLLRDNORM);
965 1.27 mycroft } else {
966 1.77 christos selrecord(l, &tp->tun_rsel);
967 1.6 deraadt }
968 1.35 veego }
969 1.115.10.1 rmind if (events & (POLLOUT | POLLWRNORM)) {
970 1.27 mycroft revents |= events & (POLLOUT | POLLWRNORM);
971 1.115.10.1 rmind }
972 1.115 rmind mutex_exit(&tp->tun_lock);
973 1.115.10.1 rmind
974 1.115.10.1 rmind return revents;
975 1.56 jdolecek }
976 1.56 jdolecek
977 1.56 jdolecek static void
978 1.56 jdolecek filt_tunrdetach(struct knote *kn)
979 1.56 jdolecek {
980 1.115.10.1 rmind tun_softc_t *tp = kn->kn_hook;
981 1.56 jdolecek
982 1.115.10.1 rmind mutex_enter(&tp->tun_lock);
983 1.57 christos SLIST_REMOVE(&tp->tun_rsel.sel_klist, kn, knote, kn_selnext);
984 1.115.10.1 rmind mutex_exit(&tp->tun_lock);
985 1.56 jdolecek }
986 1.56 jdolecek
987 1.56 jdolecek static int
988 1.94 christos filt_tunread(struct knote *kn, long hint)
989 1.56 jdolecek {
990 1.115.10.1 rmind tun_softc_t *tp = kn->kn_hook;
991 1.115.10.1 rmind ifnet_t *ifp = &tp->tun_if;
992 1.56 jdolecek struct mbuf *m;
993 1.56 jdolecek
994 1.115.10.1 rmind mutex_enter(&tp->tun_lock);
995 1.56 jdolecek IF_POLL(&ifp->if_snd, m);
996 1.56 jdolecek if (m == NULL) {
997 1.115.10.1 rmind mutex_exit(&tp->tun_lock);
998 1.56 jdolecek return (0);
999 1.56 jdolecek }
1000 1.115.10.1 rmind for (kn->kn_data = 0; m != NULL; m = m->m_next) {
1001 1.56 jdolecek kn->kn_data += m->m_len;
1002 1.115.10.1 rmind }
1003 1.115.10.1 rmind mutex_exit(&tp->tun_lock);
1004 1.56 jdolecek
1005 1.115.10.1 rmind return 1;
1006 1.56 jdolecek }
1007 1.56 jdolecek
1008 1.56 jdolecek static const struct filterops tunread_filtops =
1009 1.56 jdolecek { 1, NULL, filt_tunrdetach, filt_tunread };
1010 1.56 jdolecek
1011 1.56 jdolecek static const struct filterops tun_seltrue_filtops =
1012 1.56 jdolecek { 1, NULL, filt_tunrdetach, filt_seltrue };
1013 1.56 jdolecek
1014 1.56 jdolecek int
1015 1.56 jdolecek tunkqfilter(dev_t dev, struct knote *kn)
1016 1.56 jdolecek {
1017 1.115.10.1 rmind tun_softc_t *tp;
1018 1.56 jdolecek struct klist *klist;
1019 1.115.10.1 rmind int rv = 0;
1020 1.70 pk
1021 1.70 pk tp = tun_find_unit(dev);
1022 1.115.10.1 rmind if (tp == NULL) {
1023 1.115.10.1 rmind return 0;
1024 1.115.10.1 rmind }
1025 1.56 jdolecek
1026 1.56 jdolecek switch (kn->kn_filter) {
1027 1.56 jdolecek case EVFILT_READ:
1028 1.57 christos klist = &tp->tun_rsel.sel_klist;
1029 1.56 jdolecek kn->kn_fop = &tunread_filtops;
1030 1.56 jdolecek break;
1031 1.56 jdolecek case EVFILT_WRITE:
1032 1.57 christos klist = &tp->tun_rsel.sel_klist;
1033 1.56 jdolecek kn->kn_fop = &tun_seltrue_filtops;
1034 1.56 jdolecek break;
1035 1.56 jdolecek default:
1036 1.100 pooka rv = EINVAL;
1037 1.70 pk goto out;
1038 1.56 jdolecek }
1039 1.56 jdolecek
1040 1.56 jdolecek kn->kn_hook = tp;
1041 1.56 jdolecek SLIST_INSERT_HEAD(klist, kn, kn_selnext);
1042 1.70 pk out:
1043 1.115 rmind mutex_exit(&tp->tun_lock);
1044 1.115.10.1 rmind return rv;
1045 1.1 cgd }
1046