diff --git a/sys/net/pfil.c b/sys/net/pfil.c index 01bd688..af941a4 100644 --- a/sys/net/pfil.c +++ b/sys/net/pfil.c @@ -51,6 +51,8 @@ static struct mtx pfil_global_lock; MTX_SYSINIT(pfil_heads_lock, &pfil_global_lock, "pfil_head_list lock", MTX_DEF); +#define PFIL_LIST_LOCK() mtx_lock(&pfil_global_lock) +#define PFIL_LIST_UNLOCK() mtx_unlock(&pfil_global_lock) static int pfil_list_add(pfil_list_t *, struct packet_filter_hook *, int); @@ -62,7 +64,6 @@ LIST_HEAD(pfilheadhead, pfil_head); VNET_DEFINE(struct pfilheadhead, pfil_head_list); #define V_pfil_head_list VNET(pfil_head_list) VNET_DEFINE(struct rmlock, pfil_lock); -#define V_pfil_lock VNET(pfil_lock) /* * pfil_run_hooks() runs the specified packet filter hooks. @@ -76,7 +77,7 @@ pfil_run_hooks(struct pfil_head *ph, struct mbuf **mp, struct ifnet *ifp, struct mbuf *m = *mp; int rv = 0; - PFIL_RLOCK(ph, &rmpt); + PFIL_HEAD_RLOCK(ph, &rmpt); KASSERT(ph->ph_nhooks >= 0, ("Pfil hook count dropped < 0")); for (pfh = pfil_hook_get(dir, ph); pfh != NULL; pfh = TAILQ_NEXT(pfh, pfil_link)) { @@ -87,73 +88,12 @@ pfil_run_hooks(struct pfil_head *ph, struct mbuf **mp, struct ifnet *ifp, break; } } - PFIL_RUNLOCK(ph, &rmpt); + PFIL_HEAD_RUNLOCK(ph, &rmpt); *mp = m; return (rv); } /* - * pfil_try_rlock() acquires rm reader lock for specified head - * if this is immediately possible, - */ -int -pfil_try_rlock(struct pfil_head *ph, struct rm_priotracker *tracker) -{ - - return (PFIL_TRY_RLOCK(ph, tracker)); -} - -/* - * pfil_rlock() acquires rm reader lock for specified head. - */ -void -pfil_rlock(struct pfil_head *ph, struct rm_priotracker *tracker) -{ - - PFIL_RLOCK(ph, tracker); -} - -/* - * pfil_runlock() releases reader lock for specified head. - */ -void -pfil_runlock(struct pfil_head *ph, struct rm_priotracker *tracker) -{ - - PFIL_RUNLOCK(ph, tracker); -} - -/* - * pfil_wlock() acquires writer lock for specified head. - */ -void -pfil_wlock(struct pfil_head *ph) -{ - - PFIL_WLOCK(ph); -} - -/* - * pfil_wunlock() releases writer lock for specified head. - */ -void -pfil_wunlock(struct pfil_head *ph) -{ - - PFIL_WUNLOCK(ph); -} - -/* - * pfil_wowned() returns a non-zero value if the current thread owns - * an exclusive lock. - */ -int -pfil_wowned(struct pfil_head *ph) -{ - - return (PFIL_WOWNED(ph)); -} -/* * pfil_head_register() registers a pfil_head with the packet filter hook * mechanism. */ @@ -170,7 +110,7 @@ pfil_head_register(struct pfil_head *ph) return (EEXIST); } } - PFIL_LOCK_INIT(ph); + PFIL_HEAD_LOCK_INIT(ph); ph->ph_nhooks = 0; TAILQ_INIT(&ph->ph_in); TAILQ_INIT(&ph->ph_out); @@ -188,7 +128,7 @@ int pfil_head_unregister(struct pfil_head *ph) { struct packet_filter_hook *pfh, *pfnext; - + PFIL_LIST_LOCK(); LIST_REMOVE(ph, ph_list); PFIL_LIST_UNLOCK(); @@ -196,7 +136,7 @@ pfil_head_unregister(struct pfil_head *ph) free(pfh, M_IFADDR); TAILQ_FOREACH_SAFE(pfh, &ph->ph_out, pfil_link, pfnext) free(pfh, M_IFADDR); - PFIL_LOCK_DESTROY(ph); + PFIL_HEAD_LOCK_DESTROY(ph); return (0); } @@ -248,7 +188,7 @@ pfil_add_hook(int (*func)(void *, struct mbuf **, struct ifnet *, int, goto error; } } - PFIL_WLOCK(ph); + PFIL_HEAD_WLOCK(ph); if (flags & PFIL_IN) { pfh1->pfil_func = func; pfh1->pfil_arg = arg; @@ -268,10 +208,10 @@ pfil_add_hook(int (*func)(void *, struct mbuf **, struct ifnet *, int, } ph->ph_nhooks++; } - PFIL_WUNLOCK(ph); + PFIL_HEAD_WUNLOCK(ph); return (0); locked_error: - PFIL_WUNLOCK(ph); + PFIL_HEAD_WUNLOCK(ph); error: if (pfh1 != NULL) free(pfh1, M_IFADDR); @@ -290,7 +230,7 @@ pfil_remove_hook(int (*func)(void *, struct mbuf **, struct ifnet *, int, { int err = 0; - PFIL_WLOCK(ph); + PFIL_HEAD_WLOCK(ph); if (flags & PFIL_IN) { err = pfil_list_remove(&ph->ph_in, func, arg); if (err == 0) @@ -301,7 +241,7 @@ pfil_remove_hook(int (*func)(void *, struct mbuf **, struct ifnet *, int, if (err == 0) ph->ph_nhooks--; } - PFIL_WUNLOCK(ph); + PFIL_HEAD_WUNLOCK(ph); return (err); } @@ -358,7 +298,7 @@ vnet_pfil_init(const void *unused) { LIST_INIT(&V_pfil_head_list); - PFIL_LOCK_INIT_REAL(&V_pfil_lock, "shared"); + PFIL_LOCK_INIT(&V_pfil_lock, "shared"); return (0); } @@ -370,7 +310,7 @@ vnet_pfil_uninit(const void *unused) { /* XXX should panic if list is not empty */ - PFIL_LOCK_DESTROY_REAL(&V_pfil_lock); + PFIL_LOCK_DESTROY(&V_pfil_lock); return (0); } diff --git a/sys/net/pfil.h b/sys/net/pfil.h index fabfe9a..8a4d526 100644 --- a/sys/net/pfil.h +++ b/sys/net/pfil.h @@ -66,6 +66,9 @@ typedef TAILQ_HEAD(pfil_list, packet_filter_hook) pfil_list_t; #define PFIL_FLAG_PRIVATE_LOCK 0x01 /* Personal lock instead of global */ +VNET_DECLARE(struct rmlock, pfil_lock); +#define V_pfil_lock VNET(pfil_lock) + struct pfil_head { pfil_list_t ph_in; pfil_list_t ph_out; @@ -94,43 +97,40 @@ int pfil_remove_hook(int (*func)(void *, struct mbuf **, struct ifnet *, int pfil_run_hooks(struct pfil_head *, struct mbuf **, struct ifnet *, int, struct inpcb *inp); -struct rm_priotracker; /* Do not require including rmlock header */ -int pfil_try_rlock(struct pfil_head *, struct rm_priotracker *); -void pfil_rlock(struct pfil_head *, struct rm_priotracker *); -void pfil_runlock(struct pfil_head *, struct rm_priotracker *); -void pfil_wlock(struct pfil_head *); -void pfil_wunlock(struct pfil_head *); -int pfil_wowned(struct pfil_head *ph); - int pfil_head_register(struct pfil_head *); int pfil_head_unregister(struct pfil_head *); struct pfil_head *pfil_head_get(int, u_long); -#define PFIL_HOOKED(p) ((p)->ph_nhooks > 0) -#define PFIL_LOCK_INIT_REAL(l, t) \ +#define PFIL_HOOKED(h) ((h)->ph_nhooks > 0) + +#define PFIL_LOCK_INIT(l, t) \ rm_init_flags(l, "PFil " t " rmlock", RM_RECURSE) -#define PFIL_LOCK_DESTROY_REAL(l) \ - rm_destroy(l) -#define PFIL_LOCK_INIT(p) do { \ - if ((p)->flags & PFIL_FLAG_PRIVATE_LOCK) { \ - PFIL_LOCK_INIT_REAL(&(p)->ph_lock, "private"); \ - (p)->ph_plock = &(p)->ph_lock; \ +#define PFIL_LOCK_DESTROY(l) rm_destroy(l) +#define PFIL_HEAD_LOCK_INIT(h) do { \ + if ((h)->flags & PFIL_FLAG_PRIVATE_LOCK) { \ + PFIL_LOCK_INIT(&(h)->ph_lock, "private"); \ + (h)->ph_plock = &(h)->ph_lock; \ } else \ - (p)->ph_plock = &V_pfil_lock; \ -} while (0) -#define PFIL_LOCK_DESTROY(p) do { \ - if ((p)->flags & PFIL_FLAG_PRIVATE_LOCK) \ - PFIL_LOCK_DESTROY_REAL((p)->ph_plock); \ + (h)->ph_plock = &V_pfil_lock; \ } while (0) -#define PFIL_TRY_RLOCK(p, t) rm_try_rlock((p)->ph_plock, (t)) -#define PFIL_RLOCK(p, t) rm_rlock((p)->ph_plock, (t)) -#define PFIL_WLOCK(p) rm_wlock((p)->ph_plock) -#define PFIL_RUNLOCK(p, t) rm_runlock((p)->ph_plock, (t)) -#define PFIL_WUNLOCK(p) rm_wunlock((p)->ph_plock) -#define PFIL_WOWNED(p) rm_wowned((p)->ph_plock) -#define PFIL_LIST_LOCK() mtx_lock(&pfil_global_lock) -#define PFIL_LIST_UNLOCK() mtx_unlock(&pfil_global_lock) +#define PFIL_HEAD_LOCK_DESTROY(h) \ + if ((h)->flags & PFIL_FLAG_PRIVATE_LOCK) \ + PFIL_LOCK_DESTROY((h)->ph_plock); + +#define PFIL_TRY_RLOCK(l, t) rm_try_rlock((l), (t)) +#define PFIL_RLOCK(l, t) rm_rlock((l), (t)) +#define PFIL_WLOCK(l) rm_wlock(l) +#define PFIL_RUNLOCK(l, t) rm_runlock((l), (t)) +#define PFIL_WUNLOCK(l) rm_wunlock(l) +#define PFIL_WOWNED(l) rm_wowned(l) + +#define PFIL_HEAD_TRY_RLOCK(h, t) PFIL_TRY_RLOCK((h)->ph_plock, (t)) +#define PFIL_HEAD_RLOCK(h, t) PFIL_RLOCK((h)->ph_plock, (t)) +#define PFIL_HEAD_WLOCK(h) PFIL_WLOCK((h)->ph_plock) +#define PFIL_HEAD_RUNLOCK(h, t) PFIL_RUNLOCK((h)->ph_plock, (t)) +#define PFIL_HEAD_WUNLOCK(h) PFIL_WUNLOCK((h)->ph_plock) +#define PFIL_HEAD_WOWNED(h) PFIL_WOWNED((h)->ph_plock) static __inline struct packet_filter_hook * pfil_hook_get(int dir, struct pfil_head *ph) diff --git a/sys/netpfil/ipfw/ip_fw2.c b/sys/netpfil/ipfw/ip_fw2.c index 7113626..81f4873 100644 --- a/sys/netpfil/ipfw/ip_fw2.c +++ b/sys/netpfil/ipfw/ip_fw2.c @@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -1181,9 +1182,7 @@ do { \ args->f_id.dst_port = dst_port = ntohs(dst_port); } - IPFW_PF_RLOCK(chain); if (! V_ipfw_vnet_ready) { /* shutting down, leave NOW. */ - IPFW_PF_RUNLOCK(chain); return (IP_FW_PASS); /* accept */ } if (args->rule.slot) { @@ -2464,7 +2463,6 @@ do { \ retval = IP_FW_DENY; printf("ipfw: ouch!, skip past end of rules, denying packet\n"); } - IPFW_PF_RUNLOCK(chain); #ifdef __FreeBSD__ if (ucred_cache != NULL) crfree(ucred_cache); @@ -2667,13 +2665,13 @@ vnet_ipfw_uninit(const void *unused) IPFW_UH_WUNLOCK(chain); IPFW_UH_WLOCK(chain); - IPFW_WLOCK(chain); + PFIL_WLOCK(&V_pfil_lock); ipfw_dyn_uninit(0); /* run the callout_drain */ - IPFW_WUNLOCK(chain); + PFIL_WUNLOCK(&V_pfil_lock); ipfw_destroy_tables(chain); reap = NULL; - IPFW_WLOCK(chain); + PFIL_WLOCK(&V_pfil_lock); for (i = 0; i < chain->n_rules; i++) { rule = chain->map[i]; rule->x_next = reap; @@ -2681,7 +2679,7 @@ vnet_ipfw_uninit(const void *unused) } if (chain->map) free(chain->map, M_IPFW); - IPFW_WUNLOCK(chain); + PFIL_WUNLOCK(&V_pfil_lock); IPFW_UH_WUNLOCK(chain); if (reap != NULL) ipfw_reap_rules(reap); diff --git a/sys/netpfil/ipfw/ip_fw_dynamic.c b/sys/netpfil/ipfw/ip_fw_dynamic.c index 3c49ee7..a9868ce 100644 --- a/sys/netpfil/ipfw/ip_fw_dynamic.c +++ b/sys/netpfil/ipfw/ip_fw_dynamic.c @@ -46,11 +46,13 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include #include /* for ETHERTYPE_IP */ #include +#include #include #include @@ -551,7 +553,7 @@ resize_dynamic_table(struct ip_fw_chain *chain, int nbuckets) * Acquire chain write lock to permit hash access * for main traffic path without additional locks */ - IPFW_WLOCK(chain); + PFIL_WLOCK(&V_pfil_lock); /* Save old values */ nbuckets_old = V_curr_dyn_buckets; @@ -581,7 +583,7 @@ resize_dynamic_table(struct ip_fw_chain *chain, int nbuckets) V_curr_dyn_buckets = nbuckets; V_ipfw_dyn_v = dyn_v; - IPFW_WUNLOCK(chain); + PFIL_WUNLOCK(&V_pfil_lock); IPFW_UH_WUNLOCK(chain); diff --git a/sys/netpfil/ipfw/ip_fw_nat.c b/sys/netpfil/ipfw/ip_fw_nat.c index 87d9561..1c0b163 100644 --- a/sys/netpfil/ipfw/ip_fw_nat.c +++ b/sys/netpfil/ipfw/ip_fw_nat.c @@ -34,7 +34,7 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include +#include #define IPFW_INTERNAL /* Access to protected data structures in ip_fw.h. */ @@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -64,7 +65,7 @@ ifaddr_change(void *arg __unused, struct ifnet *ifp) struct ip_fw_chain *chain; chain = &V_layer3_chain; - IPFW_WLOCK(chain); + PFIL_WLOCK(&V_pfil_lock); /* Check every nat entry... */ LIST_FOREACH(ptr, &chain->nat, _next) { /* ...using nic 'ifp->if_xname' as dynamic alias address. */ @@ -82,7 +83,7 @@ ifaddr_change(void *arg __unused, struct ifnet *ifp) } if_addr_runlock(ifp); } - IPFW_WUNLOCK(chain); + PFIL_WUNLOCK(&V_pfil_lock); } /* @@ -94,7 +95,8 @@ flush_nat_ptrs(struct ip_fw_chain *chain, const int ix) int i; ipfw_insn_nat *cmd; - IPFW_WLOCK_ASSERT(chain); + KASSERT(PFIL_WOWNED(&V_pfil_lock) != 0); + for (i = 0; i < chain->n_rules; i++) { cmd = (ipfw_insn_nat *)ACTION_PTR(chain->map[i]); /* XXX skip log and the like ? */ @@ -276,7 +278,6 @@ ipfw_nat(struct ip_fw_args *args, struct cfg_nat *t, struct mbuf *m) found = 0; chain = &V_layer3_chain; - IPFW_RLOCK_ASSERT(chain); /* Check every nat entry... */ LIST_FOREACH(t, &chain->nat, _next) { if ((t->mode & PKT_ALIAS_SKIP_GLOBAL) != 0) @@ -413,11 +414,11 @@ ipfw_nat_cfg(struct sockopt *sopt) /* * Find/create nat rule. */ - IPFW_WLOCK(chain); + PFIL_WLOCK(&V_pfil_lock); gencnt = chain->gencnt; ptr = lookup_nat(&chain->nat, cfg->id); if (ptr == NULL) { - IPFW_WUNLOCK(chain); + PFIL_WUNLOCK(&V_pfil_lock); /* New rule: allocate and init new instance. */ ptr = malloc(sizeof(struct cfg_nat), M_IPFW, M_WAITOK | M_ZERO); ptr->lib = LibAliasInit(NULL); @@ -426,7 +427,7 @@ ipfw_nat_cfg(struct sockopt *sopt) /* Entry already present: temporarily unhook it. */ LIST_REMOVE(ptr, _next); flush_nat_ptrs(chain, cfg->id); - IPFW_WUNLOCK(chain); + PFIL_WUNLOCK(&V_pfil_lock); } /* @@ -453,14 +454,14 @@ ipfw_nat_cfg(struct sockopt *sopt) /* Add new entries. */ add_redir_spool_cfg(&buf[(sizeof(struct cfg_nat))], ptr); - IPFW_WLOCK(chain); + PFIL_WLOCK(&V_pfil_lock); /* Extra check to avoid race with another ipfw_nat_cfg() */ if (gencnt != chain->gencnt && ((cfg = lookup_nat(&chain->nat, ptr->id)) != NULL)) LIST_REMOVE(cfg, _next); LIST_INSERT_HEAD(&chain->nat, ptr, _next); chain->gencnt++; - IPFW_WUNLOCK(chain); + PFIL_WUNLOCK(&V_pfil_lock); out: free(buf, M_TEMP); @@ -476,15 +477,15 @@ ipfw_nat_del(struct sockopt *sopt) sooptcopyin(sopt, &i, sizeof i, sizeof i); /* XXX validate i */ - IPFW_WLOCK(chain); + PFIL_WLOCK(&V_pfil_lock); ptr = lookup_nat(&chain->nat, i); if (ptr == NULL) { - IPFW_WUNLOCK(chain); + PFIL_WUNLOCK(&V_pfil_lock); return (EINVAL); } LIST_REMOVE(ptr, _next); flush_nat_ptrs(chain, i); - IPFW_WUNLOCK(chain); + PFIL_WUNLOCK(&V_pfil_lock); del_redir_spool_cfg(ptr, &ptr->redir_chain); LibAliasUninit(ptr->lib); free(ptr, M_IPFW); @@ -494,6 +495,7 @@ ipfw_nat_del(struct sockopt *sopt) static int ipfw_nat_get_cfg(struct sockopt *sopt) { + struct rm_priotracker rmpt; struct ip_fw_chain *chain = &V_layer3_chain; struct cfg_nat *n; struct cfg_redir *r; @@ -504,7 +506,7 @@ ipfw_nat_get_cfg(struct sockopt *sopt) nat_cnt = 0; len = sizeof(nat_cnt); - IPFW_RLOCK(chain); + PFIL_RLOCK(&V_pfil_lock, &rmpt); retry: gencnt = chain->gencnt; /* Estimate memory amount */ @@ -517,7 +519,7 @@ retry: len += sizeof(struct cfg_spool); } } - IPFW_RUNLOCK(chain); + PFIL_RUNLOCK(&V_pfil_lock, &rmpt); data = malloc(len, M_TEMP, M_WAITOK | M_ZERO); bcopy(&nat_cnt, data, sizeof(nat_cnt)); @@ -525,7 +527,7 @@ retry: nat_cnt = 0; len = sizeof(nat_cnt); - IPFW_RLOCK(chain); + PFIL_RLOCK(&V_pfil_lock); if (gencnt != chain->gencnt) { free(data, M_TEMP); goto retry; @@ -543,7 +545,7 @@ retry: } } } - IPFW_RUNLOCK(chain); + PFIL_RUNLOCK(&V_pfil_lock); error = sooptcopyout(sopt, data, len); free(data, M_TEMP); @@ -554,6 +556,7 @@ retry: static int ipfw_nat_get_log(struct sockopt *sopt) { + struct rm_priotracker rmpt; uint8_t *data; struct cfg_nat *ptr; int i, size; @@ -561,7 +564,7 @@ ipfw_nat_get_log(struct sockopt *sopt) chain = &V_layer3_chain; - IPFW_RLOCK(chain); + PFIL_RLOCK(&V_pfil_lock, &rmpt); /* one pass to count, one to copy the data */ i = 0; LIST_FOREACH(ptr, &chain->nat, _next) { @@ -572,7 +575,7 @@ ipfw_nat_get_log(struct sockopt *sopt) size = i * (LIBALIAS_BUF_SIZE + sizeof(int)); data = malloc(size, M_IPFW, M_NOWAIT | M_ZERO); if (data == NULL) { - IPFW_RUNLOCK(chain); + PFIL_RUNLOCK(&V_pfil_lock, &rmpt); return (ENOSPC); } i = 0; @@ -584,7 +587,7 @@ ipfw_nat_get_log(struct sockopt *sopt) bcopy(ptr->lib->logDesc, &data[i], LIBALIAS_BUF_SIZE); i += LIBALIAS_BUF_SIZE; } - IPFW_RUNLOCK(chain); + PFIL_RUNLOCK(&V_pfil_lock, &rmpt); sooptcopyout(sopt, data, size); free(data, M_IPFW); return(0); @@ -594,7 +597,7 @@ static void ipfw_nat_init(void) { - IPFW_WLOCK(&V_layer3_chain); + PFIL_WLOCK(&V_pfil_lock); /* init ipfw hooks */ ipfw_nat_ptr = ipfw_nat; lookup_nat_ptr = lookup_nat; @@ -602,7 +605,7 @@ ipfw_nat_init(void) ipfw_nat_del_ptr = ipfw_nat_del; ipfw_nat_get_cfg_ptr = ipfw_nat_get_cfg; ipfw_nat_get_log_ptr = ipfw_nat_get_log; - IPFW_WUNLOCK(&V_layer3_chain); + PFIL_WUNLOCK(&V_pfil_lock); V_ifaddr_event_tag = EVENTHANDLER_REGISTER( ifaddr_event, ifaddr_change, NULL, EVENTHANDLER_PRI_ANY); @@ -615,7 +618,7 @@ ipfw_nat_destroy(void) struct ip_fw_chain *chain; chain = &V_layer3_chain; - IPFW_WLOCK(chain); + PFIL_WLOCK(&V_pfil_lock); LIST_FOREACH_SAFE(ptr, &chain->nat, _next, ptr_temp) { LIST_REMOVE(ptr, _next); del_redir_spool_cfg(ptr, &ptr->redir_chain); @@ -631,7 +634,7 @@ ipfw_nat_destroy(void) ipfw_nat_del_ptr = NULL; ipfw_nat_get_cfg_ptr = NULL; ipfw_nat_get_log_ptr = NULL; - IPFW_WUNLOCK(chain); + PFIL_WUNLOCK(&V_pfil_lock); } static int diff --git a/sys/netpfil/ipfw/ip_fw_private.h b/sys/netpfil/ipfw/ip_fw_private.h index 77a8c2f..9177813 100644 --- a/sys/netpfil/ipfw/ip_fw_private.h +++ b/sys/netpfil/ipfw/ip_fw_private.h @@ -227,7 +227,6 @@ struct ip_fw_chain { spinlock_t rwmtx; spinlock_t uh_lock; #else - struct rwlock rwmtx; struct rwlock uh_lock; /* lock for upper half */ #endif uint32_t id; /* ruleset id */ @@ -269,26 +268,13 @@ if (update_counters != 0) { \ */ #define IPFW_LOCK_INIT(_chain) do { \ - rw_init(&(_chain)->rwmtx, "IPFW static rules"); \ rw_init(&(_chain)->uh_lock, "IPFW UH lock"); \ } while (0) #define IPFW_LOCK_DESTROY(_chain) do { \ - rw_destroy(&(_chain)->rwmtx); \ rw_destroy(&(_chain)->uh_lock); \ } while (0) -#define IPFW_RLOCK_ASSERT(_chain) rw_assert(&(_chain)->rwmtx, RA_RLOCKED) -#define IPFW_WLOCK_ASSERT(_chain) rw_assert(&(_chain)->rwmtx, RA_WLOCKED) - -#define IPFW_RLOCK(p) rw_rlock(&(p)->rwmtx) -#define IPFW_RUNLOCK(p) rw_runlock(&(p)->rwmtx) -#define IPFW_WLOCK(p) rw_wlock(&(p)->rwmtx) -#define IPFW_WUNLOCK(p) rw_wunlock(&(p)->rwmtx) -/* These macros are used in the packet flow path, i.e. in the ipfw_chk */ -#define IPFW_PF_RLOCK(p) IPFW_RLOCK(p) -#define IPFW_PF_RUNLOCK(p) IPFW_RUNLOCK(p) - #define IPFW_UH_RLOCK_ASSERT(_chain) rw_assert(&(_chain)->uh_lock, RA_RLOCKED) #define IPFW_UH_WLOCK_ASSERT(_chain) rw_assert(&(_chain)->uh_lock, RA_WLOCKED) diff --git a/sys/netpfil/ipfw/ip_fw_sockopt.c b/sys/netpfil/ipfw/ip_fw_sockopt.c index b681612..58d729f 100644 --- a/sys/netpfil/ipfw/ip_fw_sockopt.c +++ b/sys/netpfil/ipfw/ip_fw_sockopt.c @@ -49,11 +49,13 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include #include #include +#include #include #include @@ -136,13 +138,13 @@ swap_map(struct ip_fw_chain *chain, struct ip_fw **new_map, int new_len) { struct ip_fw **old_map; - IPFW_WLOCK(chain); + PFIL_WLOCK(&V_pfil_lock); chain->id++; chain->n_rules = new_len; old_map = chain->map; chain->map = new_map; - IPFW_WUNLOCK(chain); - return old_map; + PFIL_WUNLOCK(&V_pfil_lock); + return (old_map); } /* @@ -939,6 +941,7 @@ int ipfw_ctl(struct sockopt *sopt) { #define RULE_MAXSIZE (512*sizeof(u_int32_t)) + struct rm_priotracker rmpt; int error; size_t size, len, valsize; struct ip_fw *buf, *rule; @@ -1183,9 +1186,9 @@ ipfw_ctl(struct sockopt *sopt) if ((error = sooptcopyin(sopt, &tbl, sizeof(tbl), sizeof(tbl)))) break; - IPFW_RLOCK(chain); + PFIL_RLOCK(&V_pfil_lock, &rmpt); error = ipfw_count_table(chain, tbl, &cnt); - IPFW_RUNLOCK(chain); + PFIL_RUNLOCK(&V_pfil_lock, &rmpt); if (error) break; error = sooptcopyout(sopt, &cnt, sizeof(cnt)); @@ -1209,9 +1212,9 @@ ipfw_ctl(struct sockopt *sopt) } tbl->size = (size - sizeof(*tbl)) / sizeof(ipfw_table_entry); - IPFW_RLOCK(chain); + PFIL_RLOCK(&V_pfil_lock, &rmpt); error = ipfw_dump_table(chain, tbl); - IPFW_RUNLOCK(chain); + PFIL_RUNLOCK(&V_pfil_lock, &rmpt); if (error) { free(tbl, M_TEMP); break; @@ -1232,9 +1235,9 @@ ipfw_ctl(struct sockopt *sopt) tbl = (uint32_t *)(op3 + 1); - IPFW_RLOCK(chain); + PFIL_RLOCK(&V_pfil_lock, &rmpt); error = ipfw_count_xtable(chain, *tbl, tbl); - IPFW_RUNLOCK(chain); + PFIL_RUNLOCK(&V_pfil_lock, &rmpt); if (error) break; error = sooptcopyout(sopt, op3, sopt->sopt_valsize); @@ -1256,9 +1259,9 @@ ipfw_ctl(struct sockopt *sopt) /* Get maximum number of entries we can store */ tbl->size = (size - sizeof(ipfw_xtable)) / sizeof(ipfw_table_xentry); - IPFW_RLOCK(chain); + PFIL_RLOCK(&V_pfil_lock, &rmpt); error = ipfw_dump_xtable(chain, tbl); - IPFW_RUNLOCK(chain); + PFIL_RUNLOCK(&V_pfil_lock, &rmpt); if (error) { free(tbl, M_TEMP); break; diff --git a/sys/netpfil/ipfw/ip_fw_table.c b/sys/netpfil/ipfw/ip_fw_table.c index 27c13ca..386afdc 100644 --- a/sys/netpfil/ipfw/ip_fw_table.c +++ b/sys/netpfil/ipfw/ip_fw_table.c @@ -52,9 +52,11 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include /* ip_fw.h requires IFNAMSIZ */ +#include #include #include #include @@ -235,32 +237,32 @@ ipfw_add_table_entry(struct ip_fw_chain *ch, uint16_t tbl, void *paddr, return (EINVAL); } - IPFW_WLOCK(ch); + PFIL_WLOCK(&V_pfil_lock); /* Check if tabletype is valid */ if ((ch->tabletype[tbl] != 0) && (ch->tabletype[tbl] != type)) { - IPFW_WUNLOCK(ch); + PFIL_WUNLOCK(&V_pfil_lock); free(ent_ptr, M_IPFW_TBL); return (EINVAL); } /* Check if radix tree exists */ if ((rnh = *rnh_ptr) == NULL) { - IPFW_WUNLOCK(ch); + PFIL_WUNLOCK(&V_pfil_lock); /* Create radix for a new table */ if (!rn_inithead((void **)&rnh, offset)) { free(ent_ptr, M_IPFW_TBL); return (ENOMEM); } - IPFW_WLOCK(ch); + PFIL_WLOCK(&V_pfil_lock); if (*rnh_ptr != NULL) { /* Tree is already attached by other thread */ rn_detachhead((void **)&rnh); rnh = *rnh_ptr; /* Check table type another time */ if (ch->tabletype[tbl] != type) { - IPFW_WUNLOCK(ch); + PFIL_WUNLOCK(&V_pfil_lock); free(ent_ptr, M_IPFW_TBL); return (EINVAL); } @@ -276,7 +278,7 @@ ipfw_add_table_entry(struct ip_fw_chain *ch, uint16_t tbl, void *paddr, } rn = rnh->rnh_addaddr(addr_ptr, mask_ptr, rnh, ent_ptr); - IPFW_WUNLOCK(ch); + PFIL_WUNLOCK(&V_pfil_lock); if (rn == NULL) { free(ent_ptr, M_IPFW_TBL); @@ -369,19 +371,19 @@ ipfw_del_table_entry(struct ip_fw_chain *ch, uint16_t tbl, void *paddr, return (EINVAL); } - IPFW_WLOCK(ch); + PFIL_WLOCK(&V_pfil_lock); if ((rnh = *rnh_ptr) == NULL) { - IPFW_WUNLOCK(ch); + PFIL_WUNLOCK(&V_pfil_lock); return (ESRCH); } if (ch->tabletype[tbl] != type) { - IPFW_WUNLOCK(ch); + PFIL_WUNLOCK(&V_pfil_lock); return (EINVAL); } ent = (struct table_entry *)rnh->rnh_deladdr(sa_ptr, mask_ptr, rnh); - IPFW_WUNLOCK(ch); + PFIL_WUNLOCK(&V_pfil_lock); if (ent == NULL) return (ESRCH); @@ -417,7 +419,7 @@ ipfw_flush_table(struct ip_fw_chain *ch, uint16_t tbl) * for different type without module reload */ - IPFW_WLOCK(ch); + PFIL_WLOCK(&V_pfil_lock); /* Set IPv4 table pointer to zero */ if ((rnh = ch->tables[tbl]) != NULL) ch->tables[tbl] = NULL; @@ -426,7 +428,7 @@ ipfw_flush_table(struct ip_fw_chain *ch, uint16_t tbl) ch->xtables[tbl] = NULL; /* Zero table type */ ch->tabletype[tbl] = 0; - IPFW_WUNLOCK(ch); + PFIL_WUNLOCK(&V_pfil_lock); if (rnh != NULL) { rnh->rnh_walktree(rnh, flush_table_entry, rnh); @@ -483,7 +485,7 @@ ipfw_resize_tables(struct ip_fw_chain *ch, unsigned int ntables) xtables = malloc(ntables * sizeof(void *), M_IPFW, M_WAITOK | M_ZERO); tabletype = malloc(ntables * sizeof(uint8_t), M_IPFW, M_WAITOK | M_ZERO); - IPFW_WLOCK(ch); + PFIL_WLOCK(&V_pfil_lock); tbl = (ntables >= V_fw_tables_max) ? V_fw_tables_max : ntables; @@ -503,7 +505,7 @@ ipfw_resize_tables(struct ip_fw_chain *ch, unsigned int ntables) ntables_old = V_fw_tables_max; V_fw_tables_max = ntables; - IPFW_WUNLOCK(ch); + PFIL_WUNLOCK(&V_pfil_lock); /* Check if we need to destroy radix trees */ if (ntables < ntables_old) {