#include <net/pf_mtag.h>
#include <net/vnet.h>
-#ifdef linux
-#define INP_LOCK_ASSERT /* define before missing.h otherwise ? */
-#include "missing.h"
-#endif
-
#define IPFW_INTERNAL /* Access to protected data structures in ip_fw.h. */
#include <netinet/in.h>
#include <machine/in_cksum.h> /* XXX for in_cksum */
-#ifdef IPFW_HASHTABLES
-#include "hashtable.h"
-#endif
-
#ifdef MAC
#include <security/mac/mac_framework.h>
#endif
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");
-static unsigned int dummy_default_rule = IPFW_DEFAULT_RULE;
+unsigned int dummy_default_rule = IPFW_DEFAULT_RULE;
SYSCTL_UINT(_net_inet_ip_fw, OID_AUTO, default_rule, CTLFLAG_RD,
&dummy_default_rule, IPFW_DEFAULT_RULE,
"The default/max possible rule number.");
-static unsigned int dummy_tables_max = IPFW_TABLES_MAX;
+unsigned int dummy_tables_max = IPFW_TABLES_MAX;
SYSCTL_UINT(_net_inet_ip_fw, OID_AUTO, tables_max, CTLFLAG_RD,
&dummy_tables_max, IPFW_TABLES_MAX,
"The maximum number of tables.");
-static unsigned int skipto_entries = 256;
-SYSCTL_UINT(_net_inet_ip_fw, OID_AUTO, skipto_entries,
- CTLFLAG_RW, &skipto_entries, 0,
- "Number of entries in the skipto cache");
SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, default_to_accept, CTLFLAG_RDTUN,
&default_to_accept, 0,
"Make the default rule accept all packets.");
args->m = NULL;
}
-static void
-set_skipto_table(struct ip_fw_chain *ch)
-{
- int i, n, sh;
- struct ip_fw *f, **t, **oldt;
-
- for (sh = 15; sh > 0; sh--)
- if (skipto_entries > 1<<sh)
- break;
- sh++;
- skipto_entries = 1<< (16 - sh) ;
- /* XXX unsafe and too long */
- t = malloc(skipto_entries * sizeof(*t), M_IPFW_TBL, M_WAITOK | M_ZERO);
- if (t == NULL)
- return;
- IPFW_RLOCK(ch);
- /* Store pointers in the table. In the loop i is the next
- * free slot, n is the slot where the current rule goes.
- */
- for (i = 0, f = ch->rules; f; f = f->next) {
- n = f->rulenum >> sh ;
- while (i <= n)
- t[i++] = f;
- }
- V_layer3_chain.skipto_shift = sh;
- V_layer3_chain.skipto_size = skipto_entries;
- oldt = V_layer3_chain.skipto_ptrs;
- V_layer3_chain.skipto_ptrs = t;
- IPFW_RUNLOCK(ch);
- if (oldt) {
- IPFW_WLOCK(ch);
- IPFW_WUNLOCK(ch);
- /* now can free oldt */
- free(oldt, M_IPFW_TBL);
- }
-}
-#if 0
-/*
- * Map a rule number to a rule pointer, using the skipto table.
- * First lookup the slot, then follow the chain until we find a
- * non-null entry with rulenum >= num. Return default_rule on error.
- */
-static struct ip_fw *
-rule2ptr(struct ip_fw_chain *ch, int num)
-{
- struct ip_fw *r = NULL;
- int ix = (num & 0xffff) >> ch->skipto_shift;
-
- while (ix < ch->skipto_size && (r = ch->skipto_ptrs[ix]) == NULL)
- ix++;
- while (r && num < r->rulenum)
- r = r->next;
- return (r ? r : ch->default_rule);
-}
-#endif
/**
*
* Given an ip_fw *, lookup_next_rule will return a pointer
*/
static struct ip_fw *
-lookup_next_rule(struct ip_fw_chain *ch, struct ip_fw *me, uint32_t tablearg)
+lookup_next_rule(struct ip_fw *me, u_int32_t tablearg)
{
struct ip_fw *rule = NULL;
ipfw_insn *cmd;
+ u_int16_t rulenum;
/* look for action, in case it is a skipto */
cmd = ACTION_PTR(me);
cmd += F_LEN(cmd);
if (cmd->opcode == O_TAG)
cmd += F_LEN(cmd);
- if (cmd->opcode != O_SKIPTO ) {
- rule = me->next;
- } else {
- tablearg = tablearg ? tablearg : cmd->arg1;
+ if (cmd->opcode == O_SKIPTO ) {
+ if (tablearg != 0) {
+ rulenum = (u_int16_t)tablearg;
+ } else {
+ rulenum = cmd->arg1;
+ }
for (rule = me->next; rule ; rule = rule->next) {
- if (rule->rulenum >= tablearg) {
+ if (rule->rulenum >= rulenum) {
break;
}
}
-
-// rule = rule2ptr(ch, tablearg ? tablearg : cmd->arg1);
}
- me->next_rule = rule; /* XXX perhaps unnecessary ? */
+ if (rule == NULL) /* failure or not a skipto */
+ rule = me->next;
+ me->next_rule = rule;
return rule;
}
struct table_entry *ent;
struct radix_node *rn;
-#ifdef IPFW_HASHTABLES
- if (tbl >= 2*IPFW_TABLES_MAX)
- return EINVAL;
- return EINVAL; // XXX to be completed
-#endif
if (tbl >= IPFW_TABLES_MAX)
return (EINVAL);
rnh = ch->tables[tbl];
struct table_entry *ent;
struct sockaddr_in sa, mask;
-#ifdef IPFW_HASHTABLES
- if (tbl >= 2*IPFW_TABLES_MAX)
- return EINVAL;
- return EINVAL; // XXX to be completed
-#endif
if (tbl >= IPFW_TABLES_MAX)
return (EINVAL);
rnh = ch->tables[tbl];
IPFW_WLOCK_ASSERT(ch);
-#ifdef IPFW_HASHTABLES
- if (tbl >= 2*IPFW_TABLES_MAX)
- return EINVAL;
- return EINVAL; // XXX to be completed
-#endif
if (tbl >= IPFW_TABLES_MAX)
return (EINVAL);
rnh = ch->tables[tbl];
for (tbl = 0; tbl < IPFW_TABLES_MAX; tbl++)
flush_table(ch, tbl);
-#ifdef IPFW_HASHTABLES
- for (tbl = 0; tbl < IPFW_TABLES_MAX; tbl++)
- ch->hashtab[tbl] = ipfw_ht_destroy(ch->hashtab[tbl]);
-#endif
}
static int
return (ENOMEM);
}
}
-#ifdef IPFW_HASHTABLES
- for (i = 0; i < IPFW_TABLES_MAX; i++)
- ch->hashtab[i] = ipfw_ht_destroy(ch->hashtab[i]);
-#endif
return (0);
}
f = args->rule->next_rule;
if (f == NULL)
- f = lookup_next_rule(chain, args->rule, 0);
+ f = lookup_next_rule(args->rule, 0);
} else {
/*
* Find the starting rule. It can be either the first
a = dst_port;
else if (v == 3)
a = src_port;
- else if (v >= 4 && v <= 6) {
+ else if (v == 4 || v == 5) {
check_uidgid(
(ipfw_insn_u32 *)cmd,
proto, oif,
#ifdef linux
if (v ==4 /* O_UID */)
a = ucred_cache.uid;
- else if (v == 5 /* O_GID */)
- a = ucred_cache.gid;
- else if (v == 6 /* O_JAIL */)
+ else if (v == 5 /* O_JAIL */)
a = ucred_cache.xid;
#else
if (v ==4 /* O_UID */)
a = (*uc)->cr_uid;
- else if (v == 5 /* O_GID */)
- ; // a = groupmember((gid_t)insn->d[0], *uc);
- else if (v == 6 /* O_JAIL */)
+ else if (v == 5 /* O_JAIL */)
a = (*uc)->cr_prison->pr_id;
#endif
} else
}
/* handle skipto */
if (cmd->arg1 == IP_FW_TABLEARG) {
- f = lookup_next_rule(chain, f, tablearg);
- } else {
+ f = lookup_next_rule(f, tablearg);
+ } else { // XXX ?
if (f->next_rule == NULL)
- lookup_next_rule(chain, f, 0);
+ lookup_next_rule(f, 0);
f = f->next_rule;
}
/*
goto done;
}
+ /*
+ * If rulenum is 0, find highest numbered rule before the
+ * default rule, and add autoinc_step
+ */
if (V_autoinc_step < 1)
V_autoinc_step = 1;
else if (V_autoinc_step > 1000)
V_autoinc_step = 1000;
if (rule->rulenum == 0) {
/*
- * If rulenum is 0, use highest numbered rule before
- * the default, adding autoinc_step if room.
- * Also set the number in the caller.
+ * locate the highest numbered rule before default
*/
for (f = chain->rules; f; f = f->next) {
if (f->rulenum == IPFW_DEFAULT_RULE)
/*
* Now insert the new rule in the right place in the sorted list.
- * XXX TODO also put in the skipto table.
*/
for (prev = NULL, f = chain->rules; f; prev = f, f = f->next) {
if (f->rulenum > rule->rulenum) { /* found the location */
prev->next = n;
V_static_count--;
V_static_len -= l;
- // XXX remove from the skipto table
rule->next = chain->reap;
chain->reap = rule;
IPFW_WUNLOCK(&V_layer3_chain);
if (reap != NULL)
reap_rules(reap);
- IPFW_DYN_LOCK_DESTROY();
uma_zdestroy(ipfw_dyn_rule_zone);
+ IPFW_DYN_LOCK_DESTROY();
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");
}
IPFW_LOCK_INIT(&V_layer3_chain);
callout_init(&V_ipfw_timeout, CALLOUT_MPSAFE);
- set_skipto_table(&V_layer3_chain);
-
bzero(&default_rule, sizeof default_rule);
default_rule.act_ofs = 0;
default_rule.rulenum = IPFW_DEFAULT_RULE;