Changeset View
Changeset View
Standalone View
Standalone View
sys/netpfil/ipfw/ip_fw_sockopt.c
Show First 20 Lines • Show All 155 Lines • ▼ Show 20 Lines | static struct ipfw_sopt_handler scodes[] = { | ||||
{ IP_FW_DUMP_SOPTCODES, 0, HDIR_GET, dump_soptcodes }, | { IP_FW_DUMP_SOPTCODES, 0, HDIR_GET, dump_soptcodes }, | ||||
{ IP_FW_DUMP_SRVOBJECTS,0, HDIR_GET, dump_srvobjects }, | { IP_FW_DUMP_SRVOBJECTS,0, HDIR_GET, dump_srvobjects }, | ||||
}; | }; | ||||
static int | static int | ||||
set_legacy_obj_kidx(struct ip_fw_chain *ch, struct ip_fw_rule0 *rule); | set_legacy_obj_kidx(struct ip_fw_chain *ch, struct ip_fw_rule0 *rule); | ||||
static struct opcode_obj_rewrite *find_op_rw(ipfw_insn *cmd, | static struct opcode_obj_rewrite *find_op_rw(ipfw_insn *cmd, | ||||
uint16_t *puidx, uint8_t *ptype); | uint16_t *puidx, uint8_t *ptype); | ||||
static int mark_object_kidx(struct ip_fw_chain *ch, struct ip_fw *rule, | |||||
uint32_t *bmask); | |||||
static int ref_rule_objects(struct ip_fw_chain *ch, struct ip_fw *rule, | static int ref_rule_objects(struct ip_fw_chain *ch, struct ip_fw *rule, | ||||
struct rule_check_info *ci, struct obj_idx *oib, struct tid_info *ti); | struct rule_check_info *ci, struct obj_idx *oib, struct tid_info *ti); | ||||
static int ref_opcode_object(struct ip_fw_chain *ch, ipfw_insn *cmd, | static int ref_opcode_object(struct ip_fw_chain *ch, ipfw_insn *cmd, | ||||
struct tid_info *ti, struct obj_idx *pidx, int *unresolved); | struct tid_info *ti, struct obj_idx *pidx, int *unresolved); | ||||
static void unref_rule_objects(struct ip_fw_chain *chain, struct ip_fw *rule); | static void unref_rule_objects(struct ip_fw_chain *chain, struct ip_fw *rule); | ||||
static void unref_oib_objects(struct ip_fw_chain *ch, ipfw_insn *cmd, | static void unref_oib_objects(struct ip_fw_chain *ch, ipfw_insn *cmd, | ||||
struct obj_idx *oib, struct obj_idx *end); | struct obj_idx *oib, struct obj_idx *end); | ||||
static int export_objhash_ntlv(struct namedobj_instance *ni, uint16_t kidx, | static int export_objhash_ntlv(struct namedobj_instance *ni, uint16_t kidx, | ||||
Show All 30 Lines | |||||
struct ip_fw * | struct ip_fw * | ||||
ipfw_alloc_rule(struct ip_fw_chain *chain, size_t rulesize) | ipfw_alloc_rule(struct ip_fw_chain *chain, size_t rulesize) | ||||
{ | { | ||||
struct ip_fw *rule; | struct ip_fw *rule; | ||||
rule = malloc(rulesize, M_IPFW, M_WAITOK | M_ZERO); | rule = malloc(rulesize, M_IPFW, M_WAITOK | M_ZERO); | ||||
rule->cntr = uma_zalloc_pcpu(V_ipfw_cntr_zone, M_WAITOK | M_ZERO); | rule->cntr = uma_zalloc_pcpu(V_ipfw_cntr_zone, M_WAITOK | M_ZERO); | ||||
rule->refcnt = 1; | |||||
return (rule); | return (rule); | ||||
} | } | ||||
static void | void | ||||
free_rule(struct ip_fw *rule) | ipfw_free_rule(struct ip_fw *rule) | ||||
{ | { | ||||
/* | |||||
* We don't release refcnt here, since this function | |||||
* can be called without any locks held. The caller | |||||
* must release reference under IPFW_UH_WLOCK, and then | |||||
* call this function if refcount becomes 1. | |||||
*/ | |||||
if (rule->refcnt > 1) | |||||
return; | |||||
uma_zfree_pcpu(V_ipfw_cntr_zone, rule->cntr); | uma_zfree_pcpu(V_ipfw_cntr_zone, rule->cntr); | ||||
free(rule, M_IPFW); | free(rule, M_IPFW); | ||||
} | } | ||||
/* | /* | ||||
* Find the smallest rule >= key, id. | * Find the smallest rule >= key, id. | ||||
* We could use bsearch but it is so simple that we code it directly | * We could use bsearch but it is so simple that we code it directly | ||||
▲ Show 20 Lines • Show All 594 Lines • ▼ Show 20 Lines | ipfw_reap_add(struct ip_fw_chain *chain, struct ip_fw **head, | ||||
struct ip_fw *rule) | struct ip_fw *rule) | ||||
{ | { | ||||
IPFW_UH_WLOCK_ASSERT(chain); | IPFW_UH_WLOCK_ASSERT(chain); | ||||
/* Unlink rule from everywhere */ | /* Unlink rule from everywhere */ | ||||
unref_rule_objects(chain, rule); | unref_rule_objects(chain, rule); | ||||
*((struct ip_fw **)rule) = *head; | rule->next = *head; | ||||
*head = rule; | *head = rule; | ||||
} | } | ||||
/* | /* | ||||
* Reclaim storage associated with a list of rules. This is | * Reclaim storage associated with a list of rules. This is | ||||
* typically the list created using remove_rule. | * typically the list created using remove_rule. | ||||
* A NULL pointer on input is handled correctly. | * A NULL pointer on input is handled correctly. | ||||
*/ | */ | ||||
void | void | ||||
ipfw_reap_rules(struct ip_fw *head) | ipfw_reap_rules(struct ip_fw *head) | ||||
{ | { | ||||
struct ip_fw *rule; | struct ip_fw *rule; | ||||
while ((rule = head) != NULL) { | while ((rule = head) != NULL) { | ||||
head = *((struct ip_fw **)head); | head = head->next; | ||||
free_rule(rule); | ipfw_free_rule(rule); | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* Rules to keep are | * Rules to keep are | ||||
* (default || reserved || !match_set || !match_number) | * (default || reserved || !match_set || !match_number) | ||||
* where | * where | ||||
* default ::= (rule->rulenum == IPFW_DEFAULT_RULE) | * default ::= (rule->rulenum == IPFW_DEFAULT_RULE) | ||||
▲ Show 20 Lines • Show All 1,327 Lines • ▼ Show 20 Lines | |||||
struct dump_args { | struct dump_args { | ||||
uint32_t b; /* start rule */ | uint32_t b; /* start rule */ | ||||
uint32_t e; /* end rule */ | uint32_t e; /* end rule */ | ||||
uint32_t rcount; /* number of rules */ | uint32_t rcount; /* number of rules */ | ||||
uint32_t rsize; /* rules size */ | uint32_t rsize; /* rules size */ | ||||
uint32_t tcount; /* number of tables */ | uint32_t tcount; /* number of tables */ | ||||
int rcounters; /* counters */ | int rcounters; /* counters */ | ||||
uint32_t *bmask; /* index bitmask of used named objects */ | |||||
}; | }; | ||||
void | void | ||||
ipfw_export_obj_ntlv(struct named_object *no, ipfw_obj_ntlv *ntlv) | ipfw_export_obj_ntlv(struct named_object *no, ipfw_obj_ntlv *ntlv) | ||||
{ | { | ||||
ntlv->head.type = no->etlv; | ntlv->head.type = no->etlv; | ||||
ntlv->head.length = sizeof(*ntlv); | ntlv->head.length = sizeof(*ntlv); | ||||
Show All 20 Lines | export_objhash_ntlv(struct namedobj_instance *ni, uint16_t kidx, | ||||
ntlv = (ipfw_obj_ntlv *)ipfw_get_sopt_space(sd, sizeof(*ntlv)); | ntlv = (ipfw_obj_ntlv *)ipfw_get_sopt_space(sd, sizeof(*ntlv)); | ||||
if (ntlv == NULL) | if (ntlv == NULL) | ||||
return (ENOMEM); | return (ENOMEM); | ||||
ipfw_export_obj_ntlv(no, ntlv); | ipfw_export_obj_ntlv(no, ntlv); | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | |||||
* Dumps static rules with table TLVs in buffer @sd. | |||||
* | |||||
* Returns 0 on success. | |||||
*/ | |||||
static int | static int | ||||
dump_static_rules(struct ip_fw_chain *chain, struct dump_args *da, | export_named_objects(struct namedobj_instance *ni, struct dump_args *da, | ||||
uint32_t *bmask, struct sockopt_data *sd) | struct sockopt_data *sd) | ||||
{ | { | ||||
int error; | int error, i; | ||||
int i, l; | |||||
uint32_t tcount; | for (i = 0; i < IPFW_TABLES_MAX && da->tcount > 0; i++) { | ||||
if ((da->bmask[i / 32] & (1 << (i % 32))) == 0) | |||||
continue; | |||||
if ((error = export_objhash_ntlv(ni, i, sd)) != 0) | |||||
return (error); | |||||
da->tcount--; | |||||
} | |||||
return (0); | |||||
} | |||||
static int | |||||
dump_named_objects(struct ip_fw_chain *ch, struct dump_args *da, | |||||
struct sockopt_data *sd) | |||||
{ | |||||
ipfw_obj_ctlv *ctlv; | ipfw_obj_ctlv *ctlv; | ||||
struct ip_fw *krule; | int error; | ||||
struct namedobj_instance *ni; | |||||
caddr_t dst; | |||||
/* Dump table names first (if any) */ | MPASS(da->tcount > 0); | ||||
if (da->tcount > 0) { | |||||
/* Header first */ | /* Header first */ | ||||
ctlv = (ipfw_obj_ctlv *)ipfw_get_sopt_space(sd, sizeof(*ctlv)); | ctlv = (ipfw_obj_ctlv *)ipfw_get_sopt_space(sd, sizeof(*ctlv)); | ||||
if (ctlv == NULL) | if (ctlv == NULL) | ||||
return (ENOMEM); | return (ENOMEM); | ||||
ctlv->head.type = IPFW_TLV_TBLNAME_LIST; | ctlv->head.type = IPFW_TLV_TBLNAME_LIST; | ||||
ctlv->head.length = da->tcount * sizeof(ipfw_obj_ntlv) + | ctlv->head.length = da->tcount * sizeof(ipfw_obj_ntlv) + | ||||
sizeof(*ctlv); | sizeof(*ctlv); | ||||
ctlv->count = da->tcount; | ctlv->count = da->tcount; | ||||
ctlv->objsize = sizeof(ipfw_obj_ntlv); | ctlv->objsize = sizeof(ipfw_obj_ntlv); | ||||
} | |||||
i = 0; | /* Dump table names first (if any) */ | ||||
tcount = da->tcount; | error = export_named_objects(ipfw_get_table_objhash(ch), da, sd); | ||||
ni = ipfw_get_table_objhash(chain); | if (error != 0) | ||||
while (tcount > 0) { | |||||
if ((bmask[i / 32] & (1 << (i % 32))) == 0) { | |||||
i++; | |||||
continue; | |||||
} | |||||
/* Jump to shared named object bitmask */ | |||||
if (i >= IPFW_TABLES_MAX) { | |||||
ni = CHAIN_TO_SRV(chain); | |||||
i -= IPFW_TABLES_MAX; | |||||
bmask += IPFW_TABLES_MAX / 32; | |||||
} | |||||
if ((error = export_objhash_ntlv(ni, i, sd)) != 0) | |||||
return (error); | return (error); | ||||
/* Then dump another named objects */ | |||||
i++; | da->bmask += IPFW_TABLES_MAX / 32; | ||||
tcount--; | return (export_named_objects(CHAIN_TO_SRV(ch), da, sd)); | ||||
} | } | ||||
/* | |||||
* Dumps static rules with table TLVs in buffer @sd. | |||||
* | |||||
* Returns 0 on success. | |||||
*/ | |||||
static int | |||||
dump_static_rules(struct ip_fw_chain *chain, struct dump_args *da, | |||||
struct sockopt_data *sd) | |||||
{ | |||||
ipfw_obj_ctlv *ctlv; | |||||
struct ip_fw *krule; | |||||
caddr_t dst; | |||||
int i, l; | |||||
/* Dump rules */ | /* Dump rules */ | ||||
ctlv = (ipfw_obj_ctlv *)ipfw_get_sopt_space(sd, sizeof(*ctlv)); | ctlv = (ipfw_obj_ctlv *)ipfw_get_sopt_space(sd, sizeof(*ctlv)); | ||||
if (ctlv == NULL) | if (ctlv == NULL) | ||||
return (ENOMEM); | return (ENOMEM); | ||||
ctlv->head.type = IPFW_TLV_RULE_LIST; | ctlv->head.type = IPFW_TLV_RULE_LIST; | ||||
ctlv->head.length = da->rsize + sizeof(*ctlv); | ctlv->head.length = da->rsize + sizeof(*ctlv); | ||||
ctlv->count = da->rcount; | ctlv->count = da->rcount; | ||||
for (i = da->b; i < da->e; i++) { | for (i = da->b; i < da->e; i++) { | ||||
krule = chain->map[i]; | krule = chain->map[i]; | ||||
l = RULEUSIZE1(krule) + sizeof(ipfw_obj_tlv); | l = RULEUSIZE1(krule) + sizeof(ipfw_obj_tlv); | ||||
if (da->rcounters != 0) | if (da->rcounters != 0) | ||||
l += sizeof(struct ip_fw_bcounter); | l += sizeof(struct ip_fw_bcounter); | ||||
dst = (caddr_t)ipfw_get_sopt_space(sd, l); | dst = (caddr_t)ipfw_get_sopt_space(sd, l); | ||||
if (dst == NULL) | if (dst == NULL) | ||||
return (ENOMEM); | return (ENOMEM); | ||||
export_rule1(krule, dst, l, da->rcounters); | export_rule1(krule, dst, l, da->rcounters); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
int | |||||
ipfw_mark_object_kidx(uint32_t *bmask, uint16_t etlv, uint16_t kidx) | |||||
{ | |||||
uint32_t bidx; | |||||
/* | /* | ||||
* Maintain separate bitmasks for table and non-table objects. | |||||
*/ | |||||
bidx = (etlv == IPFW_TLV_TBL_NAME) ? 0: IPFW_TABLES_MAX / 32; | |||||
bidx += kidx / 32; | |||||
if ((bmask[bidx] & (1 << (kidx % 32))) != 0) | |||||
return (0); | |||||
bmask[bidx] |= 1 << (kidx % 32); | |||||
return (1); | |||||
} | |||||
/* | |||||
* Marks every object index used in @rule with bit in @bmask. | * Marks every object index used in @rule with bit in @bmask. | ||||
* Used to generate bitmask of referenced tables/objects for given ruleset | * Used to generate bitmask of referenced tables/objects for given ruleset | ||||
* or its part. | * or its part. | ||||
* | |||||
* Returns number of newly-referenced objects. | |||||
*/ | */ | ||||
static int | static void | ||||
mark_object_kidx(struct ip_fw_chain *ch, struct ip_fw *rule, | mark_rule_objects(struct ip_fw_chain *ch, struct ip_fw *rule, | ||||
uint32_t *bmask) | struct dump_args *da) | ||||
{ | { | ||||
struct opcode_obj_rewrite *rw; | struct opcode_obj_rewrite *rw; | ||||
ipfw_insn *cmd; | ipfw_insn *cmd; | ||||
int bidx, cmdlen, l, count; | int cmdlen, l; | ||||
uint16_t kidx; | uint16_t kidx; | ||||
uint8_t subtype; | uint8_t subtype; | ||||
l = rule->cmd_len; | l = rule->cmd_len; | ||||
cmd = rule->cmd; | cmd = rule->cmd; | ||||
cmdlen = 0; | cmdlen = 0; | ||||
count = 0; | |||||
for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) { | for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) { | ||||
cmdlen = F_LEN(cmd); | cmdlen = F_LEN(cmd); | ||||
rw = find_op_rw(cmd, &kidx, &subtype); | rw = find_op_rw(cmd, &kidx, &subtype); | ||||
if (rw == NULL) | if (rw == NULL) | ||||
continue; | continue; | ||||
bidx = kidx / 32; | if (ipfw_mark_object_kidx(da->bmask, rw->etlv, kidx)) | ||||
/* | da->tcount++; | ||||
* Maintain separate bitmasks for table and | |||||
* non-table objects. | |||||
*/ | |||||
if (rw->etlv != IPFW_TLV_TBL_NAME) | |||||
bidx += IPFW_TABLES_MAX / 32; | |||||
if ((bmask[bidx] & (1 << (kidx % 32))) == 0) | |||||
count++; | |||||
bmask[bidx] |= 1 << (kidx % 32); | |||||
} | } | ||||
return (count); | |||||
} | } | ||||
/* | /* | ||||
* Dumps requested objects data | * Dumps requested objects data | ||||
* Data layout (version 0)(current): | * Data layout (version 0)(current): | ||||
* Request: [ ipfw_cfg_lheader ] + IPFW_CFG_GET_* flags | * Request: [ ipfw_cfg_lheader ] + IPFW_CFG_GET_* flags | ||||
* size = ipfw_cfg_lheader.size | * size = ipfw_cfg_lheader.size | ||||
* Reply: [ ipfw_cfg_lheader | * Reply: [ ipfw_cfg_lheader | ||||
* [ ipfw_obj_ctlv(IPFW_TLV_TBL_LIST) ipfw_obj_ntlv x N ] (optional) | * [ ipfw_obj_ctlv(IPFW_TLV_TBL_LIST) ipfw_obj_ntlv x N ] (optional) | ||||
* [ ipfw_obj_ctlv(IPFW_TLV_RULE_LIST) | * [ ipfw_obj_ctlv(IPFW_TLV_RULE_LIST) | ||||
* ipfw_obj_tlv(IPFW_TLV_RULE_ENT) [ ip_fw_bcounter (optional) ip_fw_rule ] | * ipfw_obj_tlv(IPFW_TLV_RULE_ENT) [ ip_fw_bcounter (optional) ip_fw_rule ] | ||||
* ] (optional) | * ] (optional) | ||||
* [ ipfw_obj_ctlv(IPFW_TLV_STATE_LIST) ipfw_obj_dyntlv x N ] (optional) | * [ ipfw_obj_ctlv(IPFW_TLV_STATE_LIST) ipfw_obj_dyntlv x N ] (optional) | ||||
* ] | * ] | ||||
* * NOTE IPFW_TLV_STATE_LIST has the single valid field: objsize. | * * NOTE IPFW_TLV_STATE_LIST has the single valid field: objsize. | ||||
* The rest (size, count) are set to zero and needs to be ignored. | * The rest (size, count) are set to zero and needs to be ignored. | ||||
* | * | ||||
* Returns 0 on success. | * Returns 0 on success. | ||||
*/ | */ | ||||
static int | static int | ||||
dump_config(struct ip_fw_chain *chain, ip_fw3_opheader *op3, | dump_config(struct ip_fw_chain *chain, ip_fw3_opheader *op3, | ||||
struct sockopt_data *sd) | struct sockopt_data *sd) | ||||
{ | { | ||||
struct dump_args da; | |||||
ipfw_cfg_lheader *hdr; | ipfw_cfg_lheader *hdr; | ||||
struct ip_fw *rule; | struct ip_fw *rule; | ||||
size_t sz, rnum; | size_t sz, rnum; | ||||
uint32_t hdr_flags; | uint32_t hdr_flags, *bmask; | ||||
int error, i; | int error, i; | ||||
struct dump_args da; | |||||
uint32_t *bmask; | |||||
hdr = (ipfw_cfg_lheader *)ipfw_get_sopt_header(sd, sizeof(*hdr)); | hdr = (ipfw_cfg_lheader *)ipfw_get_sopt_header(sd, sizeof(*hdr)); | ||||
if (hdr == NULL) | if (hdr == NULL) | ||||
return (EINVAL); | return (EINVAL); | ||||
error = 0; | error = 0; | ||||
bmask = NULL; | bmask = NULL; | ||||
/* Allocate needed state. Note we allocate 2xspace mask, for table&srv */ | memset(&da, 0, sizeof(da)); | ||||
if (hdr->flags & IPFW_CFG_GET_STATIC) | /* | ||||
bmask = malloc(IPFW_TABLES_MAX / 4, M_TEMP, M_WAITOK | M_ZERO); | * Allocate needed state. | ||||
* Note we allocate 2xspace mask, for table & srv | |||||
*/ | |||||
if (hdr->flags & (IPFW_CFG_GET_STATIC | IPFW_CFG_GET_STATES)) | |||||
da.bmask = bmask = malloc( | |||||
sizeof(uint32_t) * IPFW_TABLES_MAX * 2 / 32, M_TEMP, | |||||
M_WAITOK | M_ZERO); | |||||
IPFW_UH_RLOCK(chain); | IPFW_UH_RLOCK(chain); | ||||
/* | /* | ||||
* STAGE 1: Determine size/count for objects in range. | * STAGE 1: Determine size/count for objects in range. | ||||
* Prepare used tables bitmask. | * Prepare used tables bitmask. | ||||
*/ | */ | ||||
sz = sizeof(ipfw_cfg_lheader); | sz = sizeof(ipfw_cfg_lheader); | ||||
memset(&da, 0, sizeof(da)); | |||||
da.b = 0; | |||||
da.e = chain->n_rules; | da.e = chain->n_rules; | ||||
if (hdr->end_rule != 0) { | if (hdr->end_rule != 0) { | ||||
/* Handle custom range */ | /* Handle custom range */ | ||||
if ((rnum = hdr->start_rule) > IPFW_DEFAULT_RULE) | if ((rnum = hdr->start_rule) > IPFW_DEFAULT_RULE) | ||||
rnum = IPFW_DEFAULT_RULE; | rnum = IPFW_DEFAULT_RULE; | ||||
da.b = ipfw_find_rule(chain, rnum, 0); | da.b = ipfw_find_rule(chain, rnum, 0); | ||||
rnum = (hdr->end_rule < IPFW_DEFAULT_RULE) ? | rnum = (hdr->end_rule < IPFW_DEFAULT_RULE) ? | ||||
hdr->end_rule + 1: IPFW_DEFAULT_RULE; | hdr->end_rule + 1: IPFW_DEFAULT_RULE; | ||||
da.e = ipfw_find_rule(chain, rnum, UINT32_MAX) + 1; | da.e = ipfw_find_rule(chain, rnum, UINT32_MAX) + 1; | ||||
} | } | ||||
if (hdr->flags & IPFW_CFG_GET_STATIC) { | if (hdr->flags & IPFW_CFG_GET_STATIC) { | ||||
for (i = da.b; i < da.e; i++) { | for (i = da.b; i < da.e; i++) { | ||||
rule = chain->map[i]; | rule = chain->map[i]; | ||||
da.rsize += RULEUSIZE1(rule) + sizeof(ipfw_obj_tlv); | da.rsize += RULEUSIZE1(rule) + sizeof(ipfw_obj_tlv); | ||||
da.rcount++; | da.rcount++; | ||||
/* Update bitmask of used objects for given range */ | /* Update bitmask of used objects for given range */ | ||||
da.tcount += mark_object_kidx(chain, rule, bmask); | mark_rule_objects(chain, rule, &da); | ||||
} | } | ||||
/* Add counters if requested */ | /* Add counters if requested */ | ||||
if (hdr->flags & IPFW_CFG_GET_COUNTERS) { | if (hdr->flags & IPFW_CFG_GET_COUNTERS) { | ||||
da.rsize += sizeof(struct ip_fw_bcounter) * da.rcount; | da.rsize += sizeof(struct ip_fw_bcounter) * da.rcount; | ||||
da.rcounters = 1; | da.rcounters = 1; | ||||
} | } | ||||
sz += da.rsize + sizeof(ipfw_obj_ctlv); | |||||
} | |||||
if (hdr->flags & IPFW_CFG_GET_STATES) { | |||||
sz += sizeof(ipfw_obj_ctlv) + | |||||
ipfw_dyn_get_count(bmask, &i) * sizeof(ipfw_obj_dyntlv); | |||||
da.tcount += i; | |||||
} | |||||
if (da.tcount > 0) | if (da.tcount > 0) | ||||
sz += da.tcount * sizeof(ipfw_obj_ntlv) + | sz += da.tcount * sizeof(ipfw_obj_ntlv) + | ||||
sizeof(ipfw_obj_ctlv); | sizeof(ipfw_obj_ctlv); | ||||
sz += da.rsize + sizeof(ipfw_obj_ctlv); | |||||
} | |||||
if (hdr->flags & IPFW_CFG_GET_STATES) | |||||
sz += ipfw_dyn_get_count() * sizeof(ipfw_obj_dyntlv) + | |||||
sizeof(ipfw_obj_ctlv); | |||||
/* | /* | ||||
* Fill header anyway. | * Fill header anyway. | ||||
* Note we have to save header fields to stable storage | * Note we have to save header fields to stable storage | ||||
* buffer inside @sd can be flushed after dumping rules | * buffer inside @sd can be flushed after dumping rules | ||||
*/ | */ | ||||
hdr->size = sz; | hdr->size = sz; | ||||
hdr->set_mask = ~V_set_disable; | hdr->set_mask = ~V_set_disable; | ||||
hdr_flags = hdr->flags; | hdr_flags = hdr->flags; | ||||
hdr = NULL; | hdr = NULL; | ||||
if (sd->valsize < sz) { | if (sd->valsize < sz) { | ||||
error = ENOMEM; | error = ENOMEM; | ||||
goto cleanup; | goto cleanup; | ||||
} | } | ||||
/* STAGE2: Store actual data */ | /* STAGE2: Store actual data */ | ||||
if (da.tcount > 0) { | |||||
error = dump_named_objects(chain, &da, sd); | |||||
if (error != 0) | |||||
goto cleanup; | |||||
} | |||||
if (hdr_flags & IPFW_CFG_GET_STATIC) { | if (hdr_flags & IPFW_CFG_GET_STATIC) { | ||||
error = dump_static_rules(chain, &da, bmask, sd); | error = dump_static_rules(chain, &da, sd); | ||||
if (error != 0) | if (error != 0) | ||||
goto cleanup; | goto cleanup; | ||||
} | } | ||||
if (hdr_flags & IPFW_CFG_GET_STATES) | if (hdr_flags & IPFW_CFG_GET_STATES) | ||||
error = ipfw_dump_states(chain, sd); | error = ipfw_dump_states(chain, sd); | ||||
cleanup: | cleanup: | ||||
▲ Show 20 Lines • Show All 562 Lines • ▼ Show 20 Lines | for (i = 0, ci = cbuf; i < rtlv->count; i++, ci++) { | ||||
clen = RULEKSIZE1((struct ip_fw_rule *)ci->urule); | clen = RULEKSIZE1((struct ip_fw_rule *)ci->urule); | ||||
ci->krule = ipfw_alloc_rule(chain, clen); | ci->krule = ipfw_alloc_rule(chain, clen); | ||||
import_rule1(ci); | import_rule1(ci); | ||||
} | } | ||||
if ((error = commit_rules(chain, cbuf, rtlv->count)) != 0) { | if ((error = commit_rules(chain, cbuf, rtlv->count)) != 0) { | ||||
/* Free allocate krules */ | /* Free allocate krules */ | ||||
for (i = 0, ci = cbuf; i < rtlv->count; i++, ci++) | for (i = 0, ci = cbuf; i < rtlv->count; i++, ci++) | ||||
free_rule(ci->krule); | ipfw_free_rule(ci->krule); | ||||
} | } | ||||
if (cbuf != NULL && cbuf != &rci) | if (cbuf != NULL && cbuf != &rci) | ||||
free(cbuf, M_TEMP); | free(cbuf, M_TEMP); | ||||
return (error); | return (error); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 807 Lines • ▼ Show 20 Lines | if (error == 0) { | ||||
/* locking is done within add_rule() */ | /* locking is done within add_rule() */ | ||||
struct ip_fw *krule; | struct ip_fw *krule; | ||||
krule = ipfw_alloc_rule(chain, RULEKSIZE0(rule)); | krule = ipfw_alloc_rule(chain, RULEKSIZE0(rule)); | ||||
ci.urule = (caddr_t)rule; | ci.urule = (caddr_t)rule; | ||||
ci.krule = krule; | ci.krule = krule; | ||||
import_rule0(&ci); | import_rule0(&ci); | ||||
error = commit_rules(chain, &ci, 1); | error = commit_rules(chain, &ci, 1); | ||||
if (error != 0) | if (error != 0) | ||||
free_rule(ci.krule); | ipfw_free_rule(ci.krule); | ||||
else if (sopt->sopt_dir == SOPT_GET) { | else if (sopt->sopt_dir == SOPT_GET) { | ||||
if (is7) { | if (is7) { | ||||
error = convert_rule_to_7(rule); | error = convert_rule_to_7(rule); | ||||
size = RULESIZE7(rule); | size = RULESIZE7(rule); | ||||
if (error) { | if (error) { | ||||
free(rule, M_TEMP); | free(rule, M_TEMP); | ||||
return error; | return error; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 790 Lines • Show Last 20 Lines |