diff options
author | ae <ae@FreeBSD.org> | 2016-04-14 20:49:27 +0000 |
---|---|---|
committer | ae <ae@FreeBSD.org> | 2016-04-14 20:49:27 +0000 |
commit | c259f15148fd9e7666d161b42e69949f8477257e (patch) | |
tree | 2a68b57165563f3240dbad4f99cb94884770d516 /sys/netpfil | |
parent | 34046610f1e66c243c46981949efca943d200816 (diff) | |
download | FreeBSD-src-c259f15148fd9e7666d161b42e69949f8477257e.zip FreeBSD-src-c259f15148fd9e7666d161b42e69949f8477257e.tar.gz |
Move several functions related to opcode rewriting framework from
ip_fw_table.c into ip_fw_sockopt.c and make them static.
Obtained from: Yandex LLC
Diffstat (limited to 'sys/netpfil')
-rw-r--r-- | sys/netpfil/ipfw/ip_fw_private.h | 8 | ||||
-rw-r--r-- | sys/netpfil/ipfw/ip_fw_sockopt.c | 143 | ||||
-rw-r--r-- | sys/netpfil/ipfw/ip_fw_table.c | 130 |
3 files changed, 141 insertions, 140 deletions
diff --git a/sys/netpfil/ipfw/ip_fw_private.h b/sys/netpfil/ipfw/ip_fw_private.h index 7be3d1e..659af35 100644 --- a/sys/netpfil/ipfw/ip_fw_private.h +++ b/sys/netpfil/ipfw/ip_fw_private.h @@ -685,14 +685,6 @@ void ipfw_destroy_obj_rewriter(void); void ipfw_add_obj_rewriter(struct opcode_obj_rewrite *rw, size_t count); int ipfw_del_obj_rewriter(struct opcode_obj_rewrite *rw, size_t count); -int ipfw_rewrite_rule_uidx(struct ip_fw_chain *chain, - struct rule_check_info *ci); -int ipfw_mark_object_kidx(struct ip_fw_chain *chain, struct ip_fw *rule, - uint32_t *bmask); -int ref_opcode_object(struct ip_fw_chain *ch, ipfw_insn *cmd, struct tid_info *ti, - struct obj_idx *pidx, int *found, int *unresolved); -void unref_oib_objects(struct ip_fw_chain *ch, ipfw_insn *cmd, - struct obj_idx *oib, struct obj_idx *end); int create_objects_compat(struct ip_fw_chain *ch, ipfw_insn *cmd, struct obj_idx *oib, struct obj_idx *pidx, struct tid_info *ti); void update_opcode_kidx(ipfw_insn *cmd, uint16_t idx); diff --git a/sys/netpfil/ipfw/ip_fw_sockopt.c b/sys/netpfil/ipfw/ip_fw_sockopt.c index 857b465..18f2f19 100644 --- a/sys/netpfil/ipfw/ip_fw_sockopt.c +++ b/sys/netpfil/ipfw/ip_fw_sockopt.c @@ -81,6 +81,8 @@ static int check_ipfw_rule1(struct ip_fw_rule *rule, int size, struct rule_check_info *ci); static int check_ipfw_rule0(struct ip_fw_rule0 *rule, int size, struct rule_check_info *ci); +static int rewrite_rule_uidx(struct ip_fw_chain *chain, + struct rule_check_info *ci); #define NAMEDOBJ_HASH_SIZE 32 @@ -156,7 +158,13 @@ set_legacy_obj_kidx(struct ip_fw_chain *ch, struct ip_fw_rule0 *rule); struct opcode_obj_rewrite *ipfw_find_op_rw(uint16_t opcode); 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, + 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, + struct tid_info *ti, struct obj_idx *pidx, int *found, int *unresolved); 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, + struct obj_idx *oib, struct obj_idx *end); static int export_objhash_ntlv(struct namedobj_instance *ni, uint16_t kidx, struct sockopt_data *sd); @@ -675,7 +683,7 @@ commit_rules(struct ip_fw_chain *chain, struct rule_check_info *rci, int count) * We need to find (and create non-existing) * kernel objects, and reference existing ones. */ - error = ipfw_rewrite_rule_uidx(chain, ci); + error = rewrite_rule_uidx(chain, ci); if (error != 0) { /* @@ -2286,7 +2294,7 @@ set_legacy_obj_kidx(struct ip_fw_chain *ch, struct ip_fw_rule0 *rule) * * Used to rollback partially converted rule on error. */ -void +static void unref_oib_objects(struct ip_fw_chain *ch, ipfw_insn *cmd, struct obj_idx *oib, struct obj_idx *end) { @@ -2407,6 +2415,137 @@ ref_opcode_object(struct ip_fw_chain *ch, ipfw_insn *cmd, struct tid_info *ti, } /* + * Finds and bumps refcount for objects referenced by given @rule. + * Auto-creates non-existing tables. + * Fills in @oib array with userland/kernel indexes. + * + * Returns 0 on success. + */ +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) +{ + int cmdlen, error, l, numnew; + ipfw_insn *cmd; + struct obj_idx *pidx; + int found, unresolved; + + pidx = oib; + l = rule->cmd_len; + cmd = rule->cmd; + cmdlen = 0; + error = 0; + numnew = 0; + found = 0; + unresolved = 0; + + IPFW_UH_WLOCK(ch); + + /* Increase refcount on each existing referenced table. */ + for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) { + cmdlen = F_LEN(cmd); + + error = ref_opcode_object(ch, cmd, ti, pidx, &found, + &unresolved); + if (error != 0) + break; + if (found || unresolved) { + pidx->off = rule->cmd_len - l; + pidx++; + } + /* + * Compability stuff for old clients: + * prepare to manually create non-existing objects. + */ + if (unresolved) + numnew++; + } + + if (error != 0) { + /* Unref everything we have already done */ + unref_oib_objects(ch, rule->cmd, oib, pidx); + IPFW_UH_WUNLOCK(ch); + return (error); + } + IPFW_UH_WUNLOCK(ch); + + /* Perform auto-creation for non-existing objects */ + if (numnew != 0) + error = create_objects_compat(ch, rule->cmd, oib, pidx, ti); + + /* Calculate real number of dynamic objects */ + ci->object_opcodes = (uint16_t)(pidx - oib); + + return (error); +} + +/* + * Checks is opcode is referencing table of appropriate type. + * Adds reference count for found table if true. + * Rewrites user-supplied opcode values with kernel ones. + * + * Returns 0 on success and appropriate error code otherwise. + */ +static int +rewrite_rule_uidx(struct ip_fw_chain *chain, struct rule_check_info *ci) +{ + int error; + ipfw_insn *cmd; + uint8_t type; + struct obj_idx *p, *pidx_first, *pidx_last; + struct tid_info ti; + + /* + * Prepare an array for storing opcode indices. + * Use stack allocation by default. + */ + if (ci->object_opcodes <= (sizeof(ci->obuf)/sizeof(ci->obuf[0]))) { + /* Stack */ + pidx_first = ci->obuf; + } else + pidx_first = malloc( + ci->object_opcodes * sizeof(struct obj_idx), + M_IPFW, M_WAITOK | M_ZERO); + + error = 0; + type = 0; + memset(&ti, 0, sizeof(ti)); + + /* + * Use default set for looking up tables (old way) or + * use set rule is assigned to (new way). + */ + ti.set = (V_fw_tables_sets != 0) ? ci->krule->set : 0; + if (ci->ctlv != NULL) { + ti.tlvs = (void *)(ci->ctlv + 1); + ti.tlen = ci->ctlv->head.length - sizeof(ipfw_obj_ctlv); + } + + /* Reference all used tables and other objects */ + error = ref_rule_objects(chain, ci->krule, ci, pidx_first, &ti); + if (error != 0) + goto free; + /* + * Note that ref_rule_objects() might have updated ci->object_opcodes + * to reflect actual number of object opcodes. + */ + + /* Perform rule rewrite */ + p = pidx_first; + pidx_last = pidx_first + ci->object_opcodes; + for (p = pidx_first; p < pidx_last; p++) { + cmd = ci->krule->cmd + p->off; + update_opcode_kidx(cmd, p->kidx); + } + +free: + if (pidx_first != ci->obuf) + free(pidx_first, M_IPFW); + + return (error); +} + +/* * Adds one or more rules to ipfw @chain. * Data layout (version 0)(current): * Request: diff --git a/sys/netpfil/ipfw/ip_fw_table.c b/sys/netpfil/ipfw/ip_fw_table.c index a1ee5dd..4af7c88 100644 --- a/sys/netpfil/ipfw/ip_fw_table.c +++ b/sys/netpfil/ipfw/ip_fw_table.c @@ -3336,136 +3336,6 @@ ipfw_move_tables_sets(struct ip_fw_chain *ch, ipfw_range_tlv *rt, return (bad); } -/* - * Finds and bumps refcount for objects referenced by given @rule. - * Auto-creates non-existing tables. - * Fills in @oib array with userland/kernel indexes. - * - * Returns 0 on success. - */ -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) -{ - int cmdlen, error, l, numnew; - ipfw_insn *cmd; - struct obj_idx *pidx; - int found, unresolved; - - pidx = oib; - l = rule->cmd_len; - cmd = rule->cmd; - cmdlen = 0; - error = 0; - numnew = 0; - found = 0; - unresolved = 0; - - IPFW_UH_WLOCK(ch); - - /* Increase refcount on each existing referenced table. */ - for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) { - cmdlen = F_LEN(cmd); - - error = ref_opcode_object(ch, cmd, ti, pidx, &found, &unresolved); - if (error != 0) - break; - if (found || unresolved) { - pidx->off = rule->cmd_len - l; - pidx++; - } - /* - * Compability stuff for old clients: - * prepare to manually create non-existing objects. - */ - if (unresolved) - numnew++; - } - - if (error != 0) { - /* Unref everything we have already done */ - unref_oib_objects(ch, rule->cmd, oib, pidx); - IPFW_UH_WUNLOCK(ch); - return (error); - } - IPFW_UH_WUNLOCK(ch); - - /* Perform auto-creation for non-existing objects */ - if (numnew != 0) - error = create_objects_compat(ch, rule->cmd, oib, pidx, ti); - - /* Calculate real number of dynamic objects */ - ci->object_opcodes = (uint16_t)(pidx - oib); - - return (error); -} - -/* - * Checks is opcode is referencing table of appropriate type. - * Adds reference count for found table if true. - * Rewrites user-supplied opcode values with kernel ones. - * - * Returns 0 on success and appropriate error code otherwise. - */ -int -ipfw_rewrite_rule_uidx(struct ip_fw_chain *chain, - struct rule_check_info *ci) -{ - int error; - ipfw_insn *cmd; - uint8_t type; - struct obj_idx *p, *pidx_first, *pidx_last; - struct tid_info ti; - - /* - * Prepare an array for storing opcode indices. - * Use stack allocation by default. - */ - if (ci->object_opcodes <= (sizeof(ci->obuf)/sizeof(ci->obuf[0]))) { - /* Stack */ - pidx_first = ci->obuf; - } else - pidx_first = malloc(ci->object_opcodes * sizeof(struct obj_idx), - M_IPFW, M_WAITOK | M_ZERO); - - error = 0; - type = 0; - memset(&ti, 0, sizeof(ti)); - - /* - * Use default set for looking up tables (old way) or - * use set rule is assigned to (new way). - */ - ti.set = (V_fw_tables_sets != 0) ? ci->krule->set : 0; - if (ci->ctlv != NULL) { - ti.tlvs = (void *)(ci->ctlv + 1); - ti.tlen = ci->ctlv->head.length - sizeof(ipfw_obj_ctlv); - } - - /* Reference all used tables and other objects */ - error = ref_rule_objects(chain, ci->krule, ci, pidx_first, &ti); - if (error != 0) - goto free; - /* - * Note that ref_rule_objects() might have updated ci->object_opcodes - * to reflect actual number of object opcodes. - */ - - /* Perform rule rewrite */ - p = pidx_first; - pidx_last = pidx_first + ci->object_opcodes; - for (p = pidx_first; p < pidx_last; p++) { - cmd = ci->krule->cmd + p->off; - update_opcode_kidx(cmd, p->kidx); - } - -free: - if (pidx_first != ci->obuf) - free(pidx_first, M_IPFW); - - return (error); -} - static struct ipfw_sopt_handler scodes[] = { { IP_FW_TABLE_XCREATE, 0, HDIR_SET, create_table }, { IP_FW_TABLE_XDESTROY, 0, HDIR_SET, flush_table_v0 }, |