1120386Ssam/*	$FreeBSD: stable/11/sys/net/pfil.c 332513 2018-04-15 15:22:28Z kp $ */
2120386Ssam/*	$NetBSD: pfil.c,v 1.20 2001/11/12 23:49:46 lukem Exp $	*/
360317Sdarrenr
4139823Simp/*-
560317Sdarrenr * Copyright (c) 1996 Matthew R. Green
660317Sdarrenr * All rights reserved.
760317Sdarrenr *
860317Sdarrenr * Redistribution and use in source and binary forms, with or without
960317Sdarrenr * modification, are permitted provided that the following conditions
1060317Sdarrenr * are met:
1160317Sdarrenr * 1. Redistributions of source code must retain the above copyright
1260317Sdarrenr *    notice, this list of conditions and the following disclaimer.
1360317Sdarrenr * 2. Redistributions in binary form must reproduce the above copyright
1460317Sdarrenr *    notice, this list of conditions and the following disclaimer in the
1560317Sdarrenr *    documentation and/or other materials provided with the distribution.
1660317Sdarrenr * 3. The name of the author may not be used to endorse or promote products
1760317Sdarrenr *    derived from this software without specific prior written permission.
1860317Sdarrenr *
1960317Sdarrenr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2060317Sdarrenr * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2160317Sdarrenr * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2260317Sdarrenr * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2360317Sdarrenr * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
2460317Sdarrenr * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2560317Sdarrenr * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
2660317Sdarrenr * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2760317Sdarrenr * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2860317Sdarrenr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2960317Sdarrenr * SUCH DAMAGE.
3060317Sdarrenr */
3160317Sdarrenr
3260317Sdarrenr#include <sys/param.h>
33120386Ssam#include <sys/kernel.h>
3460317Sdarrenr#include <sys/errno.h>
35155201Scsjp#include <sys/lock.h>
3660317Sdarrenr#include <sys/malloc.h>
37173904Smlaier#include <sys/rmlock.h>
3860317Sdarrenr#include <sys/socket.h>
3960317Sdarrenr#include <sys/socketvar.h>
4060317Sdarrenr#include <sys/systm.h>
41120386Ssam#include <sys/condvar.h>
42120386Ssam#include <sys/lock.h>
43120386Ssam#include <sys/mutex.h>
44120386Ssam#include <sys/proc.h>
4560317Sdarrenr#include <sys/queue.h>
4660317Sdarrenr
4760317Sdarrenr#include <net/if.h>
48257176Sglebius#include <net/if_var.h>
4960317Sdarrenr#include <net/pfil.h>
5060317Sdarrenr
51120386Ssamstatic struct mtx pfil_global_lock;
52120386Ssam
53198198SrwatsonMTX_SYSINIT(pfil_heads_lock, &pfil_global_lock, "pfil_head_list lock",
54198198Srwatson  MTX_DEF);
55120386Ssam
56254773Sandrestatic struct packet_filter_hook *pfil_chain_get(int, struct pfil_head *);
57254773Sandrestatic int pfil_chain_add(pfil_chain_t *, struct packet_filter_hook *, int);
58332513Skpstatic int pfil_chain_remove(pfil_chain_t *, void *, void *);
59332513Skpstatic int pfil_add_hook_priv(void *, void *, int, struct pfil_head *, bool);
60120386Ssam
61197952SjulianLIST_HEAD(pfilheadhead, pfil_head);
62197952SjulianVNET_DEFINE(struct pfilheadhead, pfil_head_list);
63197952Sjulian#define	V_pfil_head_list	VNET(pfil_head_list)
64241888SmelifaroVNET_DEFINE(struct rmlock, pfil_lock);
65120386Ssam
66316458Sae#define	PFIL_LOCK_INIT_REAL(l, t)	\
67316458Sae	rm_init_flags(l, "PFil " t " rmlock", RM_RECURSE)
68316458Sae#define	PFIL_LOCK_DESTROY_REAL(l)	\
69316458Sae	rm_destroy(l)
70316458Sae#define	PFIL_LOCK_INIT(p)	do {			\
71316458Sae	if ((p)->flags & PFIL_FLAG_PRIVATE_LOCK) {	\
72316458Sae		PFIL_LOCK_INIT_REAL(&(p)->ph_lock, "private");	\
73316458Sae		(p)->ph_plock = &(p)->ph_lock;		\
74316458Sae	} else						\
75316458Sae		(p)->ph_plock = &V_pfil_lock;		\
76316458Sae} while (0)
77316458Sae#define	PFIL_LOCK_DESTROY(p)	do {			\
78316458Sae	if ((p)->flags & PFIL_FLAG_PRIVATE_LOCK)	\
79316458Sae		PFIL_LOCK_DESTROY_REAL((p)->ph_plock);	\
80316458Sae} while (0)
81316458Sae
82316458Sae#define	PFIL_TRY_RLOCK(p, t)	rm_try_rlock((p)->ph_plock, (t))
83316458Sae#define	PFIL_RLOCK(p, t)	rm_rlock((p)->ph_plock, (t))
84316458Sae#define	PFIL_WLOCK(p)		rm_wlock((p)->ph_plock)
85316458Sae#define	PFIL_RUNLOCK(p, t)	rm_runlock((p)->ph_plock, (t))
86316458Sae#define	PFIL_WUNLOCK(p)		rm_wunlock((p)->ph_plock)
87316458Sae#define	PFIL_WOWNED(p)		rm_wowned((p)->ph_plock)
88316458Sae
89316458Sae#define	PFIL_HEADLIST_LOCK()	mtx_lock(&pfil_global_lock)
90316458Sae#define	PFIL_HEADLIST_UNLOCK()	mtx_unlock(&pfil_global_lock)
91316458Sae
92120386Ssam/*
93254773Sandre * pfil_run_hooks() runs the specified packet filter hook chain.
94120386Ssam */
95120386Ssamint
96120386Ssampfil_run_hooks(struct pfil_head *ph, struct mbuf **mp, struct ifnet *ifp,
97332513Skp    int dir, int flags, struct inpcb *inp)
98120386Ssam{
99173904Smlaier	struct rm_priotracker rmpt;
100120386Ssam	struct packet_filter_hook *pfh;
101120386Ssam	struct mbuf *m = *mp;
102120386Ssam	int rv = 0;
103120386Ssam
104173904Smlaier	PFIL_RLOCK(ph, &rmpt);
105155201Scsjp	KASSERT(ph->ph_nhooks >= 0, ("Pfil hook count dropped < 0"));
106254773Sandre	for (pfh = pfil_chain_get(dir, ph); pfh != NULL;
107254773Sandre	     pfh = TAILQ_NEXT(pfh, pfil_chain)) {
108332513Skp		if (pfh->pfil_func_flags != NULL) {
109332513Skp			rv = (*pfh->pfil_func_flags)(pfh->pfil_arg, &m, ifp,
110332513Skp			    dir, flags, inp);
111332513Skp			if (rv != 0 || m == NULL)
112332513Skp				break;
113332513Skp		}
114120386Ssam		if (pfh->pfil_func != NULL) {
115198198Srwatson			rv = (*pfh->pfil_func)(pfh->pfil_arg, &m, ifp, dir,
116198198Srwatson			    inp);
117120386Ssam			if (rv != 0 || m == NULL)
118120386Ssam				break;
119120386Ssam		}
120120386Ssam	}
121173904Smlaier	PFIL_RUNLOCK(ph, &rmpt);
122120386Ssam	*mp = m;
123120386Ssam	return (rv);
124120386Ssam}
125120386Ssam
126254771Sandrestatic struct packet_filter_hook *
127254773Sandrepfil_chain_get(int dir, struct pfil_head *ph)
128254771Sandre{
129254771Sandre
130254771Sandre	if (dir == PFIL_IN)
131254771Sandre		return (TAILQ_FIRST(&ph->ph_in));
132254771Sandre	else if (dir == PFIL_OUT)
133254771Sandre		return (TAILQ_FIRST(&ph->ph_out));
134254771Sandre	else
135254771Sandre		return (NULL);
136254771Sandre}
137254771Sandre
138120386Ssam/*
139241888Smelifaro * pfil_try_rlock() acquires rm reader lock for specified head
140248490Sae * if this is immediately possible.
141241888Smelifaro */
142241888Smelifaroint
143241888Smelifaropfil_try_rlock(struct pfil_head *ph, struct rm_priotracker *tracker)
144241888Smelifaro{
145248490Sae
146248490Sae	return (PFIL_TRY_RLOCK(ph, tracker));
147241888Smelifaro}
148241888Smelifaro
149241888Smelifaro/*
150241888Smelifaro * pfil_rlock() acquires rm reader lock for specified head.
151241888Smelifaro */
152241888Smelifarovoid
153241888Smelifaropfil_rlock(struct pfil_head *ph, struct rm_priotracker *tracker)
154241888Smelifaro{
155248490Sae
156241888Smelifaro	PFIL_RLOCK(ph, tracker);
157241888Smelifaro}
158241888Smelifaro
159241888Smelifaro/*
160241888Smelifaro * pfil_runlock() releases reader lock for specified head.
161241888Smelifaro */
162241888Smelifarovoid
163241888Smelifaropfil_runlock(struct pfil_head *ph, struct rm_priotracker *tracker)
164241888Smelifaro{
165248490Sae
166241888Smelifaro	PFIL_RUNLOCK(ph, tracker);
167241888Smelifaro}
168241888Smelifaro
169241888Smelifaro/*
170241888Smelifaro * pfil_wlock() acquires writer lock for specified head.
171241888Smelifaro */
172241888Smelifarovoid
173241888Smelifaropfil_wlock(struct pfil_head *ph)
174241888Smelifaro{
175248490Sae
176241888Smelifaro	PFIL_WLOCK(ph);
177241888Smelifaro}
178241888Smelifaro
179241888Smelifaro/*
180241888Smelifaro * pfil_wunlock() releases writer lock for specified head.
181241888Smelifaro */
182241888Smelifarovoid
183241888Smelifaropfil_wunlock(struct pfil_head *ph)
184241888Smelifaro{
185248490Sae
186241888Smelifaro	PFIL_WUNLOCK(ph);
187241888Smelifaro}
188241888Smelifaro
189241888Smelifaro/*
190248490Sae * pfil_wowned() returns a non-zero value if the current thread owns
191248490Sae * an exclusive lock.
192241888Smelifaro */
193241888Smelifaroint
194241888Smelifaropfil_wowned(struct pfil_head *ph)
195241888Smelifaro{
196248490Sae
197248490Sae	return (PFIL_WOWNED(ph));
198241888Smelifaro}
199254773Sandre
200241888Smelifaro/*
201198233Srwatson * pfil_head_register() registers a pfil_head with the packet filter hook
202198233Srwatson * mechanism.
203120386Ssam */
204120386Ssamint
205120386Ssampfil_head_register(struct pfil_head *ph)
206120386Ssam{
207120386Ssam	struct pfil_head *lph;
208120386Ssam
209254774Sandre	PFIL_HEADLIST_LOCK();
210197952Sjulian	LIST_FOREACH(lph, &V_pfil_head_list, ph_list) {
211120386Ssam		if (ph->ph_type == lph->ph_type &&
212120386Ssam		    ph->ph_un.phu_val == lph->ph_un.phu_val) {
213254774Sandre			PFIL_HEADLIST_UNLOCK();
214198233Srwatson			return (EEXIST);
215120386Ssam		}
216186187Srwatson	}
217173904Smlaier	PFIL_LOCK_INIT(ph);
218155201Scsjp	ph->ph_nhooks = 0;
21960317Sdarrenr	TAILQ_INIT(&ph->ph_in);
22060317Sdarrenr	TAILQ_INIT(&ph->ph_out);
221197952Sjulian	LIST_INSERT_HEAD(&V_pfil_head_list, ph, ph_list);
222254774Sandre	PFIL_HEADLIST_UNLOCK();
223120386Ssam	return (0);
22460317Sdarrenr}
22560317Sdarrenr
22660317Sdarrenr/*
227186187Srwatson * pfil_head_unregister() removes a pfil_head from the packet filter hook
228186187Srwatson * mechanism.  The producer of the hook promises that all outstanding
229186187Srwatson * invocations of the hook have completed before it unregisters the hook.
230120386Ssam */
231120386Ssamint
232120386Ssampfil_head_unregister(struct pfil_head *ph)
233120386Ssam{
234120386Ssam	struct packet_filter_hook *pfh, *pfnext;
235120386Ssam
236254774Sandre	PFIL_HEADLIST_LOCK();
237120386Ssam	LIST_REMOVE(ph, ph_list);
238254774Sandre	PFIL_HEADLIST_UNLOCK();
239254773Sandre	TAILQ_FOREACH_SAFE(pfh, &ph->ph_in, pfil_chain, pfnext)
240120386Ssam		free(pfh, M_IFADDR);
241254773Sandre	TAILQ_FOREACH_SAFE(pfh, &ph->ph_out, pfil_chain, pfnext)
242120386Ssam		free(pfh, M_IFADDR);
243173904Smlaier	PFIL_LOCK_DESTROY(ph);
244120386Ssam	return (0);
245120386Ssam}
246120386Ssam
247120386Ssam/*
248120386Ssam * pfil_head_get() returns the pfil_head for a given key/dlt.
249120386Ssam */
250120386Ssamstruct pfil_head *
251120386Ssampfil_head_get(int type, u_long val)
252120386Ssam{
253120386Ssam	struct pfil_head *ph;
254120386Ssam
255254774Sandre	PFIL_HEADLIST_LOCK();
256197952Sjulian	LIST_FOREACH(ph, &V_pfil_head_list, ph_list)
257120386Ssam		if (ph->ph_type == type && ph->ph_un.phu_val == val)
258120386Ssam			break;
259254774Sandre	PFIL_HEADLIST_UNLOCK();
260120386Ssam	return (ph);
261120386Ssam}
262120386Ssam
263120386Ssam/*
264332513Skp * pfil_add_hook_flags() adds a function to the packet filter hook.  the
265332513Skp * flags are:
266332513Skp *	PFIL_IN		call me on incoming packets
267332513Skp *	PFIL_OUT	call me on outgoing packets
268332513Skp *	PFIL_ALL	call me on all of the above
269332513Skp *	PFIL_WAITOK	OK to call malloc with M_WAITOK.
270332513Skp */
271332513Skpint
272332513Skppfil_add_hook_flags(pfil_func_flags_t func, void *arg, int flags,
273332513Skp    struct pfil_head *ph)
274332513Skp{
275332513Skp	return (pfil_add_hook_priv(func, arg, flags, ph, true));
276332513Skp}
277332513Skp
278332513Skp/*
27960317Sdarrenr * pfil_add_hook() adds a function to the packet filter hook.  the
28060317Sdarrenr * flags are:
28160317Sdarrenr *	PFIL_IN		call me on incoming packets
28260317Sdarrenr *	PFIL_OUT	call me on outgoing packets
28360317Sdarrenr *	PFIL_ALL	call me on all of the above
284111119Simp *	PFIL_WAITOK	OK to call malloc with M_WAITOK.
28560317Sdarrenr */
28660317Sdarrenrint
287254769Sandrepfil_add_hook(pfil_func_t func, void *arg, int flags, struct pfil_head *ph)
28860317Sdarrenr{
289332513Skp	return (pfil_add_hook_priv(func, arg, flags, ph, false));
290332513Skp}
291332513Skp
292332513Skpstatic int
293332513Skppfil_add_hook_priv(void *func, void *arg, int flags,
294332513Skp    struct pfil_head *ph, bool hasflags)
295332513Skp{
296120386Ssam	struct packet_filter_hook *pfh1 = NULL;
297120386Ssam	struct packet_filter_hook *pfh2 = NULL;
298120386Ssam	int err;
29960317Sdarrenr
300120386Ssam	if (flags & PFIL_IN) {
301120386Ssam		pfh1 = (struct packet_filter_hook *)malloc(sizeof(*pfh1),
302120386Ssam		    M_IFADDR, (flags & PFIL_WAITOK) ? M_WAITOK : M_NOWAIT);
303120386Ssam		if (pfh1 == NULL) {
304120386Ssam			err = ENOMEM;
305120386Ssam			goto error;
306120386Ssam		}
307120386Ssam	}
308120386Ssam	if (flags & PFIL_OUT) {
309120386Ssam		pfh2 = (struct packet_filter_hook *)malloc(sizeof(*pfh1),
310120386Ssam		    M_IFADDR, (flags & PFIL_WAITOK) ? M_WAITOK : M_NOWAIT);
311120386Ssam		if (pfh2 == NULL) {
312120386Ssam			err = ENOMEM;
313120386Ssam			goto error;
314120386Ssam		}
315120386Ssam	}
316155201Scsjp	PFIL_WLOCK(ph);
317120386Ssam	if (flags & PFIL_IN) {
318332513Skp		pfh1->pfil_func_flags = hasflags ? func : NULL;
319332513Skp		pfh1->pfil_func = hasflags ? NULL : func;
320120386Ssam		pfh1->pfil_arg = arg;
321254773Sandre		err = pfil_chain_add(&ph->ph_in, pfh1, flags & ~PFIL_OUT);
322120386Ssam		if (err)
323186187Srwatson			goto locked_error;
324155201Scsjp		ph->ph_nhooks++;
325120386Ssam	}
326120386Ssam	if (flags & PFIL_OUT) {
327332513Skp		pfh2->pfil_func_flags = hasflags ? func : NULL;
328332513Skp		pfh2->pfil_func = hasflags ? NULL : func;
329120386Ssam		pfh2->pfil_arg = arg;
330254773Sandre		err = pfil_chain_add(&ph->ph_out, pfh2, flags & ~PFIL_IN);
331120386Ssam		if (err) {
332120386Ssam			if (flags & PFIL_IN)
333254773Sandre				pfil_chain_remove(&ph->ph_in, func, arg);
334186187Srwatson			goto locked_error;
335120386Ssam		}
336155201Scsjp		ph->ph_nhooks++;
337120386Ssam	}
338120386Ssam	PFIL_WUNLOCK(ph);
339198233Srwatson	return (0);
340186187Srwatsonlocked_error:
341120386Ssam	PFIL_WUNLOCK(ph);
342120386Ssamerror:
343120386Ssam	if (pfh1 != NULL)
344120386Ssam		free(pfh1, M_IFADDR);
345120386Ssam	if (pfh2 != NULL)
346120386Ssam		free(pfh2, M_IFADDR);
347198233Srwatson	return (err);
34860317Sdarrenr}
34960317Sdarrenr
35060317Sdarrenr/*
351332513Skp * pfil_remove_hook_flags removes a specific function from the packet filter hook
352332513Skp * chain.
353332513Skp */
354332513Skpint
355332513Skppfil_remove_hook_flags(pfil_func_flags_t func, void *arg, int flags,
356332513Skp    struct pfil_head *ph)
357332513Skp{
358332513Skp	return (pfil_remove_hook((pfil_func_t)func, arg, flags, ph));
359332513Skp}
360332513Skp
361332513Skp/*
362198233Srwatson * pfil_remove_hook removes a specific function from the packet filter hook
363254773Sandre * chain.
36460317Sdarrenr */
36560317Sdarrenrint
366254769Sandrepfil_remove_hook(pfil_func_t func, void *arg, int flags, struct pfil_head *ph)
36760317Sdarrenr{
36860317Sdarrenr	int err = 0;
36960317Sdarrenr
370155201Scsjp	PFIL_WLOCK(ph);
371155201Scsjp	if (flags & PFIL_IN) {
372254773Sandre		err = pfil_chain_remove(&ph->ph_in, func, arg);
373155201Scsjp		if (err == 0)
374155201Scsjp			ph->ph_nhooks--;
375155201Scsjp	}
376155201Scsjp	if ((err == 0) && (flags & PFIL_OUT)) {
377254773Sandre		err = pfil_chain_remove(&ph->ph_out, func, arg);
378155201Scsjp		if (err == 0)
379155201Scsjp			ph->ph_nhooks--;
380155201Scsjp	}
381120386Ssam	PFIL_WUNLOCK(ph);
382198233Srwatson	return (err);
38360317Sdarrenr}
38460317Sdarrenr
385254773Sandre/*
386254773Sandre * Internal: Add a new pfil hook into a hook chain.
387254773Sandre */
388120386Ssamstatic int
389254773Sandrepfil_chain_add(pfil_chain_t *chain, struct packet_filter_hook *pfh1, int flags)
390120386Ssam{
391120386Ssam	struct packet_filter_hook *pfh;
392120386Ssam
393120386Ssam	/*
394120386Ssam	 * First make sure the hook is not already there.
395120386Ssam	 */
396254773Sandre	TAILQ_FOREACH(pfh, chain, pfil_chain)
397332513Skp		if (((pfh->pfil_func != NULL && pfh->pfil_func == pfh1->pfil_func) ||
398332513Skp		    (pfh->pfil_func_flags != NULL &&
399332513Skp		     pfh->pfil_func_flags == pfh1->pfil_func_flags)) &&
400120386Ssam		    pfh->pfil_arg == pfh1->pfil_arg)
401198233Srwatson			return (EEXIST);
402198233Srwatson
403120386Ssam	/*
404198233Srwatson	 * Insert the input list in reverse order of the output list so that
405198233Srwatson	 * the same path is followed in or out of the kernel.
406120386Ssam	 */
407120386Ssam	if (flags & PFIL_IN)
408254773Sandre		TAILQ_INSERT_HEAD(chain, pfh1, pfil_chain);
409120386Ssam	else
410254773Sandre		TAILQ_INSERT_TAIL(chain, pfh1, pfil_chain);
411198233Srwatson	return (0);
412120386Ssam}
413120386Ssam
41460317Sdarrenr/*
415254773Sandre * Internal: Remove a pfil hook from a hook chain.
41660317Sdarrenr */
41760317Sdarrenrstatic int
418332513Skppfil_chain_remove(pfil_chain_t *chain, void *func, void *arg)
41960317Sdarrenr{
42060317Sdarrenr	struct packet_filter_hook *pfh;
42160317Sdarrenr
422254773Sandre	TAILQ_FOREACH(pfh, chain, pfil_chain)
423332513Skp		if ((pfh->pfil_func == func || pfh->pfil_func_flags == func) &&
424332513Skp		    pfh->pfil_arg == arg) {
425254773Sandre			TAILQ_REMOVE(chain, pfh, pfil_chain);
42660317Sdarrenr			free(pfh, M_IFADDR);
427198233Srwatson			return (0);
42860317Sdarrenr		}
429198233Srwatson	return (ENOENT);
43060317Sdarrenr}
431197952Sjulian
432198233Srwatson/*
433198233Srwatson * Stuff that must be initialized for every instance (including the first of
434198233Srwatson * course).
435197952Sjulian */
436301503Sbzstatic void
437301503Sbzvnet_pfil_init(const void *unused __unused)
438197952Sjulian{
439198233Srwatson
440197952Sjulian	LIST_INIT(&V_pfil_head_list);
441241888Smelifaro	PFIL_LOCK_INIT_REAL(&V_pfil_lock, "shared");
442197952Sjulian}
443197952Sjulian
444198233Srwatson/*
445197952Sjulian * Called for the removal of each instance.
446197952Sjulian */
447301503Sbzstatic void
448301503Sbzvnet_pfil_uninit(const void *unused __unused)
449197952Sjulian{
450198233Srwatson
451254773Sandre	KASSERT(LIST_EMPTY(&V_pfil_head_list),
452254773Sandre	    ("%s: pfil_head_list %p not empty", __func__, &V_pfil_head_list));
453241888Smelifaro	PFIL_LOCK_DESTROY_REAL(&V_pfil_lock);
454197952Sjulian}
455197952Sjulian
456197952Sjulian/*
457198233Srwatson * Starting up.
458198233Srwatson *
459197952Sjulian * VNET_SYSINIT is called for each existing vnet and each new vnet.
460302054Sbz * Make sure the pfil bits are first before any possible subsystem which
461302054Sbz * might piggyback on the SI_SUB_PROTO_PFIL.
462197952Sjulian */
463302054SbzVNET_SYSINIT(vnet_pfil_init, SI_SUB_PROTO_PFIL, SI_ORDER_FIRST,
464198233Srwatson    vnet_pfil_init, NULL);
465197952Sjulian
466197952Sjulian/*
467198233Srwatson * Closing up shop.  These are done in REVERSE ORDER.  Not called on reboot.
468198233Srwatson *
469197952Sjulian * VNET_SYSUNINIT is called for each exiting vnet as it exits.
470197952Sjulian */
471302054SbzVNET_SYSUNINIT(vnet_pfil_uninit, SI_SUB_PROTO_PFIL, SI_ORDER_FIRST,
472198233Srwatson    vnet_pfil_uninit, NULL);
473