1e9c7bebfSDarren Reed /* $FreeBSD$ */ 2134ea224SSam Leffler /* $NetBSD: pfil.c,v 1.20 2001/11/12 23:49:46 lukem Exp $ */ 3e9c7bebfSDarren Reed 4c398230bSWarner Losh /*- 5e9c7bebfSDarren Reed * Copyright (c) 1996 Matthew R. Green 6e9c7bebfSDarren Reed * All rights reserved. 7e9c7bebfSDarren Reed * 8e9c7bebfSDarren Reed * Redistribution and use in source and binary forms, with or without 9e9c7bebfSDarren Reed * modification, are permitted provided that the following conditions 10e9c7bebfSDarren Reed * are met: 11e9c7bebfSDarren Reed * 1. Redistributions of source code must retain the above copyright 12e9c7bebfSDarren Reed * notice, this list of conditions and the following disclaimer. 13e9c7bebfSDarren Reed * 2. Redistributions in binary form must reproduce the above copyright 14e9c7bebfSDarren Reed * notice, this list of conditions and the following disclaimer in the 15e9c7bebfSDarren Reed * documentation and/or other materials provided with the distribution. 16e9c7bebfSDarren Reed * 3. The name of the author may not be used to endorse or promote products 17e9c7bebfSDarren Reed * derived from this software without specific prior written permission. 18e9c7bebfSDarren Reed * 19e9c7bebfSDarren Reed * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20e9c7bebfSDarren Reed * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21e9c7bebfSDarren Reed * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22e9c7bebfSDarren Reed * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23e9c7bebfSDarren Reed * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24e9c7bebfSDarren Reed * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25e9c7bebfSDarren Reed * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 26e9c7bebfSDarren Reed * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27e9c7bebfSDarren Reed * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28e9c7bebfSDarren Reed * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29e9c7bebfSDarren Reed * SUCH DAMAGE. 30e9c7bebfSDarren Reed */ 31e9c7bebfSDarren Reed 32e9c7bebfSDarren Reed #include <sys/param.h> 33134ea224SSam Leffler #include <sys/kernel.h> 34e9c7bebfSDarren Reed #include <sys/errno.h> 35604afec4SChristian S.J. Peron #include <sys/lock.h> 36e9c7bebfSDarren Reed #include <sys/malloc.h> 371030a1a9SMax Laier #include <sys/rmlock.h> 38e9c7bebfSDarren Reed #include <sys/socket.h> 39e9c7bebfSDarren Reed #include <sys/socketvar.h> 40e9c7bebfSDarren Reed #include <sys/systm.h> 41134ea224SSam Leffler #include <sys/condvar.h> 42134ea224SSam Leffler #include <sys/lock.h> 43134ea224SSam Leffler #include <sys/mutex.h> 44134ea224SSam Leffler #include <sys/proc.h> 45e9c7bebfSDarren Reed #include <sys/queue.h> 46e9c7bebfSDarren Reed 47e9c7bebfSDarren Reed #include <net/if.h> 4876039bc8SGleb Smirnoff #include <net/if_var.h> 49e9c7bebfSDarren Reed #include <net/pfil.h> 50e9c7bebfSDarren Reed 51134ea224SSam Leffler static struct mtx pfil_global_lock; 52e9c7bebfSDarren Reed 5333c89765SRobert Watson MTX_SYSINIT(pfil_heads_lock, &pfil_global_lock, "pfil_head_list lock", 5433c89765SRobert Watson MTX_DEF); 55134ea224SSam Leffler 568da01399SAndre Oppermann static struct packet_filter_hook *pfil_chain_get(int, struct pfil_head *); 578da01399SAndre Oppermann static int pfil_chain_add(pfil_chain_t *, struct packet_filter_hook *, int); 588da01399SAndre Oppermann static int pfil_chain_remove(pfil_chain_t *, pfil_func_t, void *); 59134ea224SSam Leffler 600b4b0b0fSJulian Elischer LIST_HEAD(pfilheadhead, pfil_head); 610b4b0b0fSJulian Elischer VNET_DEFINE(struct pfilheadhead, pfil_head_list); 620b4b0b0fSJulian Elischer #define V_pfil_head_list VNET(pfil_head_list) 634dab1a18SAlexander V. Chernikov VNET_DEFINE(struct rmlock, pfil_lock); 644dab1a18SAlexander V. Chernikov #define V_pfil_lock VNET(pfil_lock) 65134ea224SSam Leffler 66134ea224SSam Leffler /* 678da01399SAndre Oppermann * pfil_run_hooks() runs the specified packet filter hook chain. 68134ea224SSam Leffler */ 69134ea224SSam Leffler int 70134ea224SSam Leffler pfil_run_hooks(struct pfil_head *ph, struct mbuf **mp, struct ifnet *ifp, 71d6a8d588SMax Laier int dir, struct inpcb *inp) 72134ea224SSam Leffler { 731030a1a9SMax Laier struct rm_priotracker rmpt; 74134ea224SSam Leffler struct packet_filter_hook *pfh; 75134ea224SSam Leffler struct mbuf *m = *mp; 76134ea224SSam Leffler int rv = 0; 77134ea224SSam Leffler 781030a1a9SMax Laier PFIL_RLOCK(ph, &rmpt); 79604afec4SChristian S.J. Peron KASSERT(ph->ph_nhooks >= 0, ("Pfil hook count dropped < 0")); 808da01399SAndre Oppermann for (pfh = pfil_chain_get(dir, ph); pfh != NULL; 818da01399SAndre Oppermann pfh = TAILQ_NEXT(pfh, pfil_chain)) { 82134ea224SSam Leffler if (pfh->pfil_func != NULL) { 8333c89765SRobert Watson rv = (*pfh->pfil_func)(pfh->pfil_arg, &m, ifp, dir, 8433c89765SRobert Watson inp); 85134ea224SSam Leffler if (rv != 0 || m == NULL) 86134ea224SSam Leffler break; 87134ea224SSam Leffler } 88134ea224SSam Leffler } 891030a1a9SMax Laier PFIL_RUNLOCK(ph, &rmpt); 90134ea224SSam Leffler *mp = m; 91134ea224SSam Leffler return (rv); 92134ea224SSam Leffler } 93134ea224SSam Leffler 94887c60fcSAndre Oppermann static struct packet_filter_hook * 958da01399SAndre Oppermann pfil_chain_get(int dir, struct pfil_head *ph) 96887c60fcSAndre Oppermann { 97887c60fcSAndre Oppermann 98887c60fcSAndre Oppermann if (dir == PFIL_IN) 99887c60fcSAndre Oppermann return (TAILQ_FIRST(&ph->ph_in)); 100887c60fcSAndre Oppermann else if (dir == PFIL_OUT) 101887c60fcSAndre Oppermann return (TAILQ_FIRST(&ph->ph_out)); 102887c60fcSAndre Oppermann else 103887c60fcSAndre Oppermann return (NULL); 104887c60fcSAndre Oppermann } 105887c60fcSAndre Oppermann 106134ea224SSam Leffler /* 1074dab1a18SAlexander V. Chernikov * pfil_try_rlock() acquires rm reader lock for specified head 1085474386bSAndrey V. Elsukov * if this is immediately possible. 1094dab1a18SAlexander V. Chernikov */ 1104dab1a18SAlexander V. Chernikov int 1114dab1a18SAlexander V. Chernikov pfil_try_rlock(struct pfil_head *ph, struct rm_priotracker *tracker) 1124dab1a18SAlexander V. Chernikov { 1135474386bSAndrey V. Elsukov 1145474386bSAndrey V. Elsukov return (PFIL_TRY_RLOCK(ph, tracker)); 1154dab1a18SAlexander V. Chernikov } 1164dab1a18SAlexander V. Chernikov 1174dab1a18SAlexander V. Chernikov /* 1184dab1a18SAlexander V. Chernikov * pfil_rlock() acquires rm reader lock for specified head. 1194dab1a18SAlexander V. Chernikov */ 1204dab1a18SAlexander V. Chernikov void 1214dab1a18SAlexander V. Chernikov pfil_rlock(struct pfil_head *ph, struct rm_priotracker *tracker) 1224dab1a18SAlexander V. Chernikov { 1235474386bSAndrey V. Elsukov 1244dab1a18SAlexander V. Chernikov PFIL_RLOCK(ph, tracker); 1254dab1a18SAlexander V. Chernikov } 1264dab1a18SAlexander V. Chernikov 1274dab1a18SAlexander V. Chernikov /* 1284dab1a18SAlexander V. Chernikov * pfil_runlock() releases reader lock for specified head. 1294dab1a18SAlexander V. Chernikov */ 1304dab1a18SAlexander V. Chernikov void 1314dab1a18SAlexander V. Chernikov pfil_runlock(struct pfil_head *ph, struct rm_priotracker *tracker) 1324dab1a18SAlexander V. Chernikov { 1335474386bSAndrey V. Elsukov 1344dab1a18SAlexander V. Chernikov PFIL_RUNLOCK(ph, tracker); 1354dab1a18SAlexander V. Chernikov } 1364dab1a18SAlexander V. Chernikov 1374dab1a18SAlexander V. Chernikov /* 1384dab1a18SAlexander V. Chernikov * pfil_wlock() acquires writer lock for specified head. 1394dab1a18SAlexander V. Chernikov */ 1404dab1a18SAlexander V. Chernikov void 1414dab1a18SAlexander V. Chernikov pfil_wlock(struct pfil_head *ph) 1424dab1a18SAlexander V. Chernikov { 1435474386bSAndrey V. Elsukov 1444dab1a18SAlexander V. Chernikov PFIL_WLOCK(ph); 1454dab1a18SAlexander V. Chernikov } 1464dab1a18SAlexander V. Chernikov 1474dab1a18SAlexander V. Chernikov /* 1484dab1a18SAlexander V. Chernikov * pfil_wunlock() releases writer lock for specified head. 1494dab1a18SAlexander V. Chernikov */ 1504dab1a18SAlexander V. Chernikov void 1514dab1a18SAlexander V. Chernikov pfil_wunlock(struct pfil_head *ph) 1524dab1a18SAlexander V. Chernikov { 1535474386bSAndrey V. Elsukov 1544dab1a18SAlexander V. Chernikov PFIL_WUNLOCK(ph); 1554dab1a18SAlexander V. Chernikov } 1564dab1a18SAlexander V. Chernikov 1574dab1a18SAlexander V. Chernikov /* 1585474386bSAndrey V. Elsukov * pfil_wowned() returns a non-zero value if the current thread owns 1595474386bSAndrey V. Elsukov * an exclusive lock. 1604dab1a18SAlexander V. Chernikov */ 1614dab1a18SAlexander V. Chernikov int 1624dab1a18SAlexander V. Chernikov pfil_wowned(struct pfil_head *ph) 1634dab1a18SAlexander V. Chernikov { 1645474386bSAndrey V. Elsukov 1655474386bSAndrey V. Elsukov return (PFIL_WOWNED(ph)); 1664dab1a18SAlexander V. Chernikov } 1678da01399SAndre Oppermann 1684dab1a18SAlexander V. Chernikov /* 169cee81198SRobert Watson * pfil_head_register() registers a pfil_head with the packet filter hook 170cee81198SRobert Watson * mechanism. 171134ea224SSam Leffler */ 172134ea224SSam Leffler int 173134ea224SSam Leffler pfil_head_register(struct pfil_head *ph) 174134ea224SSam Leffler { 175134ea224SSam Leffler struct pfil_head *lph; 176134ea224SSam Leffler 177737003b3SAndre Oppermann PFIL_HEADLIST_LOCK(); 1780b4b0b0fSJulian Elischer LIST_FOREACH(lph, &V_pfil_head_list, ph_list) { 179134ea224SSam Leffler if (ph->ph_type == lph->ph_type && 180134ea224SSam Leffler ph->ph_un.phu_val == lph->ph_un.phu_val) { 181737003b3SAndre Oppermann PFIL_HEADLIST_UNLOCK(); 182cee81198SRobert Watson return (EEXIST); 183134ea224SSam Leffler } 184d2c205d5SRobert Watson } 1851030a1a9SMax Laier PFIL_LOCK_INIT(ph); 186604afec4SChristian S.J. Peron ph->ph_nhooks = 0; 187e9c7bebfSDarren Reed TAILQ_INIT(&ph->ph_in); 188e9c7bebfSDarren Reed TAILQ_INIT(&ph->ph_out); 1890b4b0b0fSJulian Elischer LIST_INSERT_HEAD(&V_pfil_head_list, ph, ph_list); 190737003b3SAndre Oppermann PFIL_HEADLIST_UNLOCK(); 191134ea224SSam Leffler return (0); 192134ea224SSam Leffler } 193134ea224SSam Leffler 194134ea224SSam Leffler /* 195d2c205d5SRobert Watson * pfil_head_unregister() removes a pfil_head from the packet filter hook 196d2c205d5SRobert Watson * mechanism. The producer of the hook promises that all outstanding 197d2c205d5SRobert Watson * invocations of the hook have completed before it unregisters the hook. 198134ea224SSam Leffler */ 199134ea224SSam Leffler int 200134ea224SSam Leffler pfil_head_unregister(struct pfil_head *ph) 201134ea224SSam Leffler { 202134ea224SSam Leffler struct packet_filter_hook *pfh, *pfnext; 203134ea224SSam Leffler 204737003b3SAndre Oppermann PFIL_HEADLIST_LOCK(); 205134ea224SSam Leffler LIST_REMOVE(ph, ph_list); 206737003b3SAndre Oppermann PFIL_HEADLIST_UNLOCK(); 2078da01399SAndre Oppermann TAILQ_FOREACH_SAFE(pfh, &ph->ph_in, pfil_chain, pfnext) 208134ea224SSam Leffler free(pfh, M_IFADDR); 2098da01399SAndre Oppermann TAILQ_FOREACH_SAFE(pfh, &ph->ph_out, pfil_chain, pfnext) 210134ea224SSam Leffler free(pfh, M_IFADDR); 2111030a1a9SMax Laier PFIL_LOCK_DESTROY(ph); 212134ea224SSam Leffler return (0); 213134ea224SSam Leffler } 214134ea224SSam Leffler 215134ea224SSam Leffler /* 216134ea224SSam Leffler * pfil_head_get() returns the pfil_head for a given key/dlt. 217134ea224SSam Leffler */ 218134ea224SSam Leffler struct pfil_head * 219134ea224SSam Leffler pfil_head_get(int type, u_long val) 220134ea224SSam Leffler { 221134ea224SSam Leffler struct pfil_head *ph; 222134ea224SSam Leffler 223737003b3SAndre Oppermann PFIL_HEADLIST_LOCK(); 2240b4b0b0fSJulian Elischer LIST_FOREACH(ph, &V_pfil_head_list, ph_list) 225134ea224SSam Leffler if (ph->ph_type == type && ph->ph_un.phu_val == val) 226134ea224SSam Leffler break; 227737003b3SAndre Oppermann PFIL_HEADLIST_UNLOCK(); 228134ea224SSam Leffler return (ph); 229e9c7bebfSDarren Reed } 230e9c7bebfSDarren Reed 231e9c7bebfSDarren Reed /* 232e9c7bebfSDarren Reed * pfil_add_hook() adds a function to the packet filter hook. the 233e9c7bebfSDarren Reed * flags are: 234e9c7bebfSDarren Reed * PFIL_IN call me on incoming packets 235e9c7bebfSDarren Reed * PFIL_OUT call me on outgoing packets 236e9c7bebfSDarren Reed * PFIL_ALL call me on all of the above 237a163d034SWarner Losh * PFIL_WAITOK OK to call malloc with M_WAITOK. 238e9c7bebfSDarren Reed */ 239e9c7bebfSDarren Reed int 24025da5060SAndre Oppermann pfil_add_hook(pfil_func_t func, void *arg, int flags, struct pfil_head *ph) 241e9c7bebfSDarren Reed { 242134ea224SSam Leffler struct packet_filter_hook *pfh1 = NULL; 243134ea224SSam Leffler struct packet_filter_hook *pfh2 = NULL; 244134ea224SSam Leffler int err; 245e9c7bebfSDarren Reed 246134ea224SSam Leffler if (flags & PFIL_IN) { 247134ea224SSam Leffler pfh1 = (struct packet_filter_hook *)malloc(sizeof(*pfh1), 248134ea224SSam Leffler M_IFADDR, (flags & PFIL_WAITOK) ? M_WAITOK : M_NOWAIT); 249134ea224SSam Leffler if (pfh1 == NULL) { 250134ea224SSam Leffler err = ENOMEM; 251134ea224SSam Leffler goto error; 252134ea224SSam Leffler } 253134ea224SSam Leffler } 254134ea224SSam Leffler if (flags & PFIL_OUT) { 255134ea224SSam Leffler pfh2 = (struct packet_filter_hook *)malloc(sizeof(*pfh1), 256134ea224SSam Leffler M_IFADDR, (flags & PFIL_WAITOK) ? M_WAITOK : M_NOWAIT); 257134ea224SSam Leffler if (pfh2 == NULL) { 258134ea224SSam Leffler err = ENOMEM; 259134ea224SSam Leffler goto error; 260134ea224SSam Leffler } 261134ea224SSam Leffler } 262134ea224SSam Leffler PFIL_WLOCK(ph); 263134ea224SSam Leffler if (flags & PFIL_IN) { 264134ea224SSam Leffler pfh1->pfil_func = func; 265134ea224SSam Leffler pfh1->pfil_arg = arg; 2668da01399SAndre Oppermann err = pfil_chain_add(&ph->ph_in, pfh1, flags & ~PFIL_OUT); 267134ea224SSam Leffler if (err) 268d2c205d5SRobert Watson goto locked_error; 269604afec4SChristian S.J. Peron ph->ph_nhooks++; 270134ea224SSam Leffler } 271134ea224SSam Leffler if (flags & PFIL_OUT) { 272134ea224SSam Leffler pfh2->pfil_func = func; 273134ea224SSam Leffler pfh2->pfil_arg = arg; 2748da01399SAndre Oppermann err = pfil_chain_add(&ph->ph_out, pfh2, flags & ~PFIL_IN); 275e9c7bebfSDarren Reed if (err) { 276e9c7bebfSDarren Reed if (flags & PFIL_IN) 2778da01399SAndre Oppermann pfil_chain_remove(&ph->ph_in, func, arg); 278d2c205d5SRobert Watson goto locked_error; 279134ea224SSam Leffler } 280604afec4SChristian S.J. Peron ph->ph_nhooks++; 281134ea224SSam Leffler } 282134ea224SSam Leffler PFIL_WUNLOCK(ph); 283cee81198SRobert Watson return (0); 284d2c205d5SRobert Watson locked_error: 285134ea224SSam Leffler PFIL_WUNLOCK(ph); 286134ea224SSam Leffler error: 287134ea224SSam Leffler if (pfh1 != NULL) 288134ea224SSam Leffler free(pfh1, M_IFADDR); 289134ea224SSam Leffler if (pfh2 != NULL) 290134ea224SSam Leffler free(pfh2, M_IFADDR); 291cee81198SRobert Watson return (err); 292e9c7bebfSDarren Reed } 293e9c7bebfSDarren Reed 294e9c7bebfSDarren Reed /* 295cee81198SRobert Watson * pfil_remove_hook removes a specific function from the packet filter hook 2968da01399SAndre Oppermann * chain. 297e9c7bebfSDarren Reed */ 298e9c7bebfSDarren Reed int 29925da5060SAndre Oppermann pfil_remove_hook(pfil_func_t func, void *arg, int flags, struct pfil_head *ph) 300e9c7bebfSDarren Reed { 301e9c7bebfSDarren Reed int err = 0; 302e9c7bebfSDarren Reed 303134ea224SSam Leffler PFIL_WLOCK(ph); 304604afec4SChristian S.J. Peron if (flags & PFIL_IN) { 3058da01399SAndre Oppermann err = pfil_chain_remove(&ph->ph_in, func, arg); 306604afec4SChristian S.J. Peron if (err == 0) 307604afec4SChristian S.J. Peron ph->ph_nhooks--; 308604afec4SChristian S.J. Peron } 309604afec4SChristian S.J. Peron if ((err == 0) && (flags & PFIL_OUT)) { 3108da01399SAndre Oppermann err = pfil_chain_remove(&ph->ph_out, func, arg); 311604afec4SChristian S.J. Peron if (err == 0) 312604afec4SChristian S.J. Peron ph->ph_nhooks--; 313604afec4SChristian S.J. Peron } 314134ea224SSam Leffler PFIL_WUNLOCK(ph); 315cee81198SRobert Watson return (err); 316e9c7bebfSDarren Reed } 317e9c7bebfSDarren Reed 3188da01399SAndre Oppermann /* 3198da01399SAndre Oppermann * Internal: Add a new pfil hook into a hook chain. 3208da01399SAndre Oppermann */ 321134ea224SSam Leffler static int 3228da01399SAndre Oppermann pfil_chain_add(pfil_chain_t *chain, struct packet_filter_hook *pfh1, int flags) 323134ea224SSam Leffler { 324134ea224SSam Leffler struct packet_filter_hook *pfh; 325134ea224SSam Leffler 326134ea224SSam Leffler /* 327134ea224SSam Leffler * First make sure the hook is not already there. 328134ea224SSam Leffler */ 3298da01399SAndre Oppermann TAILQ_FOREACH(pfh, chain, pfil_chain) 330134ea224SSam Leffler if (pfh->pfil_func == pfh1->pfil_func && 331134ea224SSam Leffler pfh->pfil_arg == pfh1->pfil_arg) 332cee81198SRobert Watson return (EEXIST); 333cee81198SRobert Watson 334134ea224SSam Leffler /* 335cee81198SRobert Watson * Insert the input list in reverse order of the output list so that 336cee81198SRobert Watson * the same path is followed in or out of the kernel. 337134ea224SSam Leffler */ 338134ea224SSam Leffler if (flags & PFIL_IN) 3398da01399SAndre Oppermann TAILQ_INSERT_HEAD(chain, pfh1, pfil_chain); 340134ea224SSam Leffler else 3418da01399SAndre Oppermann TAILQ_INSERT_TAIL(chain, pfh1, pfil_chain); 342cee81198SRobert Watson return (0); 343134ea224SSam Leffler } 344134ea224SSam Leffler 345e9c7bebfSDarren Reed /* 3468da01399SAndre Oppermann * Internal: Remove a pfil hook from a hook chain. 347e9c7bebfSDarren Reed */ 348e9c7bebfSDarren Reed static int 3498da01399SAndre Oppermann pfil_chain_remove(pfil_chain_t *chain, pfil_func_t func, void *arg) 350e9c7bebfSDarren Reed { 351e9c7bebfSDarren Reed struct packet_filter_hook *pfh; 352e9c7bebfSDarren Reed 3538da01399SAndre Oppermann TAILQ_FOREACH(pfh, chain, pfil_chain) 354134ea224SSam Leffler if (pfh->pfil_func == func && pfh->pfil_arg == arg) { 3558da01399SAndre Oppermann TAILQ_REMOVE(chain, pfh, pfil_chain); 356e9c7bebfSDarren Reed free(pfh, M_IFADDR); 357cee81198SRobert Watson return (0); 358e9c7bebfSDarren Reed } 359cee81198SRobert Watson return (ENOENT); 360e9c7bebfSDarren Reed } 3610b4b0b0fSJulian Elischer 362cee81198SRobert Watson /* 363cee81198SRobert Watson * Stuff that must be initialized for every instance (including the first of 364cee81198SRobert Watson * course). 3650b4b0b0fSJulian Elischer */ 366*b9dbac48SBjoern A. Zeeb static void 367*b9dbac48SBjoern A. Zeeb vnet_pfil_init(const void *unused __unused) 3680b4b0b0fSJulian Elischer { 369cee81198SRobert Watson 3700b4b0b0fSJulian Elischer LIST_INIT(&V_pfil_head_list); 3714dab1a18SAlexander V. Chernikov PFIL_LOCK_INIT_REAL(&V_pfil_lock, "shared"); 3720b4b0b0fSJulian Elischer } 3730b4b0b0fSJulian Elischer 374cee81198SRobert Watson /* 3750b4b0b0fSJulian Elischer * Called for the removal of each instance. 3760b4b0b0fSJulian Elischer */ 377*b9dbac48SBjoern A. Zeeb static void 378*b9dbac48SBjoern A. Zeeb vnet_pfil_uninit(const void *unused __unused) 3790b4b0b0fSJulian Elischer { 380cee81198SRobert Watson 3818da01399SAndre Oppermann KASSERT(LIST_EMPTY(&V_pfil_head_list), 3828da01399SAndre Oppermann ("%s: pfil_head_list %p not empty", __func__, &V_pfil_head_list)); 3834dab1a18SAlexander V. Chernikov PFIL_LOCK_DESTROY_REAL(&V_pfil_lock); 3840b4b0b0fSJulian Elischer } 3850b4b0b0fSJulian Elischer 3860b4b0b0fSJulian Elischer /* Define startup order. */ 3870b4b0b0fSJulian Elischer #define PFIL_SYSINIT_ORDER SI_SUB_PROTO_BEGIN 3880b4b0b0fSJulian Elischer #define PFIL_MODEVENT_ORDER (SI_ORDER_FIRST) /* On boot slot in here. */ 3890b4b0b0fSJulian Elischer #define PFIL_VNET_ORDER (PFIL_MODEVENT_ORDER + 2) /* Later still. */ 3900b4b0b0fSJulian Elischer 3910b4b0b0fSJulian Elischer /* 3920b4b0b0fSJulian Elischer * Starting up. 393cee81198SRobert Watson * 3940b4b0b0fSJulian Elischer * VNET_SYSINIT is called for each existing vnet and each new vnet. 3950b4b0b0fSJulian Elischer */ 3960b4b0b0fSJulian Elischer VNET_SYSINIT(vnet_pfil_init, PFIL_SYSINIT_ORDER, PFIL_VNET_ORDER, 3970b4b0b0fSJulian Elischer vnet_pfil_init, NULL); 3980b4b0b0fSJulian Elischer 3990b4b0b0fSJulian Elischer /* 400cee81198SRobert Watson * Closing up shop. These are done in REVERSE ORDER. Not called on reboot. 401cee81198SRobert Watson * 4020b4b0b0fSJulian Elischer * VNET_SYSUNINIT is called for each exiting vnet as it exits. 4030b4b0b0fSJulian Elischer */ 4040b4b0b0fSJulian Elischer VNET_SYSUNINIT(vnet_pfil_uninit, PFIL_SYSINIT_ORDER, PFIL_VNET_ORDER, 4050b4b0b0fSJulian Elischer vnet_pfil_uninit, NULL); 406