diff --git a/sys/netpfil/ipfw/ip_fw_table.c b/sys/netpfil/ipfw/ip_fw_table.c index 000a8df88457..84a13fa5dff7 100644 --- a/sys/netpfil/ipfw/ip_fw_table.c +++ b/sys/netpfil/ipfw/ip_fw_table.c @@ -2876,13 +2876,12 @@ table_manage_sets(struct ip_fw_chain *ch, uint16_t set, uint8_t new_set, switch (cmd) { case SWAP_ALL: case TEST_ALL: - /* - * Return success for TEST_ALL, since nothing prevents - * move rules from one set to another. All tables are - * accessible from all sets when per-set tables sysctl - * is disabled. - */ case MOVE_ALL: + /* + * Always return success, the real action and decision + * should make table_manage_sets_all(). + */ + return (0); case TEST_ONE: case MOVE_ONE: /* @@ -2907,6 +2906,39 @@ table_manage_sets(struct ip_fw_chain *ch, uint16_t set, uint8_t new_set, set, new_set, cmd)); } +/* + * We register several opcode rewriters for lookup tables. + * All tables opcodes have the same ETLV type, but different subtype. + * To avoid invoking sets handler several times for XXX_ALL commands, + * we use separate manage_sets handler. O_RECV has the lowest value, + * so it should be called first. + */ +static int +table_manage_sets_all(struct ip_fw_chain *ch, uint16_t set, uint8_t new_set, + enum ipfw_sets_cmd cmd) +{ + + switch (cmd) { + case SWAP_ALL: + case TEST_ALL: + /* + * Return success for TEST_ALL, since nothing prevents + * move rules from one set to another. All tables are + * accessible from all sets when per-set tables sysctl + * is disabled. + */ + case MOVE_ALL: + if (V_fw_tables_sets == 0) + return (0); + break; + default: + return (table_manage_sets(ch, set, new_set, cmd)); + } + /* Use generic sets handler when per-set sysctl is enabled. */ + return (ipfw_obj_manage_sets(CHAIN_TO_NI(ch), IPFW_TLV_TBL_NAME, + set, new_set, cmd)); +} + static struct opcode_obj_rewrite opcodes[] = { { .opcode = O_IP_SRC_LOOKUP, @@ -2956,7 +2988,7 @@ static struct opcode_obj_rewrite opcodes[] = { .find_byname = table_findbyname, .find_bykidx = table_findbykidx, .create_object = create_table_compat, - .manage_sets = table_manage_sets, + .manage_sets = table_manage_sets_all, }, { .opcode = O_VIA,