- Permit number of ipfw tables to be changed in runtime.

net.inet.ip.fw.tables_max is now read-write.

- Bump IPFW_TABLES_MAX to 65535
Default number of tables is still 128

- Remove IPFW_TABLES_MAX from ipfw(8) code.

Sponsored by Yandex LLC

Approved by:    kib(mentor)

MFC after:      2 weeks
This commit is contained in:
Alexander V. Chernikov 2012-03-25 20:37:59 +00:00
parent edf5bf9919
commit 732d27b32d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=233478
6 changed files with 105 additions and 24 deletions

View File

@ -2845,7 +2845,7 @@ node is not passed though the firewall again.
Otherwise, after an action, the packet is Otherwise, after an action, the packet is
reinjected into the firewall at the next rule. reinjected into the firewall at the next rule.
.It Va net.inet.ip.fw.tables_max : No 128 .It Va net.inet.ip.fw.tables_max : No 128
Maximum number of tables (read-only). Maximum number of tables.
.It Va net.inet.ip.fw.verbose : No 1 .It Va net.inet.ip.fw.verbose : No 1
Enables verbose messages. Enables verbose messages.
.It Va net.inet.ip.fw.verbose_limit : No 0 .It Va net.inet.ip.fw.verbose_limit : No 0

View File

@ -3932,15 +3932,9 @@ ipfw_table_handler(int ac, char *av[])
len = sizeof(tables_max); len = sizeof(tables_max);
if (sysctlbyname("net.inet.ip.fw.tables_max", &tables_max, &len, if (sysctlbyname("net.inet.ip.fw.tables_max", &tables_max, &len,
NULL, 0) == -1) { NULL, 0) == -1)
#ifdef IPFW_TABLES_MAX errx(1, "Can't determine maximum number of ipfw tables. "
warn("Warn: Failed to get the max tables number via sysctl. " "Perhaps you forgot to load ipfw module?");
"Using the compiled in defaults. \nThe reason was");
tables_max = IPFW_TABLES_MAX;
#else
errx(1, "Failed sysctlbyname(\"net.inet.ip.fw.tables_max\")");
#endif
}
memset(&xent, 0, sizeof(xent)); memset(&xent, 0, sizeof(xent));

View File

