summaryrefslogtreecommitdiffstats
path: root/sys/netinet/ipfw
diff options
context:
space:
mode:
authormelifaro <melifaro@FreeBSD.org>2012-03-25 20:37:59 +0000
committermelifaro <melifaro@FreeBSD.org>2012-03-25 20:37:59 +0000
commit97c3a90503d7ac77bc3c91a3910e5112ea4f1bb2 (patch)
treecc5736172eadfb11a89781cc57af9cf6e64f57d2 /sys/netinet/ipfw
parent96b099d4c47ca4e52fbc294eeb3f76bbff60ef05 (diff)
downloadFreeBSD-src-97c3a90503d7ac77bc3c91a3910e5112ea4f1bb2.zip
FreeBSD-src-97c3a90503d7ac77bc3c91a3910e5112ea4f1bb2.tar.gz
- 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
Diffstat (limited to 'sys/netinet/ipfw')
-rw-r--r--sys/netinet/ipfw/ip_fw2.c45
-rw-r--r--sys/netinet/ipfw/ip_fw_private.h5
-rw-r--r--sys/netinet/ipfw/ip_fw_table.c62
3 files changed, 99 insertions, 13 deletions
diff --git a/sys/netinet/ipfw/ip_fw2.c b/sys/netinet/ipfw/ip_fw2.c
index a678910..21a00bb 100644
--- a/sys/netinet/ipfw/ip_fw2.c
+++ b/sys/netinet/ipfw/ip_fw2.c
@@ -116,8 +116,9 @@ static int default_to_accept;
VNET_DEFINE(int, autoinc_step);
VNET_DEFINE(int, fw_one_pass) = 1;
+VNET_DEFINE(unsigned int, fw_tables_max);
/* 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).
@@ -148,6 +149,7 @@ ipfw_nat_cfg_t *ipfw_nat_get_log_ptr;
#ifdef SYSCTL_NODE
uint32_t dummy_def = IPFW_DEFAULT_RULE;
+static int sysctl_ipfw_table_num(SYSCTL_HANDLER_ARGS);
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,
&dummy_def, 0,
"The default/max possible rule number.");
-SYSCTL_UINT(_net_inet_ip_fw, OID_AUTO, tables_max, CTLFLAG_RD,
- &V_fw_tables_max, 0,
- "The maximum number of tables.");
+SYSCTL_VNET_PROC(_net_inet_ip_fw, OID_AUTO, tables_max,
+ CTLTYPE_UINT|CTLFLAG_RW, 0, 0, sysctl_ipfw_table_num, "IU",
+ "Maximum number of tables");
SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, default_to_accept, CTLFLAG_RDTUN,
&default_to_accept, 0,
"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.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,
CTLFLAG_RD, &VNET_NAME(layer3_chain.n_rules), 0,
"Number of static rules");
@@ -2488,6 +2490,26 @@ pullup_failed:
}
/*
+ * 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
*/
@@ -2543,6 +2565,10 @@ ipfw_init(void)
printf("limited to %d packets/entry by default\n",
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 */
return (error);
}
@@ -2585,18 +2611,15 @@ vnet_ipfw_init(const void *unused)
LIST_INIT(&chain->nat);
#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 */
chain->n_rules = 1;
chain->static_len = sizeof(struct ip_fw);
chain->map = malloc(sizeof(struct ip_fw *), M_IPFW, M_WAITOK | M_ZERO);
if (chain->map)
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);
if (error) {
printf("ipfw2: setting up tables failed\n");
diff --git a/sys/netinet/ipfw/ip_fw_private.h b/sys/netinet/ipfw/ip_fw_private.h
index 84d927b..7f65c41 100644
--- a/sys/netinet/ipfw/ip_fw_private.h
+++ b/sys/netinet/ipfw/ip_fw_private.h
@@ -209,8 +209,8 @@ VNET_DECLARE(u_int32_t, set_disable);
VNET_DECLARE(int, autoinc_step);
#define V_autoinc_step VNET(autoinc_step)
-extern int fw_tables_max;
-#define V_fw_tables_max fw_tables_max
+VNET_DECLARE(unsigned int, fw_tables_max);
+#define V_fw_tables_max VNET(fw_tables_max)
struct ip_fw_chain {
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_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_resize_tables(struct ip_fw_chain *ch, unsigned int ntables);
/* In ip_fw_nat.c -- XXX to be moved to ip_var.h */
diff --git a/sys/netinet/ipfw/ip_fw_table.c b/sys/netinet/ipfw/ip_fw_table.c
index 8ca8ef7..9de5d53 100644
--- a/sys/netinet/ipfw/ip_fw_table.c
+++ b/sys/netinet/ipfw/ip_fw_table.c
@@ -460,6 +460,68 @@ ipfw_init_tables(struct ip_fw_chain *ch)
}
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
ipfw_lookup_table(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr,
uint32_t *val)
{
OpenPOWER on IntegriCloud