Catch ipfw up to the rest of the vimage code.

It got left behind when it moved to its new location.

Approved by:	re (kensmith)
This commit is contained in:
Julian Elischer 2009-07-25 06:42:42 +00:00
parent 45289e2ded
commit 9d85f50ad5

View File

@ -152,6 +152,8 @@ struct table_entry {
static VNET_DEFINE(int, autoinc_step);
#define V_autoinc_step VNET(autoinc_step)
static VNET_DEFINE(int, fw_deny_unknown_exthdrs);
#define V_fw_deny_unknown_exthdrs VNET(fw_deny_unknown_exthdrs)
extern int ipfw_chg_hook(SYSCTL_HANDLER_ARGS);
@ -161,24 +163,38 @@ SYSCTL_VNET_PROC(_net_inet_ip_fw, OID_AUTO, enable,
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE3, &VNET_NAME(fw_enable), 0,
ipfw_chg_hook, "I", "Enable ipfw");
SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, autoinc_step,
CTLFLAG_RW, &VNET_NAME(autoinc_step), 0, "Rule number auto-increment step");
CTLFLAG_RW, &VNET_NAME(autoinc_step), 0,
"Rule number auto-increment step");
SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, one_pass,
CTLFLAG_RW | CTLFLAG_SECURE3, &VNET_NAME(fw_one_pass), 0,
"Only do a single pass through ipfw when using dummynet(4)");
SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, verbose,
CTLFLAG_RW | CTLFLAG_SECURE3,
&VNET_NAME(fw_verbose), 0, "Log matches to ipfw rules");
CTLFLAG_RW | CTLFLAG_SECURE3, &VNET_NAME(fw_verbose), 0,
"Log matches to ipfw rules");
SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, verbose_limit,
CTLFLAG_RW, &VNET_NAME(verbose_limit), 0,
"Set upper limit of matches of ipfw rules logged");
SYSCTL_UINT(_net_inet_ip_fw, OID_AUTO, default_rule, CTLFLAG_RD,
NULL, IPFW_DEFAULT_RULE, "The default/max possible rule number.");
NULL, IPFW_DEFAULT_RULE,
"The default/max possible rule number.");
SYSCTL_UINT(_net_inet_ip_fw, OID_AUTO, tables_max, CTLFLAG_RD,
NULL, IPFW_TABLES_MAX, "The maximum number of tables.");
NULL, IPFW_TABLES_MAX,
"The 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.");
&default_to_accept, 0,
"Make the default rule accept all packets.");
TUNABLE_INT("net.inet.ip.fw.default_to_accept", &default_to_accept);
#endif /* SYSCTL_NODE */
#ifdef INET6
SYSCTL_DECL(_net_inet6_ip6);
SYSCTL_NODE(_net_inet6_ip6, OID_AUTO, fw, CTLFLAG_RW, 0, "Firewall");
SYSCTL_VNET_PROC(_net_inet6_ip6_fw, OID_AUTO, enable,
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE3, &VNET_NAME(fw6_enable), 0,
ipfw_chg_hook, "I", "Enable ipfw+6");
SYSCTL_VNET_INT(_net_inet6_ip6_fw, OID_AUTO, deny_unknown_exthdrs,
CTLFLAG_RW | CTLFLAG_SECURE, &VNET_NAME(fw_deny_unknown_exthdrs), 0,
"Deny packets with unknown IPv6 Extension Headers");
#endif
#endif
/*
* Description of dynamic rules.
@ -277,16 +293,20 @@ static VNET_DEFINE(u_int32_t, dyn_max); /* max # of dynamic rules */
#ifdef SYSCTL_NODE
SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, dyn_buckets,
CTLFLAG_RW, &VNET_NAME(dyn_buckets), 0, "Number of dyn. buckets");
CTLFLAG_RW, &VNET_NAME(dyn_buckets), 0,
"Number of dyn. buckets");
SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, curr_dyn_buckets,
CTLFLAG_RD, &VNET_NAME(curr_dyn_buckets), 0,
"Current Number of dyn. buckets");
SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, dyn_count,
CTLFLAG_RD, &VNET_NAME(dyn_count), 0, "Number of dyn. rules");
CTLFLAG_RD, &VNET_NAME(dyn_count), 0,
"Number of dyn. rules");
SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, dyn_max,
CTLFLAG_RW, &VNET_NAME(dyn_max), 0, "Max number of dyn. rules");
CTLFLAG_RW, &VNET_NAME(dyn_max), 0,
"Max number of dyn. rules");
SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, static_count,
CTLFLAG_RD, &VNET_NAME(static_count), 0, "Number of static rules");
CTLFLAG_RD, &VNET_NAME(static_count), 0,
"Number of static rules");
SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, dyn_ack_lifetime,
CTLFLAG_RW, &VNET_NAME(dyn_ack_lifetime), 0,
"Lifetime of dyn. rules for acks");
@ -310,21 +330,6 @@ SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, dyn_keepalive,
"Enable keepalives for dyn. rules");
#endif /* SYSCTL_NODE */
#ifdef INET6
/*
* IPv6 specific variables
*/
#ifdef SYSCTL_NODE
SYSCTL_DECL(_net_inet6_ip6);
#endif /* SYSCTL_NODE */
static struct sysctl_ctx_list ip6_fw_sysctl_ctx;
static struct sysctl_oid *ip6_fw_sysctl_tree;
#endif /* INET6 */
static VNET_DEFINE(int, fw_deny_unknown_exthdrs);
#define V_fw_deny_unknown_exthdrs VNET(fw_deny_unknown_exthdrs)
/*
* L3HDR maps an ipv4 pointer into a layer3 header pointer of type T
* Other macros just cast void * into the appropriate type
@ -4511,17 +4516,22 @@ ipfw_ctl(struct sockopt *sopt)
#undef RULE_MAXSIZE
}
/*
* This procedure is only used to handle keepalives. It is invoked
* every dyn_keepalive_period
*/
static void
ipfw_tick(void * __unused unused)
ipfw_tick(void * vnetx)
{
struct mbuf *m0, *m, *mnext, **mtailp;
int i;
ipfw_dyn_rule *q;
#ifdef VIMAGE
struct vnet *vp = vnetx;
#endif
CURVNET_SET(vp);
if (V_dyn_keepalive == 0 || V_ipfw_dyn_v == NULL || V_dyn_count == 0)
goto done;
@ -4566,80 +4576,29 @@ ipfw_tick(void * __unused unused)
}
done:
callout_reset(&V_ipfw_timeout, V_dyn_keepalive_period * hz,
ipfw_tick, NULL);
ipfw_tick, vnetx);
CURVNET_RESTORE();
}
/****************
* Stuff that must be initialised only on boot or module load
*/
int
ipfw_init(void)
{
struct ip_fw default_rule;
int error;
int error = 0;
V_autoinc_step = 100; /* bounded to 1..1000 in add_rule() */
V_ipfw_dyn_v = NULL;
V_dyn_buckets = 256; /* must be power of 2 */
V_curr_dyn_buckets = 256; /* must be power of 2 */
V_dyn_ack_lifetime = 300;
V_dyn_syn_lifetime = 20;
V_dyn_fin_lifetime = 1;
V_dyn_rst_lifetime = 1;
V_dyn_udp_lifetime = 10;
V_dyn_short_lifetime = 5;
V_dyn_keepalive_interval = 20;
V_dyn_keepalive_period = 5;
V_dyn_keepalive = 1; /* do send keepalives */
V_dyn_max = 4096; /* max # of dynamic rules */
V_fw_deny_unknown_exthdrs = 1;
#ifdef INET6
/* Setup IPv6 fw sysctl tree. */
sysctl_ctx_init(&ip6_fw_sysctl_ctx);
ip6_fw_sysctl_tree = SYSCTL_ADD_NODE(&ip6_fw_sysctl_ctx,
SYSCTL_STATIC_CHILDREN(_net_inet6_ip6), OID_AUTO, "fw",
CTLFLAG_RW | CTLFLAG_SECURE, 0, "Firewall");
SYSCTL_ADD_PROC(&ip6_fw_sysctl_ctx, SYSCTL_CHILDREN(ip6_fw_sysctl_tree),
OID_AUTO, "enable", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE3,
&V_fw6_enable, 0, ipfw_chg_hook, "I", "Enable ipfw+6");
SYSCTL_ADD_INT(&ip6_fw_sysctl_ctx, SYSCTL_CHILDREN(ip6_fw_sysctl_tree),
OID_AUTO, "deny_unknown_exthdrs", CTLFLAG_RW | CTLFLAG_SECURE,
&V_fw_deny_unknown_exthdrs, 0,
"Deny packets with unknown IPv6 Extension Headers");
#endif
V_layer3_chain.rules = NULL;
IPFW_LOCK_INIT(&V_layer3_chain);
ipfw_dyn_rule_zone = uma_zcreate("IPFW dynamic rule",
sizeof(ipfw_dyn_rule), NULL, NULL, NULL, NULL,
UMA_ALIGN_PTR, 0);
IPFW_DYN_LOCK_INIT();
callout_init(&V_ipfw_timeout, CALLOUT_MPSAFE);
bzero(&default_rule, sizeof default_rule);
default_rule.act_ofs = 0;
default_rule.rulenum = IPFW_DEFAULT_RULE;
default_rule.cmd_len = 1;
default_rule.set = RESVD_SET;
default_rule.cmd[0].len = 1;
default_rule.cmd[0].opcode = default_to_accept ? O_ACCEPT : O_DENY;
error = add_rule(&V_layer3_chain, &default_rule);
if (error != 0) {
printf("ipfw2: error %u initializing default rule "
"(support disabled)\n", error);
IPFW_DYN_LOCK_DESTROY();
IPFW_LOCK_DESTROY(&V_layer3_chain);
uma_zdestroy(ipfw_dyn_rule_zone);
return (error);
}
ip_fw_default_rule = V_layer3_chain.rules;
/*
* Only print out this stuff the first time around,
* when called from the sysinit code.
*/
printf("ipfw2 "
#ifdef INET6
"(+ipv6) "
@ -4662,15 +4621,13 @@ ipfw_init(void)
#else
"loadable",
#endif
default_to_accept ? "accept" : "deny");
default_rule.cmd[0].opcode == O_ACCEPT ? "accept" : "deny");
#ifdef IPFIREWALL_VERBOSE
V_fw_verbose = 1;
#endif
#ifdef IPFIREWALL_VERBOSE_LIMIT
V_verbose_limit = IPFIREWALL_VERBOSE_LIMIT;
#endif
/*
* Note: V_xxx variables can be accessed here but the iattach()
* may not have been called yet for the VIMGE case.
* Tuneables will have been processed.
*/
if (V_fw_verbose == 0)
printf("disabled\n");
else if (V_verbose_limit == 0)
@ -4679,44 +4636,141 @@ ipfw_init(void)
printf("limited to %d packets/entry by default\n",
V_verbose_limit);
error = init_tables(&V_layer3_chain);
if (error) {
IPFW_DYN_LOCK_DESTROY();
IPFW_LOCK_DESTROY(&V_layer3_chain);
uma_zdestroy(ipfw_dyn_rule_zone);
return (error);
}
/*
* Other things that are only done the first time.
* (now that we a re cuaranteed of success).
*/
ip_fw_ctl_ptr = ipfw_ctl;
ip_fw_chk_ptr = ipfw_chk;
callout_reset(&V_ipfw_timeout, hz, ipfw_tick, NULL);
return (error);
}
/****************
* Stuff that must be initialised for every instance
* (including the forst of course).
*/
static int
vnet_ipfw_init(const void *unused)
{
int error;
struct ip_fw default_rule;
/* First set up some values that are compile time options */
#ifdef IPFIREWALL_VERBOSE
V_fw_verbose = 1;
#endif
#ifdef IPFIREWALL_VERBOSE_LIMIT
V_verbose_limit = IPFIREWALL_VERBOSE_LIMIT;
#endif
error = init_tables(&V_layer3_chain);
if (error) {
panic("init_tables"); /* XXX Marko fix this ! */
}
#ifdef IPFIREWALL_NAT
LIST_INIT(&V_layer3_chain.nat);
#endif
V_autoinc_step = 100; /* bounded to 1..1000 in add_rule() */
V_ipfw_dyn_v = NULL;
V_dyn_buckets = 256; /* must be power of 2 */
V_curr_dyn_buckets = 256; /* must be power of 2 */
V_dyn_ack_lifetime = 300;
V_dyn_syn_lifetime = 20;
V_dyn_fin_lifetime = 1;
V_dyn_rst_lifetime = 1;
V_dyn_udp_lifetime = 10;
V_dyn_short_lifetime = 5;
V_dyn_keepalive_interval = 20;
V_dyn_keepalive_period = 5;
V_dyn_keepalive = 1; /* do send keepalives */
V_dyn_max = 4096; /* max # of dynamic rules */
V_fw_deny_unknown_exthdrs = 1;
V_layer3_chain.rules = NULL;
IPFW_LOCK_INIT(&V_layer3_chain);
callout_init(&V_ipfw_timeout, CALLOUT_MPSAFE);
bzero(&default_rule, sizeof default_rule);
default_rule.act_ofs = 0;
default_rule.rulenum = IPFW_DEFAULT_RULE;
default_rule.cmd_len = 1;
default_rule.set = RESVD_SET;
default_rule.cmd[0].len = 1;
default_rule.cmd[0].opcode = default_to_accept ? O_ACCEPT : O_DENY;
error = add_rule(&V_layer3_chain, &default_rule);
if (error != 0) {
printf("ipfw2: error %u initializing default rule "
"(support disabled)\n", error);
IPFW_LOCK_DESTROY(&V_layer3_chain);
printf("leaving ipfw_iattach (1) with error %d\n", error);
return (error);
}
ip_fw_default_rule = V_layer3_chain.rules;
if (error) {
IPFW_LOCK_DESTROY(&V_layer3_chain);
printf("leaving ipfw_iattach (2) with error %d\n", error);
return (error);
}
#ifdef VIMAGE /* want a better way to do this */
callout_reset(&V_ipfw_timeout, hz, ipfw_tick, curvnet);
#else
callout_reset(&V_ipfw_timeout, hz, ipfw_tick, NULL);
#endif
/* First set up some values that are compile time options */
return (0);
}
/**********************
* Called for the removal of the last instance only on module unload.
*/
void
ipfw_destroy(void)
{
struct ip_fw *reap;
ip_fw_chk_ptr = NULL;
ip_fw_ctl_ptr = NULL;
uma_zdestroy(ipfw_dyn_rule_zone);
IPFW_DYN_LOCK_DESTROY();
printf("IP firewall unloaded\n");
}
/***********************
* Called for the removal of each instance.
*/
static int
vnet_ipfw_uninit(const void *unused)
{
struct ip_fw *reap;
callout_drain(&V_ipfw_timeout);
IPFW_WLOCK(&V_layer3_chain);
flush_tables(&V_layer3_chain);
V_layer3_chain.reap = NULL;
free_chain(&V_layer3_chain, 1 /* kill default rule */);
reap = V_layer3_chain.reap;
V_layer3_chain.reap = NULL;
IPFW_WUNLOCK(&V_layer3_chain);
reap_rules(reap);
IPFW_DYN_LOCK_DESTROY();
uma_zdestroy(ipfw_dyn_rule_zone);
if (reap != NULL)
reap_rules(reap);
IPFW_LOCK_DESTROY(&V_layer3_chain);
if (V_ipfw_dyn_v != NULL)
free(V_ipfw_dyn_v, M_IPFW);
IPFW_LOCK_DESTROY(&V_layer3_chain);
#ifdef INET6
/* Free IPv6 fw sysctl tree. */
sysctl_ctx_free(&ip6_fw_sysctl_ctx);
#endif
printf("IP firewall unloaded\n");
return 0;
}
VNET_SYSINIT(vnet_ipfw_init, SI_SUB_KTHREAD_INIT, SI_ORDER_ANY,
vnet_ipfw_init, NULL);
VNET_SYSUNINIT(vnet_ipfw_uninit, SI_SUB_KTHREAD_INIT, SI_ORDER_ANY,
vnet_ipfw_uninit, NULL);