@ -39,7 +39,8 @@
/* /*
* Default number of ipfw tables. * Default number of ipfw tables.
*/ */
#define IPFW_TABLES_MAX 128 #define IPFW_TABLES_MAX 65535
#define IPFW_TABLES_DEFAULT 128
/* /*
* Most commands (queue, pipe, tag, untag, limit...) can have a 16-bit * Most commands (queue, pipe, tag, untag, limit...) can have a 16-bit

View File

@ -116,8 +116,9 @@ static int default_to_accept;
VNET_DEFINE(int, autoinc_step); VNET_DEFINE(int, autoinc_step);
VNET_DEFINE(int, fw_one_pass) = 1; VNET_DEFINE(int, fw_one_pass) = 1;
VNET_DEFINE(unsigned int, fw_tables_max);
/* Use 128 tables by default */ /* Use 128 tables by default */
int fw_tables_max = IPFW_TABLES_MAX; static unsigned int default_fw_tables = IPFW_TABLES_DEFAULT;
/* /*
* Each rule belongs to one of 32 different sets (0..31). * Each rule belongs to one of 32 different sets (0..31).
@ -148,6 +149,7 @@ ipfw_nat_cfg_t *ipfw_nat_get_log_ptr;
#ifdef SYSCTL_NODE #ifdef SYSCTL_NODE
uint32_t dummy_def = IPFW_DEFAULT_RULE; uint32_t dummy_def = IPFW_DEFAULT_RULE;
static int sysctl_ipfw_table_num(SYSCTL_HANDLER_ARGS);
SYSBEGIN(f3) SYSBEGIN(f3)
@ -167,14 +169,14 @@ SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, verbose_limit,
SYSCTL_UINT(_net_inet_ip_fw, OID_AUTO, default_rule, CTLFLAG_RD, SYSCTL_UINT(_net_inet_ip_fw, OID_AUTO, default_rule, CTLFLAG_RD,
&dummy_def, 0, &dummy_def, 0,
"The default/max possible rule number."); "The default/max possible rule number.");
SYSCTL_UINT(_net_inet_ip_fw, OID_AUTO, tables_max, CTLFLAG_RD, SYSCTL_VNET_PROC(_net_inet_ip_fw, OID_AUTO, tables_max,
&V_fw_tables_max, 0, CTLTYPE_UINT|CTLFLAG_RW, 0, 0, sysctl_ipfw_table_num, "IU",
"The maximum number of tables."); "Maximum number of tables");
SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, default_to_accept, CTLFLAG_RDTUN, SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, default_to_accept, CTLFLAG_RDTUN,
&default_to_accept, 0, &default_to_accept, 0,
"Make the default rule accept all packets."); "Make the default rule accept all packets.");
TUNABLE_INT("net.inet.ip.fw.default_to_accept", &default_to_accept); TUNABLE_INT("net.inet.ip.fw.default_to_accept", &default_to_accept);
TUNABLE_INT("net.inet.ip.fw.tables_max", &V_fw_tables_max); TUNABLE_INT("net.inet.ip.fw.tables_max", &default_fw_tables);
SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, static_count, SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, static_count,
CTLFLAG_RD, &VNET_NAME(layer3_chain.n_rules), 0, CTLFLAG_RD, &VNET_NAME(layer3_chain.n_rules), 0,
"Number of static rules"); "Number of static rules");
@ -2487,6 +2489,26 @@ do { \
return (IP_FW_DENY); return (IP_FW_DENY);
} }
/*
* Set maximum number of tables that can be used in given VNET ipfw instance.
*/
#ifdef SYSCTL_NODE
static int
sysctl_ipfw_table_num(SYSCTL_HANDLER_ARGS)
{
int error;
unsigned int ntables;
ntables = V_fw_tables_max;
error = sysctl_handle_int(oidp, &ntables, 0, req);
/* Read operation or some error */
if ((error != 0) || (req->newptr == NULL))
return (error);
return (ipfw_resize_tables(&V_layer3_chain, ntables));
}
#endif
/* /*
* Module and VNET glue * Module and VNET glue
*/ */
@ -2543,6 +2565,10 @@ ipfw_init(void)
printf("limited to %d packets/entry by default\n", printf("limited to %d packets/entry by default\n",
V_verbose_limit); V_verbose_limit);
/* Check user-supplied table count for validness */
if (default_fw_tables > IPFW_TABLES_MAX)
default_fw_tables = IPFW_TABLES_MAX;
ipfw_log_bpf(1); /* init */ ipfw_log_bpf(1); /* init */
return (error); return (error);
} }
@ -2585,18 +2611,15 @@ vnet_ipfw_init(const void *unused)
LIST_INIT(&chain->nat); LIST_INIT(&chain->nat);
#endif #endif
/* Check user-supplied number for validness */
if (V_fw_tables_max < 0)
V_fw_tables_max = IPFW_TABLES_MAX;
if (V_fw_tables_max > 65534)
V_fw_tables_max = 65534;
/* insert the default rule and create the initial map */ /* insert the default rule and create the initial map */
chain->n_rules = 1; chain->n_rules = 1;
chain->static_len = sizeof(struct ip_fw); chain->static_len = sizeof(struct ip_fw);
chain->map = malloc(sizeof(struct ip_fw *), M_IPFW, M_WAITOK | M_ZERO); chain->map = malloc(sizeof(struct ip_fw *), M_IPFW, M_WAITOK | M_ZERO);
if (chain->map) if (chain->map)
rule = malloc(chain->static_len, M_IPFW, M_WAITOK | M_ZERO); rule = malloc(chain->static_len, M_IPFW, M_WAITOK | M_ZERO);
/* Set initial number of tables */
V_fw_tables_max = default_fw_tables;
error = ipfw_init_tables(chain); error = ipfw_init_tables(chain);
if (error) { if (error) {
printf("ipfw2: setting up tables failed\n"); printf("ipfw2: setting up tables failed\n");

View File

@ -209,8 +209,8 @@ VNET_DECLARE(u_int32_t, set_disable);
VNET_DECLARE(int, autoinc_step); VNET_DECLARE(int, autoinc_step);
#define V_autoinc_step VNET(autoinc_step) #define V_autoinc_step VNET(autoinc_step)
extern int fw_tables_max; VNET_DECLARE(unsigned int, fw_tables_max);
#define V_fw_tables_max fw_tables_max #define V_fw_tables_max VNET(fw_tables_max)
struct ip_fw_chain { struct ip_fw_chain {
struct ip_fw *rules; /* list of rules */ struct ip_fw *rules; /* list of rules */
@ -292,6 +292,7 @@ int ipfw_dump_table_entry(struct radix_node *rn, void *arg);
int ipfw_dump_table(struct ip_fw_chain *ch, ipfw_table *tbl); int ipfw_dump_table(struct ip_fw_chain *ch, ipfw_table *tbl);
int ipfw_count_xtable(struct ip_fw_chain *ch, uint32_t tbl, uint32_t *cnt); int ipfw_count_xtable(struct ip_fw_chain *ch, uint32_t tbl, uint32_t *cnt);
int ipfw_dump_xtable(struct ip_fw_chain *ch, ipfw_xtable *tbl); int ipfw_dump_xtable(struct ip_fw_chain *ch, ipfw_xtable *tbl);
int ipfw_resize_tables(struct ip_fw_chain *ch, unsigned int ntables);
/* In ip_fw_nat.c -- XXX to be moved to ip_var.h */ /* In ip_fw_nat.c -- XXX to be moved to ip_var.h */

View File

@ -459,6 +459,68 @@ ipfw_init_tables(struct ip_fw_chain *ch)
return (0); return (0);
} }
int
ipfw_resize_tables(struct ip_fw_chain *ch, unsigned int ntables)
{
struct radix_node_head **tables, **xtables, *rnh;
struct radix_node_head **tables_old, **xtables_old;
uint8_t *tabletype, *tabletype_old;
unsigned int ntables_old, tbl;
/* Check new value for validity */
if (ntables > IPFW_TABLES_MAX)
ntables = IPFW_TABLES_MAX;
/* Allocate new pointers */
tables = malloc(ntables * sizeof(void *), M_IPFW, M_WAITOK | M_ZERO);
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);
tbl = (ntables >= V_fw_tables_max) ? V_fw_tables_max : ntables;
/* Copy old table pointers */
memcpy(tables, ch->tables, sizeof(void *) * tbl);
memcpy(xtables, ch->xtables, sizeof(void *) * tbl);
memcpy(tabletype, ch->tabletype, sizeof(uint8_t) * tbl);
/* Change pointers and number of tables */
tables_old = ch->tables;
xtables_old = ch->xtables;
tabletype_old = ch->tabletype;
ch->tables = tables;
ch->xtables = xtables;
ch->tabletype = tabletype;
ntables_old = V_fw_tables_max;
V_fw_tables_max = ntables;
IPFW_WUNLOCK(ch);
/* Check if we need to destroy radix trees */
if (ntables < ntables_old) {
for (tbl = ntables; tbl < ntables_old; tbl++) {
if ((rnh = tables_old[tbl]) != NULL) {
rnh->rnh_walktree(rnh, flush_table_entry, rnh);
rn_detachhead((void **)&rnh);
}
if ((rnh = xtables_old[tbl]) != NULL) {
rnh->rnh_walktree(rnh, flush_table_entry, rnh);
rn_detachhead((void **)&rnh);
}
}
}
/* Free old pointers */
free(tables_old, M_IPFW);
free(xtables_old, M_IPFW);
free(tabletype_old, M_IPFW);
return (0);
}
int int
ipfw_lookup_table(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr, ipfw_lookup_table(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr,
uint32_t *val) uint32_t *val)