Bug Summary

File:net/if_tun.c
Warning:line 986, column 2
Value stored to 'ifp' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name if_tun.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -D CONFIG_DRM_AMD_DC_DCN3_0 -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/net/if_tun.c
1/* $OpenBSD: if_tun.c,v 1.231 2021/03/09 20:05:14 anton Exp $ */
2/* $NetBSD: if_tun.c,v 1.24 1996/05/07 02:40:48 thorpej Exp $ */
3
4/*
5 * Copyright (c) 1988, Julian Onions <Julian.Onions@nexor.co.uk>
6 * Nottingham University 1987.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/*
31 * This driver takes packets off the IP i/f and hands them up to a
32 * user process to have its wicked way with. This driver has its
33 * roots in a similar driver written by Phil Cockcroft (formerly) at
34 * UCL. This driver is based much more on read/write/select mode of
35 * operation though.
36 */
37
38/* #define TUN_DEBUG 9 */
39
40#include <sys/param.h>
41#include <sys/kernel.h>
42#include <sys/proc.h>
43#include <sys/systm.h>
44#include <sys/mbuf.h>
45#include <sys/protosw.h>
46#include <sys/sigio.h>
47#include <sys/socket.h>
48#include <sys/ioctl.h>
49#include <sys/errno.h>
50#include <sys/syslog.h>
51#include <sys/selinfo.h>
52#include <sys/fcntl.h>
53#include <sys/time.h>
54#include <sys/device.h>
55#include <sys/vnode.h>
56#include <sys/signalvar.h>
57#include <sys/poll.h>
58#include <sys/conf.h>
59#include <sys/smr.h>
60
61#include <net/if.h>
62#include <net/if_types.h>
63#include <net/netisr.h>
64#include <net/rtable.h>
65
66#include <netinet/in.h>
67#include <netinet/if_ether.h>
68
69#include "bpfilter.h"
70#if NBPFILTER1 > 0
71#include <net/bpf.h>
72#endif
73
74#ifdef MPLS1
75#include <netmpls/mpls.h>
76#endif /* MPLS */
77
78#include <net/if_tun.h>
79
80struct tun_softc {
81 struct arpcom sc_ac; /* ethernet common data */
82#define sc_ifsc_ac.ac_if sc_ac.ac_if
83 struct selinfo sc_rsel; /* read select */
84 struct selinfo sc_wsel; /* write select (not used) */
85 SMR_LIST_ENTRY(tun_softc)struct { struct tun_softc *smr_le_next; struct tun_softc **smr_le_prev
; }
86 sc_entry; /* all tunnel interfaces */
87 int sc_unit;
88 struct sigio_ref sc_sigio; /* async I/O registration */
89 unsigned int sc_flags; /* misc flags */
90#define TUN_DEAD(1 << 16) (1 << 16)
91
92 dev_t sc_dev;
93 struct refcnt sc_refs;
94 unsigned int sc_reading;
95};
96
97#ifdef TUN_DEBUG
98int tundebug = TUN_DEBUG;
99#define TUNDEBUG(a) (tundebug? printf a : 0)
100#else
101#define TUNDEBUG(a) /* (tundebug? printf a : 0) */
102#endif
103
104/* Only these IFF flags are changeable by TUNSIFINFO */
105#define TUN_IFF_FLAGS(0x1|0x10|0x8000|0x2) (IFF_UP0x1|IFF_POINTOPOINT0x10|IFF_MULTICAST0x8000|IFF_BROADCAST0x2)
106
107void tunattach(int);
108
109int tun_dev_open(dev_t, const struct if_clone *, int, struct proc *);
110int tun_dev_close(dev_t, struct proc *);
111int tun_dev_ioctl(dev_t, u_long, void *);
112int tun_dev_read(dev_t, struct uio *, int);
113int tun_dev_write(dev_t, struct uio *, int, int);
114int tun_dev_poll(dev_t, int, struct proc *);
115int tun_dev_kqfilter(dev_t, struct knote *);
116
117int tun_ioctl(struct ifnet *, u_long, caddr_t);
118void tun_input(struct ifnet *, struct mbuf *);
119int tun_output(struct ifnet *, struct mbuf *, struct sockaddr *,
120 struct rtentry *);
121int tun_enqueue(struct ifnet *, struct mbuf *);
122int tun_clone_create(struct if_clone *, int);
123int tap_clone_create(struct if_clone *, int);
124int tun_create(struct if_clone *, int, int);
125int tun_clone_destroy(struct ifnet *);
126void tun_wakeup(struct tun_softc *);
127int tun_init(struct tun_softc *);
128void tun_start(struct ifnet *);
129int filt_tunread(struct knote *, long);
130int filt_tunwrite(struct knote *, long);
131void filt_tunrdetach(struct knote *);
132void filt_tunwdetach(struct knote *);
133void tun_link_state(struct tun_softc *, int);
134
135const struct filterops tunread_filtops = {
136 .f_flags = FILTEROP_ISFD0x00000001,
137 .f_attach = NULL((void *)0),
138 .f_detach = filt_tunrdetach,
139 .f_event = filt_tunread,
140};
141
142const struct filterops tunwrite_filtops = {
143 .f_flags = FILTEROP_ISFD0x00000001,
144 .f_attach = NULL((void *)0),
145 .f_detach = filt_tunwdetach,
146 .f_event = filt_tunwrite,
147};
148
149SMR_LIST_HEAD(tun_list, tun_softc)struct tun_list { struct tun_softc *smr_lh_first; };
150
151struct if_clone tun_cloner =
152 IF_CLONE_INITIALIZER("tun", tun_clone_create, tun_clone_destroy){ .ifc_list = { ((void *)0), ((void *)0) }, .ifc_name = "tun"
, .ifc_namelen = sizeof("tun") - 1, .ifc_create = tun_clone_create
, .ifc_destroy = tun_clone_destroy, }
;
153
154struct if_clone tap_cloner =
155 IF_CLONE_INITIALIZER("tap", tap_clone_create, tun_clone_destroy){ .ifc_list = { ((void *)0), ((void *)0) }, .ifc_name = "tap"
, .ifc_namelen = sizeof("tap") - 1, .ifc_create = tap_clone_create
, .ifc_destroy = tun_clone_destroy, }
;
156
157void
158tunattach(int n)
159{
160 if_clone_attach(&tun_cloner);
161 if_clone_attach(&tap_cloner);
162}
163
164int
165tun_clone_create(struct if_clone *ifc, int unit)
166{
167 return (tun_create(ifc, unit, 0));
168}
169
170int
171tap_clone_create(struct if_clone *ifc, int unit)
172{
173 return (tun_create(ifc, unit, TUN_LAYER20x0800));
174}
175
176struct tun_list tun_devs_list = SMR_LIST_HEAD_INITIALIZER(tun_list){ .smr_lh_first = ((void *)0) };
177
178struct tun_softc *
179tun_name_lookup(const char *name)
180{
181 struct tun_softc *sc;
182
183 KERNEL_ASSERT_LOCKED()((_kernel_lock_held()) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/net/if_tun.c"
, 183, "_kernel_lock_held()"))
;
184
185 SMR_LIST_FOREACH_LOCKED(sc, &tun_devs_list, sc_entry)for((sc) = ((&tun_devs_list)->smr_lh_first); (sc)!= ((
void *)0); (sc) = ((sc)->sc_entry.smr_le_next))
{
186 if (strcmp(sc->sc_ifsc_ac.ac_if.if_xname, name) == 0)
187 return (sc);
188 }
189
190 return (NULL((void *)0));
191}
192
193int
194tun_insert(struct tun_softc *sc)
195{
196 int error = 0;
197
198 /* check for a race */
199 if (tun_name_lookup(sc->sc_ifsc_ac.ac_if.if_xname) != NULL((void *)0))
200 error = EEXIST17;
201 else {
202 /* tun_name_lookup checks for the right lock already */
203 SMR_LIST_INSERT_HEAD_LOCKED(&tun_devs_list, sc, sc_entry)do { (sc)->sc_entry.smr_le_next = (&tun_devs_list)->
smr_lh_first; (sc)->sc_entry.smr_le_prev = &(&tun_devs_list
)->smr_lh_first; if ((&tun_devs_list)->smr_lh_first
!= ((void *)0)) (&tun_devs_list)->smr_lh_first->sc_entry
.smr_le_prev = &(sc)->sc_entry.smr_le_next; do { __asm
volatile("" ::: "memory"); } while (0); (&tun_devs_list)
->smr_lh_first = (sc); } while (0)
;
204 }
205
206 return (error);
207}
208
209int
210tun_create(struct if_clone *ifc, int unit, int flags)
211{
212 struct tun_softc *sc;
213 struct ifnet *ifp;
214
215 if (unit > minor(~0U)((unsigned)((~0U) & 0xff) | (((~0U) & 0xffff0000) >>
8))
)
216 return (ENXIO6);
217
218 KERNEL_ASSERT_LOCKED()((_kernel_lock_held()) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/net/if_tun.c"
, 218, "_kernel_lock_held()"))
;
219
220 sc = malloc(sizeof(*sc), M_DEVBUF2, M_WAITOK0x0001|M_ZERO0x0008);
221 ifp = &sc->sc_ifsc_ac.ac_if;
222 snprintf(ifp->if_xname, sizeof(ifp->if_xname),
223 "%s%d", ifc->ifc_name, unit);
224 ifp->if_softc = sc;
225
226 /* this is enough state for tun_dev_open to work with */
227
228 if (tun_insert(sc) != 0)
229 goto exists;
230
231 /* build the interface */
232
233 ifp->if_ioctl = tun_ioctl;
234 ifp->if_enqueue = tun_enqueue;
235 ifp->if_start = tun_start;
236 ifp->if_hardmtu = TUNMRU16384;
237 ifp->if_link_stateif_data.ifi_link_state = LINK_STATE_DOWN2;
238
239 if_counters_alloc(ifp);
240
241 if ((flags & TUN_LAYER20x0800) == 0) {
242#if NBPFILTER1 > 0
243 ifp->if_bpf_mtap = bpf_mtap;
244#endif
245 ifp->if_input = tun_input;
246 ifp->if_output = tun_output;
247 ifp->if_mtuif_data.ifi_mtu = ETHERMTU(1518 - ((6 * 2) + 2) - 4);
248 ifp->if_flags = (IFF_POINTOPOINT0x10|IFF_MULTICAST0x8000);
249 ifp->if_typeif_data.ifi_type = IFT_TUNNEL0x83;
250 ifp->if_hdrlenif_data.ifi_hdrlen = sizeof(u_int32_t);
251 ifp->if_rtrequest = p2p_rtrequest;
252
253 if_attach(ifp);
254 if_alloc_sadl(ifp);
255
256#if NBPFILTER1 > 0
257 bpfattach(&ifp->if_bpf, ifp, DLT_LOOP12, sizeof(u_int32_t));
258#endif
259 } else {
260 sc->sc_flags |= TUN_LAYER20x0800;
261 ether_fakeaddr(ifp);
262 ifp->if_flags =
263 (IFF_BROADCAST0x2|IFF_SIMPLEX0x800|IFF_MULTICAST0x8000);
264
265 if_attach(ifp);
266 ether_ifattach(ifp);
267 }
268
269 sigio_init(&sc->sc_sigio);
270 refcnt_init(&sc->sc_refs);
271
272 /* tell tun_dev_open we're initialised */
273
274 sc->sc_flags |= TUN_INITED0x0002|TUN_STAYUP0x0400;
275 wakeup(sc);
276
277 return (0);
278
279exists:
280 free(sc, M_DEVBUF2, sizeof(*sc));
281 return (EEXIST17);
282}
283
284int
285tun_clone_destroy(struct ifnet *ifp)
286{
287 struct tun_softc *sc = ifp->if_softc;
288 dev_t dev;
289 int s;
290
291 KERNEL_ASSERT_LOCKED()((_kernel_lock_held()) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/net/if_tun.c"
, 291, "_kernel_lock_held()"))
;
292
293 if (ISSET(sc->sc_flags, TUN_DEAD)((sc->sc_flags) & ((1 << 16))))
294 return (ENXIO6);
295 SET(sc->sc_flags, TUN_DEAD)((sc->sc_flags) |= ((1 << 16)));
296
297 /* kick userland off the device */
298 dev = sc->sc_dev;
299 if (dev) {
300 struct vnode *vp;
301
302 if (vfinddev(dev, VCHR, &vp))
303 VOP_REVOKE(vp, REVOKEALL0x0001);
304
305 KASSERT(sc->sc_dev == 0)((sc->sc_dev == 0) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/net/if_tun.c"
, 305, "sc->sc_dev == 0"))
;
306 }
307
308 /* prevent userland from getting to the device again */
309 SMR_LIST_REMOVE_LOCKED(sc, sc_entry)do { if ((sc)->sc_entry.smr_le_next != ((void *)0)) (sc)->
sc_entry.smr_le_next->sc_entry.smr_le_prev = (sc)->sc_entry
.smr_le_prev; *(sc)->sc_entry.smr_le_prev = (sc)->sc_entry
.smr_le_next; } while (0)
;
310 smr_barrier()smr_barrier_impl(0);
311
312 /* help read() give up */
313 if (sc->sc_reading)
314 wakeup(&ifp->if_snd);
315
316 /* wait for device entrypoints to finish */
317 refcnt_finalize(&sc->sc_refs, "tundtor");
318
319 s = splhigh()splraise(0xd);
320 klist_invalidate(&sc->sc_rsel.si_note);
321 klist_invalidate(&sc->sc_wsel.si_note);
322 splx(s)spllower(s);
323
324 if (ISSET(sc->sc_flags, TUN_LAYER2)((sc->sc_flags) & (0x0800)))
325 ether_ifdetach(ifp);
326
327 if_detach(ifp);
328 sigio_free(&sc->sc_sigio);
329
330 free(sc, M_DEVBUF2, sizeof *sc);
331 return (0);
332}
333
334static struct tun_softc *
335tun_get(dev_t dev)
336{
337 struct tun_softc *sc;
338
339 smr_read_enter();
340 SMR_LIST_FOREACH(sc, &tun_devs_list, sc_entry)for((sc) = ({ typeof(*&(&tun_devs_list)->smr_lh_first
) __tmp = *(volatile typeof(*&(&tun_devs_list)->smr_lh_first
) *)&(*&(&tun_devs_list)->smr_lh_first); membar_datadep_consumer
(); __tmp; }); (sc)!= ((void *)0); (sc) = ({ typeof(*&(sc
)->sc_entry.smr_le_next) __tmp = *(volatile typeof(*&(
sc)->sc_entry.smr_le_next) *)&(*&(sc)->sc_entry
.smr_le_next); membar_datadep_consumer(); __tmp; }))
{
341 if (sc->sc_dev == dev) {
342 refcnt_take(&sc->sc_refs);
343 break;
344 }
345 }
346 smr_read_leave();
347
348 return (sc);
349}
350
351static inline void
352tun_put(struct tun_softc *sc)
353{
354 refcnt_rele_wake(&sc->sc_refs);
355}
356
357int
358tunopen(dev_t dev, int flag, int mode, struct proc *p)
359{
360 return (tun_dev_open(dev, &tun_cloner, mode, p));
361}
362
363int
364tapopen(dev_t dev, int flag, int mode, struct proc *p)
365{
366 return (tun_dev_open(dev, &tap_cloner, mode, p));
367}
368
369int
370tun_dev_open(dev_t dev, const struct if_clone *ifc, int mode, struct proc *p)
371{
372 struct tun_softc *sc;
373 struct ifnet *ifp;
374 int error;
375 u_short stayup = 0;
376
377 char name[IFNAMSIZ16];
378 unsigned int rdomain;
379
380 snprintf(name, sizeof(name), "%s%u", ifc->ifc_name, minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
);
381 rdomain = rtable_l2(p->p_p->ps_rtableid);
382
383 /* let's find or make an interface to work with */
384 while ((ifp = if_unit(name)) == NULL((void *)0)) {
385 error = if_clone_create(name, rdomain);
386 switch (error) {
387 case 0: /* it's probably ours */
388 stayup = TUN_STAYUP0x0400;
389 /* FALLTHROUGH */
390 case EEXIST17: /* we may have lost a race with someone else */
391 break;
392 default:
393 return (error);
394 }
395 }
396
397 sc = ifp->if_softc;
398 /* wait for it to be fully constructed before we use it */
399 while (!ISSET(sc->sc_flags, TUN_INITED)((sc->sc_flags) & (0x0002))) {
400 error = tsleep_nsec(sc, PCATCH0x100, "tuninit", INFSLP0xffffffffffffffffULL);
401 if (error != 0) {
402 /* XXX if_clone_destroy if stayup? */
403 if_put(ifp);
404 return (error);
405 }
406 }
407
408 if (sc->sc_dev != 0) {
409 /* aww, we lost */
410 if_put(ifp);
411 return (EBUSY16);
412 }
413 /* it's ours now */
414 sc->sc_dev = dev;
415 CLR(sc->sc_flags, stayup)((sc->sc_flags) &= ~(stayup));
416
417 /* automatically mark the interface running on open */
418 SET(ifp->if_flags, IFF_UP | IFF_RUNNING)((ifp->if_flags) |= (0x1 | 0x40));
419 if_put(ifp);
420 tun_link_state(sc, LINK_STATE_FULL_DUPLEX6);
421
422 return (0);
423}
424
425/*
426 * tunclose - close the device; if closing the real device, flush pending
427 * output and unless STAYUP bring down and destroy the interface.
428 */
429int
430tunclose(dev_t dev, int flag, int mode, struct proc *p)
431{
432 return (tun_dev_close(dev, p));
433}
434
435int
436tapclose(dev_t dev, int flag, int mode, struct proc *p)
437{
438 return (tun_dev_close(dev, p));
439}
440
441int
442tun_dev_close(dev_t dev, struct proc *p)
443{
444 struct tun_softc *sc;
445 struct ifnet *ifp;
446 int error = 0;
447 char name[IFNAMSIZ16];
448 int destroy = 0;
449
450 sc = tun_get(dev);
451 if (sc == NULL((void *)0))
452 return (ENXIO6);
453
454 ifp = &sc->sc_ifsc_ac.ac_if;
455
456 /*
457 * junk all pending output
458 */
459 CLR(ifp->if_flags, IFF_UP | IFF_RUNNING)((ifp->if_flags) &= ~(0x1 | 0x40));
460 ifq_purge(&ifp->if_snd);
461
462 CLR(sc->sc_flags, TUN_ASYNC)((sc->sc_flags) &= ~(0x0080));
463 selwakeup(&sc->sc_rsel);
464 sigio_free(&sc->sc_sigio);
465
466 if (!ISSET(sc->sc_flags, TUN_DEAD)((sc->sc_flags) & ((1 << 16)))) {
467 /* we can't hold a reference to sc before we start a dtor */
468 if (!ISSET(sc->sc_flags, TUN_STAYUP)((sc->sc_flags) & (0x0400))) {
469 destroy = 1;
470 strlcpy(name, ifp->if_xname, sizeof(name));
471 } else {
472 CLR(ifp->if_flags, IFF_UP | IFF_RUNNING)((ifp->if_flags) &= ~(0x1 | 0x40));
473 tun_link_state(sc, LINK_STATE_DOWN2);
474 }
475 }
476
477 sc->sc_dev = 0;
478
479 tun_put(sc);
480
481 if (destroy)
482 if_clone_destroy(name);
483
484 return (error);
485}
486
487int
488tun_init(struct tun_softc *sc)
489{
490 struct ifnet *ifp = &sc->sc_ifsc_ac.ac_if;
491 struct ifaddr *ifa;
492
493 TUNDEBUG(("%s: tun_init\n", ifp->if_xname));
494
495 ifp->if_flags |= IFF_UP0x1 | IFF_RUNNING0x40;
496
497 sc->sc_flags &= ~(TUN_IASET0x0008|TUN_DSTADDR0x0010|TUN_BRDADDR0x0200);
498 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)for((ifa) = ((&ifp->if_addrlist)->tqh_first); (ifa)
!= ((void *)0); (ifa) = ((ifa)->ifa_list.tqe_next))
{
499 if (ifa->ifa_addr->sa_family == AF_INET2) {
500 struct sockaddr_in *sin;
501
502 sin = satosin(ifa->ifa_addr);
503 if (sin && sin->sin_addr.s_addr)
504 sc->sc_flags |= TUN_IASET0x0008;
505
506 if (ifp->if_flags & IFF_POINTOPOINT0x10) {
507 sin = satosin(ifa->ifa_dstaddr);
508 if (sin && sin->sin_addr.s_addr)
509 sc->sc_flags |= TUN_DSTADDR0x0010;
510 } else
511 sc->sc_flags &= ~TUN_DSTADDR0x0010;
512
513 if (ifp->if_flags & IFF_BROADCAST0x2) {
514 sin = satosin(ifa->ifa_broadaddrifa_dstaddr);
515 if (sin && sin->sin_addr.s_addr)
516 sc->sc_flags |= TUN_BRDADDR0x0200;
517 } else
518 sc->sc_flags &= ~TUN_BRDADDR0x0200;
519 }
520#ifdef INET61
521 if (ifa->ifa_addr->sa_family == AF_INET624) {
522 struct sockaddr_in6 *sin6;
523
524 sin6 = satosin6(ifa->ifa_addr);
525 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)((*(const u_int32_t *)(const void *)(&(&sin6->sin6_addr
)->__u6_addr.__u6_addr8[0]) == 0) && (*(const u_int32_t
*)(const void *)(&(&sin6->sin6_addr)->__u6_addr
.__u6_addr8[4]) == 0) && (*(const u_int32_t *)(const void
*)(&(&sin6->sin6_addr)->__u6_addr.__u6_addr8[8
]) == 0) && (*(const u_int32_t *)(const void *)(&
(&sin6->sin6_addr)->__u6_addr.__u6_addr8[12]) == 0)
)
)
526 sc->sc_flags |= TUN_IASET0x0008;
527
528 if (ifp->if_flags & IFF_POINTOPOINT0x10) {
529 sin6 = satosin6(ifa->ifa_dstaddr);
530 if (sin6 &&
531 !IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)((*(const u_int32_t *)(const void *)(&(&sin6->sin6_addr
)->__u6_addr.__u6_addr8[0]) == 0) && (*(const u_int32_t
*)(const void *)(&(&sin6->sin6_addr)->__u6_addr
.__u6_addr8[4]) == 0) && (*(const u_int32_t *)(const void
*)(&(&sin6->sin6_addr)->__u6_addr.__u6_addr8[8
]) == 0) && (*(const u_int32_t *)(const void *)(&
(&sin6->sin6_addr)->__u6_addr.__u6_addr8[12]) == 0)
)
)
532 sc->sc_flags |= TUN_DSTADDR0x0010;
533 } else
534 sc->sc_flags &= ~TUN_DSTADDR0x0010;
535 }
536#endif /* INET6 */
537 }
538
539 return (0);
540}
541
542/*
543 * Process an ioctl request.
544 */
545int
546tun_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
547{
548 struct tun_softc *sc = (struct tun_softc *)(ifp->if_softc);
549 struct ifreq *ifr = (struct ifreq *)data;
550 int error = 0;
551
552 switch (cmd) {
553 case SIOCSIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((12)))
:
554 tun_init(sc);
555 break;
556 case SIOCSIFFLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((16)))
:
557 if (ISSET(ifp->if_flags, IFF_UP)((ifp->if_flags) & (0x1)))
558 SET(ifp->if_flags, IFF_RUNNING)((ifp->if_flags) |= (0x40));
559 else
560 CLR(ifp->if_flags, IFF_RUNNING)((ifp->if_flags) &= ~(0x40));
561 break;
562
563 case SIOCSIFDSTADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((14)))
:
564 tun_init(sc);
565 TUNDEBUG(("%s: destination address set\n", ifp->if_xname));
566 break;
567 case SIOCSIFMTU((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((127)))
:
568 if (ifr->ifr_mtuifr_ifru.ifru_metric < ETHERMIN(64 - ((6 * 2) + 2) - 4) || ifr->ifr_mtuifr_ifru.ifru_metric > TUNMRU16384)
569 error = EINVAL22;
570 else
571 ifp->if_mtuif_data.ifi_mtu = ifr->ifr_mtuifr_ifru.ifru_metric;
572 break;
573 case SIOCADDMULTI((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((49)))
:
574 case SIOCDELMULTI((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((50)))
:
575 break;
576 default:
577 if (sc->sc_flags & TUN_LAYER20x0800)
578 error = ether_ioctl(ifp, &sc->sc_ac, cmd, data);
579 else
580 error = ENOTTY25;
581 }
582
583 return (error);
584}
585
586/*
587 * tun_output - queue packets from higher level ready to put out.
588 */
589int
590tun_output(struct ifnet *ifp, struct mbuf *m0, struct sockaddr *dst,
591 struct rtentry *rt)
592{
593 u_int32_t *af;
594
595 if (!ISSET(ifp->if_flags, IFF_RUNNING)((ifp->if_flags) & (0x40))) {
596 m_freem(m0);
597 return (EHOSTDOWN64);
598 }
599
600 M_PREPEND(m0, sizeof(*af), M_DONTWAIT)(m0) = m_prepend((m0), (sizeof(*af)), (0x0002));
601 if (m0 == NULL((void *)0))
602 return (ENOBUFS55);
603 af = mtod(m0, u_int32_t *)((u_int32_t *)((m0)->m_hdr.mh_data));
604 *af = htonl(dst->sa_family)(__uint32_t)(__builtin_constant_p(dst->sa_family) ? (__uint32_t
)(((__uint32_t)(dst->sa_family) & 0xff) << 24 | (
(__uint32_t)(dst->sa_family) & 0xff00) << 8 | ((
__uint32_t)(dst->sa_family) & 0xff0000) >> 8 | (
(__uint32_t)(dst->sa_family) & 0xff000000) >> 24
) : __swap32md(dst->sa_family))
;
605
606 return (if_enqueue(ifp, m0));
607}
608
609int
610tun_enqueue(struct ifnet *ifp, struct mbuf *m0)
611{
612 struct tun_softc *sc = ifp->if_softc;
613 int error;
614
615 error = ifq_enqueue(&ifp->if_snd, m0);
616 if (error != 0)
617 return (error);
618
619 tun_wakeup(sc);
620
621 return (0);
622}
623
624void
625tun_wakeup(struct tun_softc *sc)
626{
627 if (sc->sc_reading)
628 wakeup(&sc->sc_ifsc_ac.ac_if.if_snd);
629
630 selwakeup(&sc->sc_rsel);
631 if (sc->sc_flags & TUN_ASYNC0x0080)
632 pgsigio(&sc->sc_sigio, SIGIO23, 0);
633}
634
635/*
636 * the cdevsw interface is now pretty minimal.
637 */
638int
639tunioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
640{
641 return (tun_dev_ioctl(dev, cmd, data));
642}
643
644int
645tapioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
646{
647 return (tun_dev_ioctl(dev, cmd, data));
648}
649
650int
651tun_dev_ioctl(dev_t dev, u_long cmd, void *data)
652{
653 struct tun_softc *sc;
654 struct tuninfo *tunp;
655 int error = 0;
656
657 sc = tun_get(dev);
658 if (sc == NULL((void *)0))
659 return (ENXIO6);
660
661 switch (cmd) {
662 case TUNSIFINFO((unsigned long)0x80000000 | ((sizeof(struct tuninfo) & 0x1fff
) << 16) | ((('t')) << 8) | ((91)))
:
663 tunp = (struct tuninfo *)data;
664 if (tunp->mtu < ETHERMIN(64 - ((6 * 2) + 2) - 4) || tunp->mtu > TUNMRU16384) {
665 error = EINVAL22;
666 break;
667 }
668 if (tunp->type != sc->sc_ifsc_ac.ac_if.if_typeif_data.ifi_type) {
669 error = EINVAL22;
670 break;
671 }
672 sc->sc_ifsc_ac.ac_if.if_mtuif_data.ifi_mtu = tunp->mtu;
673 sc->sc_ifsc_ac.ac_if.if_flags =
674 (tunp->flags & TUN_IFF_FLAGS(0x1|0x10|0x8000|0x2)) |
675 (sc->sc_ifsc_ac.ac_if.if_flags & ~TUN_IFF_FLAGS(0x1|0x10|0x8000|0x2));
676 sc->sc_ifsc_ac.ac_if.if_baudrateif_data.ifi_baudrate = tunp->baudrate;
677 break;
678 case TUNGIFINFO((unsigned long)0x40000000 | ((sizeof(struct tuninfo) & 0x1fff
) << 16) | ((('t')) << 8) | ((92)))
:
679 tunp = (struct tuninfo *)data;
680 tunp->mtu = sc->sc_ifsc_ac.ac_if.if_mtuif_data.ifi_mtu;
681 tunp->type = sc->sc_ifsc_ac.ac_if.if_typeif_data.ifi_type;
682 tunp->flags = sc->sc_ifsc_ac.ac_if.if_flags;
683 tunp->baudrate = sc->sc_ifsc_ac.ac_if.if_baudrateif_data.ifi_baudrate;
684 break;
685#ifdef TUN_DEBUG
686 case TUNSDEBUG((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((94)))
:
687 tundebug = *(int *)data;
688 break;
689 case TUNGDEBUG((unsigned long)0x40000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((95)))
:
690 *(int *)data = tundebug;
691 break;
692#endif
693 case TUNSIFMODE((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((93)))
:
694 switch (*(int *)data & (IFF_POINTOPOINT0x10|IFF_BROADCAST0x2)) {
695 case IFF_POINTOPOINT0x10:
696 case IFF_BROADCAST0x2:
697 sc->sc_ifsc_ac.ac_if.if_flags &= ~TUN_IFF_FLAGS(0x1|0x10|0x8000|0x2);
698 sc->sc_ifsc_ac.ac_if.if_flags |= *(int *)data & TUN_IFF_FLAGS(0x1|0x10|0x8000|0x2);
699 break;
700 default:
701 error = EINVAL22;
702 break;
703 }
704 break;
705
706 case FIONBIO((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('f')) << 8) | ((126)))
:
707 break;
708 case FIOASYNC((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('f')) << 8) | ((125)))
:
709 if (*(int *)data)
710 sc->sc_flags |= TUN_ASYNC0x0080;
711 else
712 sc->sc_flags &= ~TUN_ASYNC0x0080;
713 break;
714 case FIONREAD((unsigned long)0x40000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('f')) << 8) | ((127)))
:
715 *(int *)data = ifq_hdatalen(&sc->sc_ifsc_ac.ac_if.if_snd);
716 break;
717 case FIOSETOWN((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('f')) << 8) | ((124)))
:
718 case TIOCSPGRP((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((118)))
:
719 error = sigio_setown(&sc->sc_sigio, cmd, data);
720 break;
721 case FIOGETOWN((unsigned long)0x40000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('f')) << 8) | ((123)))
:
722 case TIOCGPGRP((unsigned long)0x40000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((119)))
:
723 sigio_getown(&sc->sc_sigio, cmd, data);
724 break;
725 case SIOCGIFADDR(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((33)))
:
726 if (!(sc->sc_flags & TUN_LAYER20x0800)) {
727 error = EINVAL22;
728 break;
729 }
730 bcopy(sc->sc_ac.ac_enaddr, data,
731 sizeof(sc->sc_ac.ac_enaddr));
732 break;
733
734 case SIOCSIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((12)))
:
735 if (!(sc->sc_flags & TUN_LAYER20x0800)) {
736 error = EINVAL22;
737 break;
738 }
739 bcopy(data, sc->sc_ac.ac_enaddr,
740 sizeof(sc->sc_ac.ac_enaddr));
741 break;
742 default:
743 error = ENOTTY25;
744 break;
745 }
746
747 tun_put(sc);
748 return (error);
749}
750
751/*
752 * The cdevsw read interface - reads a packet at a time, or at
753 * least as much of a packet as can be read.
754 */
755int
756tunread(dev_t dev, struct uio *uio, int ioflag)
757{
758 return (tun_dev_read(dev, uio, ioflag));
759}
760
761int
762tapread(dev_t dev, struct uio *uio, int ioflag)
763{
764 return (tun_dev_read(dev, uio, ioflag));
765}
766
767int
768tun_dev_read(dev_t dev, struct uio *uio, int ioflag)
769{
770 struct tun_softc *sc;
771 struct ifnet *ifp;
772 struct mbuf *m, *m0;
773 int error = 0;
774
775 sc = tun_get(dev);
776 if (sc == NULL((void *)0))
777 return (ENXIO6);
778
779 ifp = &sc->sc_ifsc_ac.ac_if;
780
781 error = ifq_deq_sleep(&ifp->if_snd, &m0, ISSET(ioflag, IO_NDELAY)((ioflag) & (0x10)),
782 (PZERO22 + 1)|PCATCH0x100, "tunread", &sc->sc_reading, &sc->sc_dev);
783 if (error != 0)
784 goto put;
785
786#if NBPFILTER1 > 0
787 if (ifp->if_bpf)
788 bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT(1 << 1));
789#endif
790
791 m = m0;
792 while (uio->uio_resid > 0) {
793 size_t len = ulmin(uio->uio_resid, m->m_lenm_hdr.mh_len);
794 if (len > 0) {
795 error = uiomove(mtod(m, void *)((void *)((m)->m_hdr.mh_data)), len, uio);
796 if (error != 0)
797 break;
798 }
799
800 m = m->m_nextm_hdr.mh_next;
801 if (m == NULL((void *)0))
802 break;
803 }
804
805 m_freem(m0);
806
807put:
808 tun_put(sc);
809 return (error);
810}
811
812/*
813 * the cdevsw write interface - an atomic write is a packet - or else!
814 */
815int
816tunwrite(dev_t dev, struct uio *uio, int ioflag)
817{
818 return (tun_dev_write(dev, uio, ioflag, 0));
819}
820
821int
822tapwrite(dev_t dev, struct uio *uio, int ioflag)
823{
824 return (tun_dev_write(dev, uio, ioflag, ETHER_ALIGN2));
825}
826
827int
828tun_dev_write(dev_t dev, struct uio *uio, int ioflag, int align)
829{
830 struct tun_softc *sc;
831 struct ifnet *ifp;
832 struct mbuf *m0;
833 int error = 0;
834 size_t mlen;
835
836 sc = tun_get(dev);
837 if (sc == NULL((void *)0))
838 return (ENXIO6);
839
840 ifp = &sc->sc_ifsc_ac.ac_if;
841
842 if (uio->uio_resid < ifp->if_hdrlenif_data.ifi_hdrlen ||
843 uio->uio_resid > (ifp->if_hdrlenif_data.ifi_hdrlen + ifp->if_hardmtu)) {
844 error = EMSGSIZE40;
845 goto put;
846 }
847
848 align += max_linkhdr;
849 mlen = align + uio->uio_resid;
850
851 m0 = m_gethdr(M_DONTWAIT0x0002, MT_DATA1);
852 if (m0 == NULL((void *)0)) {
853 error = ENOMEM12;
854 goto put;
855 }
856 if (mlen > MHLEN((256 - sizeof(struct m_hdr)) - sizeof(struct pkthdr))) {
857 m_clget(m0, M_DONTWAIT0x0002, mlen);
858 if (!ISSET(m0->m_flags, M_EXT)((m0->m_hdr.mh_flags) & (0x0001))) {
859 error = ENOMEM12;
860 goto drop;
861 }
862 }
863
864 m_align(m0, mlen);
865 m0->m_pkthdrM_dat.MH.MH_pkthdr.len = m0->m_lenm_hdr.mh_len = mlen;
866 m_adj(m0, align);
867
868 error = uiomove(mtod(m0, void *)((void *)((m0)->m_hdr.mh_data)), m0->m_lenm_hdr.mh_len, uio);
869 if (error != 0)
870 goto drop;
871
872 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
873 if_vinput(ifp, m0);
874 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
875
876 tun_put(sc);
877 return (0);
878
879drop:
880 m_freem(m0);
881put:
882 tun_put(sc);
883 return (error);
884}
885
886void
887tun_input(struct ifnet *ifp, struct mbuf *m0)
888{
889 uint32_t af;
890
891 KASSERT(m0->m_len >= sizeof(af))((m0->m_hdr.mh_len >= sizeof(af)) ? (void)0 : __assert(
"diagnostic ", "/usr/src/sys/net/if_tun.c", 891, "m0->m_len >= sizeof(af)"
))
;
892
893 af = *mtod(m0, uint32_t *)((uint32_t *)((m0)->m_hdr.mh_data));
894 /* strip the tunnel header */
895 m_adj(m0, sizeof(af));
896
897 switch (ntohl(af)(__uint32_t)(__builtin_constant_p(af) ? (__uint32_t)(((__uint32_t
)(af) & 0xff) << 24 | ((__uint32_t)(af) & 0xff00
) << 8 | ((__uint32_t)(af) & 0xff0000) >> 8 |
((__uint32_t)(af) & 0xff000000) >> 24) : __swap32md
(af))
) {
898 case AF_INET2:
899 ipv4_input(ifp, m0);
900 break;
901#ifdef INET61
902 case AF_INET624:
903 ipv6_input(ifp, m0);
904 break;
905#endif
906#ifdef MPLS1
907 case AF_MPLS33:
908 mpls_input(ifp, m0);
909 break;
910#endif
911 default:
912 m_freem(m0);
913 break;
914 }
915}
916
917/*
918 * tunpoll - the poll interface, this is only useful on reads
919 * really. The write detect always returns true, write never blocks
920 * anyway, it either accepts the packet or drops it.
921 */
922int
923tunpoll(dev_t dev, int events, struct proc *p)
924{
925 return (tun_dev_poll(dev, events, p));
926}
927
928int
929tappoll(dev_t dev, int events, struct proc *p)
930{
931 return (tun_dev_poll(dev, events, p));
932}
933
934int
935tun_dev_poll(dev_t dev, int events, struct proc *p)
936{
937 struct tun_softc *sc;
938 struct ifnet *ifp;
939 int revents;
940
941 sc = tun_get(dev);
942 if (sc == NULL((void *)0))
943 return (POLLERR0x0008);
944
945 ifp = &sc->sc_ifsc_ac.ac_if;
946 revents = 0;
947
948 if (events & (POLLIN0x0001 | POLLRDNORM0x0040)) {
949 if (!ifq_empty(&ifp->if_snd)(((&ifp->if_snd)->ifq_len) == 0))
950 revents |= events & (POLLIN0x0001 | POLLRDNORM0x0040);
951 else
952 selrecord(p, &sc->sc_rsel);
953 }
954 if (events & (POLLOUT0x0004 | POLLWRNORM0x0004))
955 revents |= events & (POLLOUT0x0004 | POLLWRNORM0x0004);
956
957 tun_put(sc);
958 return (revents);
959}
960
961int
962tunkqfilter(dev_t dev, struct knote *kn)
963{
964 return (tun_dev_kqfilter(dev, kn));
965}
966
967int
968tapkqfilter(dev_t dev, struct knote *kn)
969{
970 return (tun_dev_kqfilter(dev, kn));
971}
972
973int
974tun_dev_kqfilter(dev_t dev, struct knote *kn)
975{
976 struct tun_softc *sc;
977 struct ifnet *ifp;
978 struct klist *klist;
979 int error = 0;
980 int s;
981
982 sc = tun_get(dev);
983 if (sc == NULL((void *)0))
984 return (ENXIO6);
985
986 ifp = &sc->sc_ifsc_ac.ac_if;
Value stored to 'ifp' is never read
987
988 switch (kn->kn_filterkn_kevent.filter) {
989 case EVFILT_READ(-1):
990 klist = &sc->sc_rsel.si_note;
991 kn->kn_fop = &tunread_filtops;
992 break;
993 case EVFILT_WRITE(-2):
994 klist = &sc->sc_wsel.si_note;
995 kn->kn_fop = &tunwrite_filtops;
996 break;
997 default:
998 error = EINVAL22;
999 goto put;
1000 }
1001
1002 kn->kn_hook = (caddr_t)sc; /* XXX give the sc_ref to the hook? */
1003
1004 s = splhigh()splraise(0xd);
1005 klist_insert_locked(klist, kn);
1006 splx(s)spllower(s);
1007
1008put:
1009 tun_put(sc);
1010 return (error);
1011}
1012
1013void
1014filt_tunrdetach(struct knote *kn)
1015{
1016 int s;
1017 struct tun_softc *sc = kn->kn_hook;
1018
1019 s = splhigh()splraise(0xd);
1020 klist_remove_locked(&sc->sc_rsel.si_note, kn);
1021 splx(s)spllower(s);
1022}
1023
1024int
1025filt_tunread(struct knote *kn, long hint)
1026{
1027 struct tun_softc *sc = kn->kn_hook;
1028 struct ifnet *ifp = &sc->sc_ifsc_ac.ac_if;
1029
1030 kn->kn_datakn_kevent.data = ifq_hdatalen(&ifp->if_snd);
1031
1032 return (kn->kn_datakn_kevent.data > 0);
1033}
1034
1035void
1036filt_tunwdetach(struct knote *kn)
1037{
1038 int s;
1039 struct tun_softc *sc = kn->kn_hook;
1040
1041 s = splhigh()splraise(0xd);
1042 klist_remove_locked(&sc->sc_wsel.si_note, kn);
1043 splx(s)spllower(s);
1044}
1045
1046int
1047filt_tunwrite(struct knote *kn, long hint)
1048{
1049 struct tun_softc *sc = kn->kn_hook;
1050 struct ifnet *ifp = &sc->sc_ifsc_ac.ac_if;
1051
1052 kn->kn_datakn_kevent.data = ifp->if_hdrlenif_data.ifi_hdrlen + ifp->if_hardmtu;
1053
1054 return (1);
1055}
1056
1057void
1058tun_start(struct ifnet *ifp)
1059{
1060 struct tun_softc *sc = ifp->if_softc;
1061
1062 splassert(IPL_NET)do { if (splassert_ctl > 0) { splassert_check(0x7, __func__
); } } while (0)
;
1063
1064 if (ifq_len(&ifp->if_snd)((&ifp->if_snd)->ifq_len))
1065 tun_wakeup(sc);
1066}
1067
1068void
1069tun_link_state(struct tun_softc *sc, int link_state)
1070{
1071 struct ifnet *ifp = &sc->sc_ifsc_ac.ac_if;
1072
1073 if (ifp->if_link_stateif_data.ifi_link_state != link_state) {
1074 ifp->if_link_stateif_data.ifi_link_state = link_state;
1075 if_link_state_change(ifp);
1076 }
1077}