diff options
Diffstat (limited to 'sys/netinet/ipfw/ip_fw_sockopt.c')
-rw-r--r-- | sys/netinet/ipfw/ip_fw_sockopt.c | 77 |
1 files changed, 33 insertions, 44 deletions
diff --git a/sys/netinet/ipfw/ip_fw_sockopt.c b/sys/netinet/ipfw/ip_fw_sockopt.c index d418881..49618da 100644 --- a/sys/netinet/ipfw/ip_fw_sockopt.c +++ b/sys/netinet/ipfw/ip_fw_sockopt.c @@ -77,23 +77,9 @@ __FBSDID("$FreeBSD$"); MALLOC_DEFINE(M_IPFW, "IpFw/IpAcct", "IpFw/IpAcct chain's"); /* - * static variables followed by global ones + * static variables followed by global ones (none in this file) */ -static VNET_DEFINE(u_int32_t, static_count); /* # of static rules */ -#define V_static_count VNET(static_count) - -static VNET_DEFINE(u_int32_t, static_len); /* bytes of static rules */ -#define V_static_len VNET(static_len) - -#ifdef SYSCTL_NODE -SYSCTL_DECL(_net_inet_ip_fw); -SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, static_count, - CTLFLAG_RD, &VNET_NAME(static_count), 0, - "Number of static rules"); - -#endif /* SYSCTL_NODE */ - /* * When a rule is added/deleted, clear the next_rule pointers in all rules. * These will be reconstructed on the fly as packets are matched. @@ -187,11 +173,9 @@ ipfw_add_rule(struct ip_fw_chain *chain, struct ip_fw *input_rule) /* chain->id incremented inside flush_rule_ptrs() */ rule->id = chain->id; done: - V_static_count++; - V_static_len += l; + chain->n_rules++; + chain->static_len += l; IPFW_WUNLOCK(chain); - DEB(printf("ipfw: installed rule %d, static count now %d\n", - rule->rulenum, V_static_count);) return (0); } @@ -218,8 +202,8 @@ remove_rule(struct ip_fw_chain *chain, struct ip_fw *rule, chain->rules = n; else prev->next = n; - V_static_count--; - V_static_len -= l; + chain->n_rules--; + chain->static_len -= l; rule->next = chain->reap; chain->reap = rule; @@ -839,6 +823,7 @@ ipfw_ctl(struct sockopt *sopt) int error; size_t size; struct ip_fw *buf, *rule; + struct ip_fw_chain *chain; u_int32_t rulenum[2]; error = priv_check(sopt->sopt_td, PRIV_NETINET_IPFW); @@ -856,6 +841,7 @@ ipfw_ctl(struct sockopt *sopt) return (error); } + chain = &V_layer3_chain; error = 0; switch (sopt->sopt_name) { @@ -871,7 +857,7 @@ ipfw_ctl(struct sockopt *sopt) * change between calculating the size and returning the * data in which case we'll just return what fits. */ - size = V_static_len; /* size of static rules */ + size = chain->static_len; /* size of static rules */ size += ipfw_dyn_len(); if (size >= sopt->sopt_valsize) @@ -883,7 +869,7 @@ ipfw_ctl(struct sockopt *sopt) */ buf = malloc(size, M_TEMP, M_WAITOK); error = sooptcopyout(sopt, buf, - ipfw_getrules(&V_layer3_chain, buf, size)); + ipfw_getrules(chain, buf, size)); free(buf, M_TEMP); break; @@ -901,10 +887,10 @@ ipfw_ctl(struct sockopt *sopt) * the old list without the need for a lock. */ - IPFW_WLOCK(&V_layer3_chain); - ipfw_free_chain(&V_layer3_chain, 0 /* keep default rule */); - rule = V_layer3_chain.reap; - IPFW_WUNLOCK(&V_layer3_chain); + IPFW_WLOCK(chain); + ipfw_free_chain(chain, 0 /* keep default rule */); + rule = chain->reap; + IPFW_WUNLOCK(chain); ipfw_reap_rules(rule); break; @@ -915,7 +901,7 @@ ipfw_ctl(struct sockopt *sopt) if (error == 0) error = check_ipfw_struct(rule, sopt->sopt_valsize); if (error == 0) { - error = ipfw_add_rule(&V_layer3_chain, rule); + error = ipfw_add_rule(chain, rule); size = RULESIZE(rule); if (!error && sopt->sopt_dir == SOPT_GET) error = sooptcopyout(sopt, rule, size); @@ -941,13 +927,14 @@ ipfw_ctl(struct sockopt *sopt) if (error) break; size = sopt->sopt_valsize; - if (size == sizeof(u_int32_t)) /* delete or reassign */ - error = del_entry(&V_layer3_chain, rulenum[0]); - else if (size == 2*sizeof(u_int32_t)) /* set enable/disable */ + if (size == sizeof(u_int32_t) && rulenum[0] != 0) { + /* delete or reassign, locking done in del_entry() */ + error = del_entry(chain, rulenum[0]); + } else if (size == 2*sizeof(u_int32_t)) { /* set enable/disable */ V_set_disable = (V_set_disable | rulenum[0]) & ~rulenum[1] & ~(1<<RESVD_SET); /* set RESVD_SET always enabled */ - else + } else error = EINVAL; break; @@ -960,10 +947,11 @@ ipfw_ctl(struct sockopt *sopt) if (error) break; } - error = zero_entry(&V_layer3_chain, rulenum[0], + error = zero_entry(chain, rulenum[0], sopt->sopt_name == IP_FW_RESETLOG); break; + /*--- TABLE manipulations are protected by the IPFW_LOCK ---*/ case IP_FW_TABLE_ADD: { ipfw_table_entry ent; @@ -972,7 +960,7 @@ ipfw_ctl(struct sockopt *sopt) sizeof(ent), sizeof(ent)); if (error) break; - error = ipfw_add_table_entry(&V_layer3_chain, ent.tbl, + error = ipfw_add_table_entry(chain, ent.tbl, ent.addr, ent.masklen, ent.value); } break; @@ -985,7 +973,7 @@ ipfw_ctl(struct sockopt *sopt) sizeof(ent), sizeof(ent)); if (error) break; - error = ipfw_del_table_entry(&V_layer3_chain, ent.tbl, + error = ipfw_del_table_entry(chain, ent.tbl, ent.addr, ent.masklen); } break; @@ -998,9 +986,9 @@ ipfw_ctl(struct sockopt *sopt) sizeof(tbl), sizeof(tbl)); if (error) break; - IPFW_WLOCK(&V_layer3_chain); - error = ipfw_flush_table(&V_layer3_chain, tbl); - IPFW_WUNLOCK(&V_layer3_chain); + IPFW_WLOCK(chain); + error = ipfw_flush_table(chain, tbl); + IPFW_WUNLOCK(chain); } break; @@ -1011,9 +999,9 @@ ipfw_ctl(struct sockopt *sopt) if ((error = sooptcopyin(sopt, &tbl, sizeof(tbl), sizeof(tbl)))) break; - IPFW_RLOCK(&V_layer3_chain); - error = ipfw_count_table(&V_layer3_chain, tbl, &cnt); - IPFW_RUNLOCK(&V_layer3_chain); + IPFW_RLOCK(chain); + error = ipfw_count_table(chain, tbl, &cnt); + IPFW_RUNLOCK(chain); if (error) break; error = sooptcopyout(sopt, &cnt, sizeof(cnt)); @@ -1037,9 +1025,9 @@ ipfw_ctl(struct sockopt *sopt) } tbl->size = (size - sizeof(*tbl)) / sizeof(ipfw_table_entry); - IPFW_RLOCK(&V_layer3_chain); - error = ipfw_dump_table(&V_layer3_chain, tbl); - IPFW_RUNLOCK(&V_layer3_chain); + IPFW_RLOCK(chain); + error = ipfw_dump_table(chain, tbl); + IPFW_RUNLOCK(chain); if (error) { free(tbl, M_TEMP); break; @@ -1049,6 +1037,7 @@ ipfw_ctl(struct sockopt *sopt) } break; + /*--- NAT operations are protected by the IPFW_LOCK ---*/ case IP_FW_NAT_CFG: if (IPFW_NAT_LOADED) error = ipfw_nat_cfg_ptr(sopt); |