Index: net/bridge.c =================================================================== RCS file: /usr/store/mlaier/fcvs/src/sys/net/bridge.c,v retrieving revision 1.82.2.4 diff -u -r1.82.2.4 bridge.c --- net/bridge.c 31 Jan 2005 23:26:22 -0000 1.82.2.4 +++ net/bridge.c 4 Apr 2005 14:53:56 -0000 @@ -961,7 +961,7 @@ * and pkts already gone through a pipe. */ if (src != NULL && ( - (inet_pfil_hook.ph_busy_count >= 0 && bdg_ipf != 0) || + (inet_pfil_hook.ph_size > 0 && bdg_ipf != 0) || (IPFW_LOADED && bdg_ipfw != 0))) { int i; @@ -997,7 +997,7 @@ * Enables ipf(8) in bridging. */ if (!IPFW_LOADED) { /* XXX: Prevent ipfw from being run twice. */ - if (inet_pfil_hook.ph_busy_count >= 0 && + if (inet_pfil_hook.ph_size > 0 && m0->m_pkthdr.len >= sizeof(struct ip) && ntohs(save_eh.ether_type) == ETHERTYPE_IP) { /* Index: net/pfil.c =================================================================== RCS file: /usr/store/mlaier/fcvs/src/sys/net/pfil.c,v retrieving revision 1.8.4.4 diff -u -r1.8.4.4 pfil.c --- net/pfil.c 31 Jan 2005 23:26:23 -0000 1.8.4.4 +++ net/pfil.c 4 Apr 2005 19:04:29 -0000 @@ -2,6 +2,7 @@ /* $NetBSD: pfil.c,v 1.20 2001/11/12 23:49:46 lukem Exp $ */ /*- + * Copyright (c) 2005 Max Laier * Copyright (c) 1996 Matthew R. Green * All rights reserved. * @@ -31,12 +32,12 @@ #include #include +#include #include #include #include #include #include -#include #include #include #include @@ -46,68 +47,31 @@ #include static struct mtx pfil_global_lock; - -MTX_SYSINIT(pfil_heads_lock, &pfil_global_lock, "pfil_head_list lock", MTX_DEF); - -static int pfil_list_add(pfil_list_t *, struct packet_filter_hook *, int); - -static int pfil_list_remove(pfil_list_t *, - int (*)(void *, struct mbuf **, struct ifnet *, int, struct inpcb *), void *); - -LIST_HEAD(, pfil_head) pfil_head_list = - LIST_HEAD_INITIALIZER(&pfil_head_list); - -static __inline void -PFIL_RLOCK(struct pfil_head *ph) -{ - mtx_lock(&ph->ph_mtx); - ph->ph_busy_count++; - mtx_unlock(&ph->ph_mtx); -} - -static __inline void -PFIL_RUNLOCK(struct pfil_head *ph) -{ - mtx_lock(&ph->ph_mtx); - ph->ph_busy_count--; - if (ph->ph_busy_count == 0 && ph->ph_want_write) - cv_signal(&ph->ph_cv); - mtx_unlock(&ph->ph_mtx); -} - -static __inline void -PFIL_WLOCK(struct pfil_head *ph) +static struct packet_filter_hook _pfil_empty = { - mtx_lock(&ph->ph_mtx); - ph->ph_want_write = 1; - while (ph->ph_busy_count > 0) - cv_wait(&ph->ph_cv, &ph->ph_mtx); -} + .pfil_next = PFIL_END, + .pfil_prev = PFIL_END, + .pfil_func = NULL, + .pfil_arg = NULL +}; + +static int pfil_slots = 8; +SYSCTL_NODE(_net, OID_AUTO, pfil, CTLFLAG_RW, 0, "pfil(9)"); +SYSCTL_INT(_net_pfil, OID_AUTO, slots, CTLFLAG_RW, &pfil_slots, 0, + "Number of slots/hooks per pfil head"); -static __inline int -PFIL_TRY_WLOCK(struct pfil_head *ph) -{ - mtx_lock(&ph->ph_mtx); - ph->ph_want_write = 1; - if (ph->ph_busy_count > 0) { - ph->ph_want_write = 0; - mtx_unlock(&ph->ph_mtx); - return EBUSY; - } - return 0; -} +MTX_SYSINIT(pfil_heads_lock, &pfil_global_lock, "pfil_head_list lock", MTX_DEF); -static __inline void -PFIL_WUNLOCK(struct pfil_head *ph) -{ - ph->ph_want_write = 0; - cv_signal(&ph->ph_cv); - mtx_unlock(&ph->ph_mtx); -} +LIST_HEAD(, pfil_head) pfil_head_list = LIST_HEAD_INITIALIZER(&pfil_head_list); #define PFIL_LIST_LOCK() mtx_lock(&pfil_global_lock) #define PFIL_LIST_UNLOCK() mtx_unlock(&pfil_global_lock) +static void pfil_list_add(struct pfil_head *ph, int dir, int pos, + int (*func)(void *, struct mbuf **, struct ifnet *, int, struct inpcb *), + void *arg); +static void pfil_list_remove(struct pfil_head *ph, int dir, int pos); + /* * pfil_run_hooks() runs the specified packet filter hooks. */ @@ -119,27 +83,15 @@ struct mbuf *m = *mp; int rv = 0; - /* - * Prevent packet filtering from starving the modification of - * the packet filters. We would prefer a reader/writer locking - * mechanism with guaranteed ordering, though. - */ - if (ph->ph_busy_count == -1 || ph->ph_want_write) { - m_freem(*mp); - *mp = NULL; - return (ENOBUFS); - } - - PFIL_RLOCK(ph); for (pfh = pfil_hook_get(dir, ph); pfh != NULL; - pfh = TAILQ_NEXT(pfh, pfil_link)) { + pfh = pfil_next_hook(dir, ph, pfh)) { if (pfh->pfil_func != NULL) { - rv = (*pfh->pfil_func)(pfh->pfil_arg, &m, ifp, dir, inp); + rv = (*pfh->pfil_func)(pfh->pfil_arg, &m, ifp, dir, + inp); if (rv != 0 || m == NULL) break; } } - PFIL_RUNLOCK(ph); *mp = m; return (rv); @@ -167,21 +119,21 @@ KASSERT((0), ("%s: allready initialized!", __func__)); return EBUSY; } else { - ph->ph_busy_count = -1; - ph->ph_want_write = 1; mtx_init(&ph->ph_mtx, "pfil_head_mtx", NULL, MTX_DEF); - cv_init(&ph->ph_cv, "pfil_head_cv"); - mtx_lock(&ph->ph_mtx); /* XXX: race? */ + PFIL_LOCK(ph); /* XXX: race? */ } - TAILQ_INIT(&ph->ph_in); - TAILQ_INIT(&ph->ph_out); + ph->ph_in = &_pfil_empty; + ph->ph_in_first = PFIL_END; + ph->ph_out = &_pfil_empty; + ph->ph_out_first = PFIL_END; + ph->ph_size = 0; PFIL_LIST_LOCK(); LIST_INSERT_HEAD(&pfil_head_list, ph, ph_list); PFIL_LIST_UNLOCK(); - PFIL_WUNLOCK(ph); + PFIL_UNLOCK(ph); return (0); } @@ -193,8 +145,6 @@ int pfil_head_unregister(struct pfil_head *ph) { - struct packet_filter_hook *pfh, *pfnext; - PFIL_LIST_LOCK(); /* * LIST_REMOVE is safe for unlocked pfil_heads in ph_list. @@ -203,13 +153,13 @@ LIST_REMOVE(ph, ph_list); PFIL_LIST_UNLOCK(); - PFIL_WLOCK(ph); /* XXX: may sleep (cv_wait)! */ + PFIL_LOCK(ph); - TAILQ_FOREACH_SAFE(pfh, &ph->ph_in, pfil_link, pfnext) - free(pfh, M_IFADDR); - TAILQ_FOREACH_SAFE(pfh, &ph->ph_out, pfil_link, pfnext) - free(pfh, M_IFADDR); - cv_destroy(&ph->ph_cv); + if (ph->ph_size != 0) { + free(ph->ph_in, M_IFADDR); + free(ph->ph_out, M_IFADDR); + } + mtx_destroy(&ph->ph_mtx); return (0); @@ -246,66 +196,73 @@ { struct packet_filter_hook *pfh1 = NULL; struct packet_filter_hook *pfh2 = NULL; - int err; + int i, err = 0; + + if (func == NULL) + return (EINVAL); /* Get memory */ - if (flags & PFIL_IN) { - pfh1 = (struct packet_filter_hook *)malloc(sizeof(*pfh1), + if (ph->ph_size == 0) { + pfh1 = (struct packet_filter_hook *)malloc( + sizeof(struct packet_filter_hook) * pfil_slots, M_IFADDR, (flags & PFIL_WAITOK) ? M_WAITOK : M_NOWAIT); - if (pfh1 == NULL) { - err = ENOMEM; - goto error; - } - } - if (flags & PFIL_OUT) { - pfh2 = (struct packet_filter_hook *)malloc(sizeof(*pfh1), + if (pfh1 == NULL) + return (ENOMEM); + pfh2 = (struct packet_filter_hook *)malloc( + sizeof(struct packet_filter_hook) * pfil_slots, M_IFADDR, (flags & PFIL_WAITOK) ? M_WAITOK : M_NOWAIT); if (pfh2 == NULL) { - err = ENOMEM; - goto error; + free(pfh1, M_IFADDR); + return (ENOMEM); } + /* initialize */ + for (i = 0; i < pfil_slots; i++) + pfh1[i] = pfh2[i] = _pfil_empty; + ph->ph_in = pfh1; + ph->ph_out = pfh2; + ph->ph_size = pfil_slots; } - /* Lock */ - if (flags & PFIL_WAITOK) - PFIL_WLOCK(ph); - else { - err = PFIL_TRY_WLOCK(ph); - if (err) - goto error; - } + PFIL_LOCK(ph); - /* Add */ + /* Get slot and link to list */ if (flags & PFIL_IN) { - pfh1->pfil_func = func; - pfh1->pfil_arg = arg; - err = pfil_list_add(&ph->ph_in, pfh1, flags & ~PFIL_OUT); - if (err) - goto done; + for (i = 1; i < ph->ph_size; i++) { + if ((ph->ph_in[i].pfil_func == func) && + (ph->ph_in[i].pfil_arg == arg)) { + err = EEXIST; + goto error; + } + if (ph->ph_in[i].pfil_func == NULL) + break; + } + if (i >= ph->ph_size) { + err = ENOSPC; + goto error; + } + pfil_list_add(ph, PFIL_IN, i, func, arg); } if (flags & PFIL_OUT) { - pfh2->pfil_func = func; - pfh2->pfil_arg = arg; - err = pfil_list_add(&ph->ph_out, pfh2, flags & ~PFIL_IN); - if (err) { - if (flags & PFIL_IN) - pfil_list_remove(&ph->ph_in, func, arg); - goto done; + for (i = 1; i < ph->ph_size; i++) { + if ((ph->ph_out[i].pfil_func == func) && + (ph->ph_out[i].pfil_arg == arg)) { + err = EEXIST; + goto error; + } + if (ph->ph_out[i].pfil_func == NULL) + break; + } + if (i >= ph->ph_size) { + err = ENOSPC; + goto error; } + pfil_list_add(ph, PFIL_OUT, i, func, arg); } - ph->ph_busy_count = 0; - PFIL_WUNLOCK(ph); - - return 0; -done: - PFIL_WUNLOCK(ph); error: - if (pfh1 != NULL) - free(pfh1, M_IFADDR); - if (pfh2 != NULL) - free(pfh2, M_IFADDR); - return err; + PFIL_UNLOCK(ph); + + return (err); } /* @@ -316,68 +273,115 @@ pfil_remove_hook(int (*func)(void *, struct mbuf **, struct ifnet *, int, struct inpcb *), void *arg, int flags, struct pfil_head *ph) { - int err = 0; + int i, err = 0; - if (flags & PFIL_WAITOK) - PFIL_WLOCK(ph); - else { - err = PFIL_TRY_WLOCK(ph); - if (err) - return err; - } - - if (flags & PFIL_IN) - err = pfil_list_remove(&ph->ph_in, func, arg); - if ((err == 0) && (flags & PFIL_OUT)) - err = pfil_list_remove(&ph->ph_out, func, arg); + PFIL_LOCK(ph); - if (TAILQ_EMPTY(&ph->ph_in) && TAILQ_EMPTY(&ph->ph_out)) - ph->ph_busy_count = -1; + if (flags & PFIL_IN) { + for (i = 1; i < ph->ph_size; i++) + if ((ph->ph_in[i].pfil_func == func) && + (ph->ph_in[i].pfil_arg == arg)) + break; + if (i >= ph->ph_size) + err = ENOENT; + else + pfil_list_remove(ph, PFIL_IN, i); + } + if ((err == 0) && (flags & PFIL_OUT)) { + for (i = 1; i < ph->ph_size; i++) + if ((ph->ph_out[i].pfil_func == func) && + (ph->ph_out[i].pfil_arg == arg)) + break; + if (i >= ph->ph_size) + err = ENOENT; + else + pfil_list_remove(ph, PFIL_OUT, i); + } - PFIL_WUNLOCK(ph); + PFIL_UNLOCK(ph); + +#ifdef noyet + if (flags & PFIL_WAITOK) + /* + * We have modified a pfil_func pointer from $SOMEVAL to + * NULL. $SOMEVAL may become invalid after we return from + * this function (due to module unload). We might want to + * wait here for a reasonable amount of time until all other + * processors have catched up on the update. + */ +#endif return err; } -static int -pfil_list_add(pfil_list_t *list, struct packet_filter_hook *pfh1, int flags) -{ - struct packet_filter_hook *pfh; +static void +pfil_list_add(struct pfil_head *ph, int dir, int pos, + int (*func)(void *, struct mbuf **, struct ifnet *, int, struct inpcb *), + void *arg) +{ + struct packet_filter_hook *pfh1, *pfh2; + + if (dir == PFIL_IN) { + pfh1 = &ph->ph_in[pos]; + /* does atomic_store_... buy us anything here? */ + pfh1->pfil_func = func; + pfh1->pfil_arg = arg; - /* - * First make sure the hook is not already there. - */ - TAILQ_FOREACH(pfh, list, pfil_link) - if (pfh->pfil_func == pfh1->pfil_func && - pfh->pfil_arg == pfh1->pfil_arg) - return EEXIST; - /* - * insert the input list in reverse order of the output list - * so that the same path is followed in or out of the kernel. - */ - if (flags & PFIL_IN) - TAILQ_INSERT_HEAD(list, pfh1, pfil_link); - else - TAILQ_INSERT_TAIL(list, pfh1, pfil_link); + if (ph->ph_in_first != PFIL_END) + ph->ph_in[ph->ph_in_first].pfil_prev = pos; + pfh1->pfil_next = ph->ph_in_first; + pfh1->pfil_prev = PFIL_END; + ph->ph_in_first = pos; + } else { + pfh1 = &ph->ph_out[pos]; + /* does atomic_store_... buy us anything here? */ + pfh1->pfil_func = func; + pfh1->pfil_arg = arg; - return 0; + if (ph->ph_out_first == PFIL_END) + ph->ph_out_first = pos; + else { + pfh2 = &ph->ph_out[ph->ph_out_first]; + while (pfh2->pfil_next != PFIL_END) + pfh2 = &ph->ph_out[pfh2->pfil_next]; + pfh1->pfil_prev = (int)(pfh2 - ph->ph_out); + pfh2->pfil_next = pos; + } + } } -/* - * pfil_list_remove is an internal function that takes a function off the - * specified list. - */ -static int -pfil_list_remove(pfil_list_t *list, - int (*func)(void *, struct mbuf **, struct ifnet *, int, struct inpcb *), void *arg) +static void +pfil_list_remove(struct pfil_head *ph, int dir, int pos) { - struct packet_filter_hook *pfh; + struct packet_filter_hook *list, *pfh; + int *first; - TAILQ_FOREACH(pfh, list, pfil_link) - if (pfh->pfil_func == func && pfh->pfil_arg == arg) { - TAILQ_REMOVE(list, pfh, pfil_link); - free(pfh, M_IFADDR); - return 0; - } - return ENOENT; + if (dir == PFIL_IN) { + list = ph->ph_in; + first = &ph->ph_in_first; + } else { + list = ph->ph_out; + first = &ph->ph_out_first; + } + pfh = &list[pos]; + + /* does atomic_store_... buy us anything here? */ + pfh->pfil_func = NULL; + /* short-circut list */ + if (pfh->pfil_prev != PFIL_END) { + KASSERT(list[pfh->pfil_prev].pfil_next == pos, + ("%s: inconsistent list", __func__)); + list[pfh->pfil_prev].pfil_next = pfh->pfil_next; + } else { + KASSERT(*first == pos, + ("%s: inconsistent list", __func__)); + *first = pfh->pfil_next; + } + if (pfh->pfil_next != PFIL_END) { + KASSERT(list[pfh->pfil_next].pfil_prev == pos, + ("%s: inconsistent list", __func__)); + list[pfh->pfil_next].pfil_prev = pfh->pfil_prev; + } + /* purge */ + *pfh = _pfil_empty; } Index: net/pfil.h =================================================================== RCS file: /usr/store/mlaier/fcvs/src/sys/net/pfil.h,v retrieving revision 1.11.2.2 diff -u -r1.11.2.2 pfil.h --- net/pfil.h 31 Jan 2005 23:26:23 -0000 1.11.2.2 +++ net/pfil.h 4 Apr 2005 18:38:17 -0000 @@ -2,6 +2,7 @@ /* $NetBSD: pfil.h,v 1.22 2003/06/23 12:57:08 martin Exp $ */ /*- + * Copyright (c) 2005 Max Laier * Copyright (c) 1996 Matthew R. Green * All rights reserved. * @@ -47,10 +48,11 @@ * possibly intercept the packet. */ struct packet_filter_hook { - TAILQ_ENTRY(packet_filter_hook) pfil_link; - int (*pfil_func)(void *, struct mbuf **, struct ifnet *, int, struct inpcb *); - void *pfil_arg; - int pfil_flags; + int pfil_prev; + int pfil_next; + volatile int (*pfil_func)(void *, struct mbuf **, struct ifnet *, int, + struct inpcb *); + void *pfil_arg; }; #define PFIL_IN 0x00000001 @@ -58,23 +60,22 @@ #define PFIL_WAITOK 0x00000004 #define PFIL_ALL (PFIL_IN|PFIL_OUT) -typedef TAILQ_HEAD(pfil_list, packet_filter_hook) pfil_list_t; - #define PFIL_TYPE_AF 1 /* key is AF_* type */ #define PFIL_TYPE_IFNET 2 /* key is ifnet pointer */ struct pfil_head { - pfil_list_t ph_in; - pfil_list_t ph_out; + struct packet_filter_hook *ph_in; + int ph_in_first; + struct packet_filter_hook *ph_out; + int ph_out_first; +#define PFIL_END 0 + + int ph_size; int ph_type; - /* - * Locking: use a busycounter per pfil_head. - * Use ph_busy_count = -1 to indicate pfil_head is empty. - */ - int ph_busy_count; /* count of threads with read lock */ - int ph_want_write; /* want write lock flag */ - struct cv ph_cv; /* for waking up writers */ + struct mtx ph_mtx; /* mutex on locking state */ +#define PFIL_LOCK(ph) mtx_lock(&(ph)->ph_mtx) +#define PFIL_UNLOCK(ph) mtx_unlock(&(ph)->ph_mtx) union { u_long phu_val; void *phu_ptr; @@ -100,12 +101,28 @@ static __inline struct packet_filter_hook * pfil_hook_get(int dir, struct pfil_head *ph) { - KASSERT(ph->ph_busy_count > 0, - ("pfil_hook_get: called on unbusy pfil_head")); + KASSERT((ph->ph_in_first < ph->ph_size) && + (ph->ph_out_first < ph->ph_size), + ("pfil_hook_get: first element out of bounds")); if (dir == PFIL_IN) - return (TAILQ_FIRST(&ph->ph_in)); + return &ph->ph_in[ph->ph_in_first]; + else if (dir == PFIL_OUT) + return &ph->ph_out[ph->ph_out_first]; + else + return (NULL); +} + +static __inline struct packet_filter_hook * +pfil_next_hook(int dir, struct pfil_head *ph, struct packet_filter_hook *pfh) +{ + KASSERT((pfh->pfil_next < ph->ph_size), + ("pfil_next_hook: out of bounds")); + if (pfh->pfil_next == PFIL_END) + return NULL; + else if (dir == PFIL_IN) + return &ph->ph_in[pfh->pfil_next]; else if (dir == PFIL_OUT) - return (TAILQ_FIRST(&ph->ph_out)); + return &ph->ph_out[pfh->pfil_next]; else return (NULL); } Index: netinet/ip_fastfwd.c =================================================================== RCS file: /usr/store/mlaier/fcvs/src/sys/netinet/ip_fastfwd.c,v retrieving revision 1.17.2.7 diff -u -r1.17.2.7 ip_fastfwd.c --- netinet/ip_fastfwd.c 31 Mar 2005 17:03:45 -0000 1.17.2.7 +++ netinet/ip_fastfwd.c 4 Apr 2005 14:54:16 -0000 @@ -356,7 +356,7 @@ /* * Run through list of ipfilter hooks for input packets */ - if (inet_pfil_hook.ph_busy_count == -1) + if (inet_pfil_hook.ph_size == 0) goto passin; if (pfil_run_hooks(&inet_pfil_hook, &m, m->m_pkthdr.rcvif, PFIL_IN, NULL) || @@ -440,7 +440,7 @@ /* * Run through list of hooks for output packets. */ - if (inet_pfil_hook.ph_busy_count == -1) + if (inet_pfil_hook.ph_size == 0) goto passout; if (pfil_run_hooks(&inet_pfil_hook, &m, ifp, PFIL_OUT, NULL) || m == NULL) { Index: netinet/ip_input.c =================================================================== RCS file: /usr/store/mlaier/fcvs/src/sys/netinet/ip_input.c,v retrieving revision 1.283.2.13 diff -u -r1.283.2.13 ip_input.c --- netinet/ip_input.c 21 Mar 2005 16:05:35 -0000 1.283.2.13 +++ netinet/ip_input.c 4 Apr 2005 14:54:23 -0000 @@ -450,7 +450,7 @@ */ /* Jump over all PFIL processing if hooks are not active. */ - if (inet_pfil_hook.ph_busy_count == -1) + if (inet_pfil_hook.ph_size == 0) goto passin; odst = ip->ip_dst; Index: netinet/ip_output.c =================================================================== RCS file: /usr/store/mlaier/fcvs/src/sys/netinet/ip_output.c,v retrieving revision 1.225.2.11 diff -u -r1.225.2.11 ip_output.c --- netinet/ip_output.c 2 Mar 2005 19:50:12 -0000 1.225.2.11 +++ netinet/ip_output.c 4 Apr 2005 14:56:06 -0000 @@ -653,7 +653,7 @@ #endif /* FAST_IPSEC */ /* Jump over all PFIL processing if hooks are not active. */ - if (inet_pfil_hook.ph_busy_count == -1) + if (inet_pfil_hook.ph_size == 0) goto passout; /* Run through list of hooks for output packets. */ Index: netinet6/ip6_forward.c =================================================================== RCS file: /usr/store/mlaier/fcvs/src/sys/netinet6/ip6_forward.c,v retrieving revision 1.25.2.3 diff -u -r1.25.2.3 ip6_forward.c --- netinet6/ip6_forward.c 31 Jan 2005 23:26:39 -0000 1.25.2.3 +++ netinet6/ip6_forward.c 4 Apr 2005 14:54:37 -0000 @@ -576,7 +576,7 @@ in6_clearscope(&ip6->ip6_dst); /* Jump over all PFIL processing if hooks are not active. */ - if (inet6_pfil_hook.ph_busy_count == -1) + if (inet6_pfil_hook.ph_size == 0) goto pass; /* Run through list of hooks for output packets. */ Index: netinet6/ip6_input.c =================================================================== RCS file: /usr/store/mlaier/fcvs/src/sys/netinet6/ip6_input.c,v retrieving revision 1.75.2.4 diff -u -r1.75.2.4 ip6_input.c --- netinet6/ip6_input.c 31 Jan 2005 23:26:39 -0000 1.75.2.4 +++ netinet6/ip6_input.c 4 Apr 2005 14:54:43 -0000 @@ -421,7 +421,7 @@ odst = ip6->ip6_dst; /* Jump over all PFIL processing if hooks are not active. */ - if (inet6_pfil_hook.ph_busy_count == -1) + if (inet6_pfil_hook.ph_size == 0) goto passin; if (pfil_run_hooks(&inet6_pfil_hook, &m, m->m_pkthdr.rcvif, PFIL_IN, NULL)) Index: netinet6/ip6_output.c =================================================================== RCS file: /usr/store/mlaier/fcvs/src/sys/netinet6/ip6_output.c,v retrieving revision 1.82.2.5 diff -u -r1.82.2.5 ip6_output.c --- netinet6/ip6_output.c 1 Mar 2005 07:19:20 -0000 1.82.2.5 +++ netinet6/ip6_output.c 4 Apr 2005 14:54:49 -0000 @@ -934,7 +934,7 @@ } /* Jump over all PFIL processing if hooks are not active. */ - if (inet6_pfil_hook.ph_busy_count == -1) + if (inet6_pfil_hook.ph_size == 0) goto passout; /* Run through list of hooks for output packets. */