* Use different rule structures in kernel/userland.
* Switch kernel to use per-cpu counters for rules. * Keep ABI/API. Kernel changes: * Each rules is now exported as TLV with optional extenable counter block (ip_fW_bcounter for base one) and ip_fw_rule for rule&cmd data. * Counters needs to be explicitly requested by IPFW_CFG_GET_COUNTERS flag. * Separate counters from rules in kernel and clean up ip_fw a bit. * Pack each rule in IPFW_TLV_RULE_ENT tlv to ease parsing. * Introduce versioning in container TLV (may be needed in future). * Fix ipfw_cfg_lheader broken u64 alignment. Userland changes: * Use set_mask from cfg header when requesting config * Fix incorrect read accouting in ipfw_show_config() * Use IPFW_RULE_NOOPT flag instead of playing with _pad * Fix "ipfw -d list": do not print counters for dynamic states * Some small fixes
This commit is contained in:
parent
7189aec01e
commit
3f7d90b385
@ -61,6 +61,7 @@ struct format_opts {
|
||||
int bcwidth;
|
||||
int pcwidth;
|
||||
int show_counters;
|
||||
uint32_t set_mask; /* enabled sets mask */
|
||||
uint32_t flags; /* request flags */
|
||||
uint32_t first; /* first rule to request */
|
||||
uint32_t last; /* last rule to request */
|
||||
@ -1298,7 +1299,7 @@ show_prerequisites(int *flags, int want, int cmd)
|
||||
|
||||
static void
|
||||
show_static_rule(struct cmdline_opts *co, struct format_opts *fo,
|
||||
struct buf_pr *bp, struct ip_fw *rule)
|
||||
struct buf_pr *bp, struct ip_fw_rule *rule, struct ip_fw_bcounter *cntr)
|
||||
{
|
||||
static int twidth = 0;
|
||||
int l;
|
||||
@ -1309,11 +1310,9 @@ show_static_rule(struct cmdline_opts *co, struct format_opts *fo,
|
||||
ipfw_insn_log *logptr = NULL; /* set if we find an O_LOG */
|
||||
ipfw_insn_altq *altqptr = NULL; /* set if we find an O_ALTQ */
|
||||
int or_block = 0; /* we are in an or block */
|
||||
uint32_t set_disable;
|
||||
|
||||
bcopy(&rule->next_rule, &set_disable, sizeof(set_disable));
|
||||
|
||||
if (set_disable & (1 << rule->set)) { /* disabled */
|
||||
if ((fo->set_mask & (1 << rule->set)) == 0) {
|
||||
/* disabled mask */
|
||||
if (!co->show_sets)
|
||||
return;
|
||||
else
|
||||
@ -1321,13 +1320,14 @@ show_static_rule(struct cmdline_opts *co, struct format_opts *fo,
|
||||
}
|
||||
bprintf(bp, "%05u ", rule->rulenum);
|
||||
|
||||
/* Print counters if enabled */
|
||||
if (fo->pcwidth > 0 || fo->bcwidth > 0) {
|
||||
pr_u64(bp, &rule->pcnt, fo->pcwidth);
|
||||
pr_u64(bp, &rule->bcnt, fo->bcwidth);
|
||||
pr_u64(bp, &cntr->pcnt, fo->pcwidth);
|
||||
pr_u64(bp, &cntr->bcnt, fo->bcwidth);
|
||||
}
|
||||
|
||||
if (co->do_time == 2)
|
||||
bprintf(bp, "%10u ", rule->timestamp);
|
||||
bprintf(bp, "%10u ", cntr->timestamp);
|
||||
else if (co->do_time == 1) {
|
||||
char timestr[30];
|
||||
time_t t = (time_t)0;
|
||||
@ -1337,8 +1337,8 @@ show_static_rule(struct cmdline_opts *co, struct format_opts *fo,
|
||||
*strchr(timestr, '\n') = '\0';
|
||||
twidth = strlen(timestr);
|
||||
}
|
||||
if (rule->timestamp) {
|
||||
t = _long_to_time(rule->timestamp);
|
||||
if (cntr->timestamp > 0) {
|
||||
t = _long_to_time(cntr->timestamp);
|
||||
|
||||
strcpy(timestr, ctime(&t));
|
||||
*strchr(timestr, '\n') = '\0';
|
||||
@ -1537,7 +1537,7 @@ show_static_rule(struct cmdline_opts *co, struct format_opts *fo,
|
||||
/*
|
||||
* then print the body.
|
||||
*/
|
||||
for (l = rule->act_ofs, cmd = rule->cmd ;
|
||||
for (l = rule->act_ofs, cmd = rule->cmd;
|
||||
l > 0 ; l -= F_LEN(cmd) , cmd += F_LEN(cmd)) {
|
||||
if ((cmd->len & F_OR) || (cmd->len & F_NOT))
|
||||
continue;
|
||||
@ -1549,7 +1549,7 @@ show_static_rule(struct cmdline_opts *co, struct format_opts *fo,
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (rule->_pad & 1) { /* empty rules before options */
|
||||
if (rule->flags & IPFW_RULE_NOOPT) { /* empty rules before options */
|
||||
if (!co->do_compact) {
|
||||
show_prerequisites(&flags, HAVE_PROTO, 0);
|
||||
printf(" from any to any");
|
||||
@ -1561,7 +1561,7 @@ show_static_rule(struct cmdline_opts *co, struct format_opts *fo,
|
||||
if (co->comment_only)
|
||||
comment = "...";
|
||||
|
||||
for (l = rule->act_ofs, cmd = rule->cmd ;
|
||||
for (l = rule->act_ofs, cmd = rule->cmd;
|
||||
l > 0 ; l -= F_LEN(cmd) , cmd += F_LEN(cmd)) {
|
||||
/* useful alias */
|
||||
ipfw_insn_u32 *cmd32 = (ipfw_insn_u32 *)cmd;
|
||||
@ -2177,6 +2177,9 @@ prepare_format_dyn(struct cmdline_opts *co, struct format_opts *fo,
|
||||
/* Count _ALL_ states */
|
||||
fo->dcnt++;
|
||||
|
||||
if (fo->show_counters == 0)
|
||||
return;
|
||||
|
||||
if (co->use_set) {
|
||||
/* skip states from another set */
|
||||
bcopy((char *)&d->rule + sizeof(uint16_t), &set,
|
||||
@ -2237,27 +2240,31 @@ foreach_state(struct cmdline_opts *co, struct format_opts *fo,
|
||||
|
||||
static void
|
||||
prepare_format_opts(struct cmdline_opts *co, struct format_opts *fo,
|
||||
struct ip_fw *r, int rcnt, caddr_t base, size_t sz)
|
||||
ipfw_obj_tlv *rtlv, int rcnt, caddr_t dynbase, size_t dynsz)
|
||||
{
|
||||
int bcwidth, pcwidth, width;
|
||||
int n;
|
||||
#define NEXT(r) ((struct ip_fw *)((char *)r + RULESIZE(r)))
|
||||
struct ip_fw_bcounter *cntr;
|
||||
struct ip_fw_rule *r;
|
||||
|
||||
bcwidth = 0;
|
||||
pcwidth = 0;
|
||||
if (fo->show_counters != 0) {
|
||||
for (n = 0; n < rcnt; n++, r = NEXT(r)) {
|
||||
for (n = 0; n < rcnt; n++,
|
||||
rtlv = (ipfw_obj_tlv *)((caddr_t)rtlv + rtlv->length)) {
|
||||
cntr = (struct ip_fw_bcounter *)(rtlv + 1);
|
||||
r = (struct ip_fw_rule *)((caddr_t)cntr + cntr->size);
|
||||
/* skip rules from another set */
|
||||
if (co->use_set && r->set != co->use_set - 1)
|
||||
continue;
|
||||
|
||||
/* packet counter */
|
||||
width = pr_u64(NULL, &r->pcnt, 0);
|
||||
width = pr_u64(NULL, &cntr->pcnt, 0);
|
||||
if (width > pcwidth)
|
||||
pcwidth = width;
|
||||
|
||||
/* byte counter */
|
||||
width = pr_u64(NULL, &r->bcnt, 0);
|
||||
width = pr_u64(NULL, &cntr->bcnt, 0);
|
||||
if (width > bcwidth)
|
||||
bcwidth = width;
|
||||
}
|
||||
@ -2266,23 +2273,36 @@ prepare_format_opts(struct cmdline_opts *co, struct format_opts *fo,
|
||||
fo->pcwidth = pcwidth;
|
||||
|
||||
fo->dcnt = 0;
|
||||
if (co->do_dynamic && sz > 0)
|
||||
sz = foreach_state(co, fo, base, sz, prepare_format_dyn, NULL);
|
||||
if (co->do_dynamic && dynsz > 0)
|
||||
foreach_state(co, fo, dynbase, dynsz, prepare_format_dyn, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
list_static_range(struct cmdline_opts *co, struct format_opts *fo,
|
||||
struct buf_pr *bp, struct ip_fw *r, int rcnt)
|
||||
struct buf_pr *bp, ipfw_obj_tlv *rtlv, int rcnt)
|
||||
{
|
||||
int n, seen;
|
||||
struct ip_fw_rule *r;
|
||||
struct ip_fw_bcounter *cntr;
|
||||
int c = 0;
|
||||
|
||||
for (n = seen = 0; n < rcnt; n++, r = NEXT(r) ) {
|
||||
for (n = seen = 0; n < rcnt; n++,
|
||||
rtlv = (ipfw_obj_tlv *)((caddr_t)rtlv + rtlv->length)) {
|
||||
|
||||
if (fo->show_counters != 0) {
|
||||
cntr = (struct ip_fw_bcounter *)(rtlv + 1);
|
||||
r = (struct ip_fw_rule *)((caddr_t)cntr + cntr->size);
|
||||
} else {
|
||||
cntr = NULL;
|
||||
r = (struct ip_fw_rule *)(rtlv + 1);
|
||||
}
|
||||
if (r->rulenum > fo->last)
|
||||
break;
|
||||
if (co->use_set && r->set != co->use_set - 1)
|
||||
continue;
|
||||
if (r->rulenum >= fo->first && r->rulenum <= fo->last) {
|
||||
show_static_rule(co, fo, bp, r);
|
||||
show_static_rule(co, fo, bp, r, cntr);
|
||||
c += rtlv->length;
|
||||
bp_flush(bp);
|
||||
seen++;
|
||||
}
|
||||
@ -2369,27 +2389,27 @@ ipfw_list(int ac, char *av[], int show_counters)
|
||||
|
||||
/* get configuraion from kernel */
|
||||
cfg = NULL;
|
||||
sfo.show_counters = show_counters;
|
||||
sfo.flags = IPFW_CFG_GET_STATIC;
|
||||
if (co.do_dynamic != 0)
|
||||
sfo.flags |= IPFW_CFG_GET_STATES;
|
||||
if (sfo.show_counters != 0)
|
||||
sfo.flags |= IPFW_CFG_GET_COUNTERS;
|
||||
if ((error = ipfw_get_config(&co, &sfo, &cfg, &sz)) != 0)
|
||||
err(EX_OSERR, "retrieving config failed");
|
||||
|
||||
sfo.show_counters = show_counters;
|
||||
error = ipfw_show_config(&co, &sfo, cfg, sz, ac, av);
|
||||
|
||||
free(cfg);
|
||||
|
||||
if (error != EX_OK)
|
||||
exit(error);
|
||||
#undef NEXT
|
||||
}
|
||||
|
||||
static int
|
||||
ipfw_show_config(struct cmdline_opts *co, struct format_opts *fo,
|
||||
ipfw_cfg_lheader *cfg, size_t sz, int ac, char *av[])
|
||||
{
|
||||
struct ip_fw *rbase;
|
||||
caddr_t dynbase;
|
||||
size_t dynsz;
|
||||
int rcnt;
|
||||
@ -2400,6 +2420,7 @@ ipfw_show_config(struct cmdline_opts *co, struct format_opts *fo,
|
||||
size_t read;
|
||||
struct buf_pr bp;
|
||||
ipfw_obj_ctlv *ctlv, *tstate;
|
||||
ipfw_obj_tlv *rbase;
|
||||
|
||||
/*
|
||||
* Handle tablenames TLV first, if any
|
||||
@ -2408,7 +2429,9 @@ ipfw_show_config(struct cmdline_opts *co, struct format_opts *fo,
|
||||
rbase = NULL;
|
||||
dynbase = NULL;
|
||||
dynsz = 0;
|
||||
read = 0;
|
||||
read = sizeof(*cfg);
|
||||
|
||||
fo->set_mask = cfg->set_mask;
|
||||
|
||||
ctlv = (ipfw_obj_ctlv *)(cfg + 1);
|
||||
|
||||
@ -2422,7 +2445,7 @@ ipfw_show_config(struct cmdline_opts *co, struct format_opts *fo,
|
||||
}
|
||||
|
||||
if (ctlv->head.type == IPFW_TLV_RULE_LIST) {
|
||||
rbase = (struct ip_fw *)(ctlv + 1);
|
||||
rbase = (ipfw_obj_tlv *)(ctlv + 1);
|
||||
rcnt = ctlv->count;
|
||||
read += ctlv->head.length;
|
||||
ctlv = (ipfw_obj_ctlv *)((caddr_t)ctlv +
|
||||
@ -2432,8 +2455,12 @@ ipfw_show_config(struct cmdline_opts *co, struct format_opts *fo,
|
||||
|
||||
if ((cfg->flags & IPFW_CFG_GET_STATES) && (read != sz)) {
|
||||
/* We may have some dynamic states */
|
||||
dynbase = (caddr_t)ctlv;
|
||||
dynsz = sz - read;
|
||||
/* Skip empty header */
|
||||
if (dynsz != sizeof(ipfw_obj_ctlv))
|
||||
dynbase = (caddr_t)ctlv;
|
||||
else
|
||||
dynsz = 0;
|
||||
}
|
||||
|
||||
prepare_format_opts(co, fo, rbase, rcnt, dynbase, dynsz);
|
||||
@ -2446,7 +2473,7 @@ ipfw_show_config(struct cmdline_opts *co, struct format_opts *fo,
|
||||
list_static_range(co, fo, &bp, rbase, rcnt);
|
||||
|
||||
if (co->do_dynamic && dynsz > 0) {
|
||||
printf("## Dynamic rules (%d):\n", fo->dcnt);
|
||||
printf("## Dynamic rules (%d %lu):\n", fo->dcnt, dynsz);
|
||||
list_dyn_range(co, fo, &bp, dynbase, dynsz);
|
||||
}
|
||||
|
||||
@ -3304,7 +3331,7 @@ compile_rule(char *av[], uint32_t *rbuf, int *rbufsize, struct tidx *tstate)
|
||||
ipfw_insn *src, *dst, *cmd, *action, *prev=NULL;
|
||||
ipfw_insn *first_cmd; /* first match pattern */
|
||||
|
||||
struct ip_fw *rule;
|
||||
struct ip_fw_rule *rule;
|
||||
|
||||
/*
|
||||
* various flags used to record that we entered some fields.
|
||||
@ -3326,12 +3353,12 @@ compile_rule(char *av[], uint32_t *rbuf, int *rbufsize, struct tidx *tstate)
|
||||
bzero(cmdbuf, sizeof(cmdbuf));
|
||||
bzero(rbuf, *rbufsize);
|
||||
|
||||
rule = (struct ip_fw *)rbuf;
|
||||
rule = (struct ip_fw_rule *)rbuf;
|
||||
cmd = (ipfw_insn *)cmdbuf;
|
||||
action = (ipfw_insn *)actbuf;
|
||||
|
||||
rblen = *rbufsize / sizeof(uint32_t);
|
||||
rblen -= offsetof(struct ip_fw, cmd) / sizeof(uint32_t);
|
||||
rblen -= sizeof(struct ip_fw_rule) / sizeof(uint32_t);
|
||||
ablen = sizeof(actbuf) / sizeof(actbuf[0]);
|
||||
cblen = sizeof(cmdbuf) / sizeof(cmdbuf[0]);
|
||||
cblen -= F_INSN_SIZE(ipfw_insn_u32) + 1;
|
||||
@ -3884,7 +3911,7 @@ compile_rule(char *av[], uint32_t *rbuf, int *rbufsize, struct tidx *tstate)
|
||||
* nothing specified so far, store in the rule to ease
|
||||
* printout later.
|
||||
*/
|
||||
rule->_pad = 1;
|
||||
rule->flags |= IPFW_RULE_NOOPT;
|
||||
}
|
||||
prev = NULL;
|
||||
while ( av[0] != NULL ) {
|
||||
@ -4467,13 +4494,13 @@ compile_rule(char *av[], uint32_t *rbuf, int *rbufsize, struct tidx *tstate)
|
||||
* [
|
||||
* ip_fw3_opheader
|
||||
* [ ipfw_obj_ctlv(IPFW_TLV_TBL_LIST) ipfw_obj_ntlv x N ] (optional *1)
|
||||
* [ ipfw_obj_ctlv(IPFW_TLV_RULE_LIST) ip_fw x N ] (*2) (*3)
|
||||
* [ ipfw_obj_ctlv(IPFW_TLV_RULE_LIST) [ ip_fw_rule ip_fw_insn ] x N ] (*2) (*3)
|
||||
* ]
|
||||
* Reply:
|
||||
* [
|
||||
* ip_fw3_opheader
|
||||
* [ ipfw_obj_ctlv(IPFW_TLV_TBL_LIST) ipfw_obj_ntlv x N ] (optional)
|
||||
* [ ipfw_obj_ctlv(IPFW_TLV_RULE_LIST) ip_fw x N ]
|
||||
* [ ipfw_obj_ctlv(IPFW_TLV_RULE_LIST) [ ip_fw_rule ip_fw_insn ] x N ]
|
||||
* ]
|
||||
*
|
||||
* Rules in reply are modified to store their actual ruleset number.
|
||||
@ -4490,7 +4517,7 @@ ipfw_add(char *av[])
|
||||
int rbufsize, default_off, tlen, rlen;
|
||||
size_t sz;
|
||||
struct tidx ts;
|
||||
struct ip_fw *rule;
|
||||
struct ip_fw_rule *rule;
|
||||
caddr_t tbuf;
|
||||
ip_fw3_opheader *op3;
|
||||
ipfw_obj_ctlv *ctlv, *tstate;
|
||||
@ -4502,7 +4529,7 @@ ipfw_add(char *av[])
|
||||
default_off = sizeof(ipfw_obj_ctlv) + sizeof(ip_fw3_opheader);
|
||||
op3 = (ip_fw3_opheader *)rulebuf;
|
||||
ctlv = (ipfw_obj_ctlv *)(op3 + 1);
|
||||
rule = (struct ip_fw *)(ctlv + 1);
|
||||
rule = (struct ip_fw_rule *)(ctlv + 1);
|
||||
rbufsize -= default_off;
|
||||
|
||||
compile_rule(av, (uint32_t *)rule, &rbufsize, &ts);
|
||||
@ -4552,8 +4579,9 @@ ipfw_add(char *av[])
|
||||
struct buf_pr bp;
|
||||
memset(&sfo, 0, sizeof(sfo));
|
||||
sfo.tstate = tstate;
|
||||
sfo.set_mask = (uint32_t)(-1);
|
||||
bp_alloc(&bp, 4096);
|
||||
show_static_rule(&co, &sfo, &bp, rule);
|
||||
show_static_rule(&co, &sfo, &bp, rule, NULL);
|
||||
bp_free(&bp);
|
||||
}
|
||||
|
||||
|
@ -36,10 +36,8 @@
|
||||
*/
|
||||
#define IPFW_DEFAULT_RULE 65535
|
||||
|
||||
/*
|
||||
* Number of sets supported by ipfw
|
||||
*/
|
||||
#define IPFW_MAX_SETS 32
|
||||
#define RESVD_SET 31 /*set for default and persistent rules*/
|
||||
#define IPFW_MAX_SETS 32 /* Number of sets supported by ipfw*/
|
||||
|
||||
/*
|
||||
* Default number of ipfw tables.
|
||||
@ -513,15 +511,17 @@ typedef struct _ipfw_insn_icmp6 {
|
||||
/*
|
||||
* Here we have the structure representing an ipfw rule.
|
||||
*
|
||||
* It starts with a general area (with link fields and counters)
|
||||
* Layout:
|
||||
* struct ip_fw_rule
|
||||
* [ counter block, size = rule->cntr_len ]
|
||||
* [ one or more instructions, size = rule->cmd_len * 4 ]
|
||||
*
|
||||
* It starts with a general area (with link fields).
|
||||
* Counter block may be next (if rule->cntr_len > 0),
|
||||
* followed by an array of one or more instructions, which the code
|
||||
* accesses as an array of 32-bit values.
|
||||
*
|
||||
* Given a rule pointer r:
|
||||
*
|
||||
* r->cmd is the start of the first instruction.
|
||||
* ACTION_PTR(r) is the start of the first action (things to do
|
||||
* once a rule matched).
|
||||
* accesses as an array of 32-bit values. rule->cmd_len represents
|
||||
* the total instructions legth in u32 worrd, while act_ofs represents
|
||||
* rule action offset in u32 words.
|
||||
*
|
||||
* When assembling instruction, remember the following:
|
||||
*
|
||||
@ -532,11 +532,41 @@ typedef struct _ipfw_insn_icmp6 {
|
||||
* + if a rule has an "altq" option, it comes after "log"
|
||||
* + if a rule has an O_TAG option, it comes after "log" and "altq"
|
||||
*
|
||||
* NOTE: we use a simple linked list of rules because we never need
|
||||
* to delete a rule without scanning the list. We do not use
|
||||
* queue(3) macros for portability and readability.
|
||||
*
|
||||
* All structures (excluding instructions) are u64-aligned.
|
||||
* Please keep this.
|
||||
*/
|
||||
|
||||
struct ip_fw_rule {
|
||||
uint16_t act_ofs; /* offset of action in 32-bit units */
|
||||
uint16_t cmd_len; /* # of 32-bit words in cmd */
|
||||
uint16_t spare;
|
||||
uint8_t set; /* rule set (0..31) */
|
||||
uint8_t flags; /* rule flags */
|
||||
uint32_t rulenum; /* rule number */
|
||||
uint32_t id; /* rule id */
|
||||
|
||||
ipfw_insn cmd[1]; /* storage for commands */
|
||||
};
|
||||
#define IPFW_RULE_NOOPT 0x01 /* Has no options in body */
|
||||
|
||||
/* Unaligned version */
|
||||
|
||||
/* Base ipfw rule counter block. */
|
||||
struct ip_fw_bcounter {
|
||||
uint16_t size; /* Size of counter block, bytes */
|
||||
uint8_t flags; /* flags for given block */
|
||||
uint8_t spare;
|
||||
uint32_t timestamp; /* tv_sec of last match */
|
||||
uint64_t pcnt; /* Packet counter */
|
||||
uint64_t bcnt; /* Byte counter */
|
||||
};
|
||||
|
||||
|
||||
#ifndef _KERNEL
|
||||
/*
|
||||
* Legacy rule format
|
||||
*/
|
||||
struct ip_fw {
|
||||
struct ip_fw *x_next; /* linked list of rules */
|
||||
struct ip_fw *next_rule; /* ptr to next [skipto] rule */
|
||||
@ -546,7 +576,6 @@ struct ip_fw {
|
||||
uint16_t cmd_len; /* # of 32-bit words in cmd */
|
||||
uint16_t rulenum; /* rule number */
|
||||
uint8_t set; /* rule set (0..31) */
|
||||
#define RESVD_SET 31 /* set for default and persistent rules */
|
||||
uint8_t _pad; /* padding */
|
||||
uint32_t id; /* rule id */
|
||||
|
||||
@ -557,12 +586,13 @@ struct ip_fw {
|
||||
|
||||
ipfw_insn cmd[1]; /* storage for commands */
|
||||
};
|
||||
#endif
|
||||
|
||||
#define ACTION_PTR(rule) \
|
||||
(ipfw_insn *)( (u_int32_t *)((rule)->cmd) + ((rule)->act_ofs) )
|
||||
|
||||
#define RULESIZE(rule) (sizeof(struct ip_fw) + \
|
||||
((struct ip_fw *)(rule))->cmd_len * 4 - 4)
|
||||
#define RULESIZE(rule) (sizeof(*(rule)) + (rule)->cmd_len * 4 - 4)
|
||||
|
||||
|
||||
#if 1 // should be moved to in.h
|
||||
/*
|
||||
@ -698,6 +728,7 @@ typedef struct _ipfw_obj_tlv {
|
||||
#define IPFW_TLV_DYNSTATE_LIST 4
|
||||
#define IPFW_TLV_TBL_ENT 5
|
||||
#define IPFW_TLV_DYN_ENT 6
|
||||
#define IPFW_TLV_RULE_ENT 7
|
||||
|
||||
/* Object name TLV */
|
||||
typedef struct _ipfw_obj_ntlv {
|
||||
@ -737,7 +768,9 @@ typedef struct _ipfw_obj_dyntlv {
|
||||
typedef struct _ipfw_obj_ctlv {
|
||||
ipfw_obj_tlv head; /* TLV header */
|
||||
uint32_t count; /* Number of sub-TLVs */
|
||||
uint32_t objsize; /* Single object size */
|
||||
uint16_t objsize; /* Single object size */
|
||||
uint8_t version; /* TLV version */
|
||||
uint8_t spare;
|
||||
} ipfw_obj_ctlv;
|
||||
|
||||
typedef struct _ipfw_xtable_info {
|
||||
@ -772,11 +805,13 @@ typedef struct _ipfw_obj_lheader {
|
||||
uint32_t objsize; /* Size of one object */
|
||||
} ipfw_obj_lheader;
|
||||
|
||||
#define IPFW_CFG_GET_STATIC 1
|
||||
#define IPFW_CFG_GET_STATES 2
|
||||
#define IPFW_CFG_GET_STATIC 0x01
|
||||
#define IPFW_CFG_GET_STATES 0x02
|
||||
#define IPFW_CFG_GET_COUNTERS 0x04
|
||||
typedef struct _ipfw_cfg_lheader {
|
||||
ip_fw3_opheader opheader; /* IP_FW3 opcode */
|
||||
uint32_t set_mask; /* enabled set mask */
|
||||
uint32_t spare;
|
||||
uint32_t flags; /* Request flags */
|
||||
uint32_t size; /* neded buffer size */
|
||||
uint32_t start_rule;
|
||||
|
@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/condvar.h>
|
||||
#include <sys/counter.h>
|
||||
#include <sys/eventhandler.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mbuf.h>
|
||||
@ -2647,12 +2648,11 @@ vnet_ipfw_init(const void *unused)
|
||||
LIST_INIT(&chain->nat);
|
||||
#endif
|
||||
|
||||
ipfw_init_counters();
|
||||
/* 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);
|
||||
rule = ipfw_alloc_rule(chain, sizeof(struct ip_fw));
|
||||
|
||||
/* Set initial number of tables */
|
||||
V_fw_tables_max = default_fw_tables;
|
||||
@ -2673,6 +2673,8 @@ vnet_ipfw_init(const void *unused)
|
||||
rule->cmd[0].opcode = default_to_accept ? O_ACCEPT : O_DENY;
|
||||
chain->default_rule = chain->map[0] = rule;
|
||||
chain->id = rule->id = 1;
|
||||
/* Pre-calculate rules length for legacy dump format */
|
||||
chain->static_len = sizeof(struct ip_fw_rule0);
|
||||
|
||||
IPFW_LOCK_INIT(chain);
|
||||
ipfw_dyn_init(chain);
|
||||
@ -2740,7 +2742,8 @@ vnet_ipfw_uninit(const void *unused)
|
||||
ipfw_reap_rules(reap);
|
||||
IPFW_LOCK_DESTROY(chain);
|
||||
ipfw_dyn_uninit(1); /* free the remaining parts */
|
||||
return 0;
|
||||
ipfw_destroy_counters();
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -220,6 +220,44 @@ VNET_DECLARE(unsigned int, fw_tables_sets);
|
||||
|
||||
struct tables_config;
|
||||
|
||||
#ifdef _KERNEL
|
||||
typedef struct ip_fw_cntr {
|
||||
uint64_t pcnt; /* Packet counter */
|
||||
uint64_t bcnt; /* Byte counter */
|
||||
uint64_t timestamp; /* tv_sec of last match */
|
||||
} ip_fw_cntr;
|
||||
|
||||
/*
|
||||
* Here we have the structure representing an ipfw rule.
|
||||
*
|
||||
* It starts with a general area
|
||||
* followed by an array of one or more instructions, which the code
|
||||
* accesses as an array of 32-bit values.
|
||||
*
|
||||
* Given a rule pointer r:
|
||||
*
|
||||
* r->cmd is the start of the first instruction.
|
||||
* ACTION_PTR(r) is the start of the first action (things to do
|
||||
* once a rule matched).
|
||||
*/
|
||||
|
||||
struct ip_fw {
|
||||
uint16_t act_ofs; /* offset of action in 32-bit units */
|
||||
uint16_t cmd_len; /* # of 32-bit words in cmd */
|
||||
uint16_t rulenum; /* rule number */
|
||||
uint8_t set; /* rule set (0..31) */
|
||||
uint8_t flags; /* currently unused */
|
||||
counter_u64_t cntr; /* Pointer to rule counters */
|
||||
uint32_t timestamp; /* tv_sec of last match */
|
||||
uint32_t id; /* rule id */
|
||||
struct ip_fw *x_next; /* linked list of rules */
|
||||
struct ip_fw *next_rule; /* ptr to next [skipto] rule */
|
||||
|
||||
ipfw_insn cmd[1]; /* storage for commands */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
struct ip_fw_chain {
|
||||
struct ip_fw **map; /* array of rule ptrs to ease lookup */
|
||||
uint32_t id; /* ruleset id */
|
||||
@ -231,7 +269,7 @@ struct ip_fw_chain {
|
||||
#else
|
||||
struct rwlock rwmtx;
|
||||
#endif
|
||||
int static_len; /* total len of static rules */
|
||||
int static_len; /* total len of static rules (v0) */
|
||||
uint32_t gencnt; /* NAT generation count */
|
||||
struct ip_fw *reap; /* list of rules to reap */
|
||||
struct ip_fw *default_rule;
|
||||
@ -255,6 +293,7 @@ struct sockopt_data {
|
||||
};
|
||||
|
||||
/* Macro for working with various counters */
|
||||
#ifdef USERSPACE
|
||||
#define IPFW_INC_RULE_COUNTER(_cntr, _bytes) do { \
|
||||
(_cntr)->pcnt++; \
|
||||
(_cntr)->bcnt += _bytes; \
|
||||
@ -276,6 +315,31 @@ struct sockopt_data {
|
||||
(_cntr)->pcnt = 0; \
|
||||
(_cntr)->bcnt = 0; \
|
||||
} while (0)
|
||||
#else
|
||||
#define IPFW_INC_RULE_COUNTER(_cntr, _bytes) do { \
|
||||
counter_u64_add((_cntr)->cntr, 1); \
|
||||
counter_u64_add((_cntr)->cntr + 1, _bytes); \
|
||||
if ((_cntr)->timestamp != time_uptime) \
|
||||
(_cntr)->timestamp = time_uptime; \
|
||||
} while (0)
|
||||
|
||||
#define IPFW_INC_DYN_COUNTER(_cntr, _bytes) do { \
|
||||
(_cntr)->pcnt++; \
|
||||
(_cntr)->bcnt += _bytes; \
|
||||
} while (0)
|
||||
|
||||
#define IPFW_ZERO_RULE_COUNTER(_cntr) do { \
|
||||
counter_u64_zero((_cntr)->cntr); \
|
||||
counter_u64_zero((_cntr)->cntr + 1); \
|
||||
(_cntr)->timestamp = 0; \
|
||||
} while (0)
|
||||
|
||||
#define IPFW_ZERO_DYN_COUNTER(_cntr) do { \
|
||||
(_cntr)->pcnt = 0; \
|
||||
(_cntr)->bcnt = 0; \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
|
||||
#define IP_FW_ARG_TABLEARG(a) (((a) == IP_FW_TABLEARG) ? tablearg : (a))
|
||||
/*
|
||||
@ -322,17 +386,70 @@ struct obj_idx {
|
||||
struct rule_check_info {
|
||||
uint16_t table_opcodes; /* count of opcodes referencing table */
|
||||
uint16_t new_tables; /* count of opcodes referencing table */
|
||||
uint16_t urule_numoff; /* offset of rulenum in bytes */
|
||||
uint8_t version; /* rule version */
|
||||
ipfw_obj_ctlv *ctlv; /* name TLV containter */
|
||||
struct ip_fw *krule; /* resulting rule pointer */
|
||||
struct ip_fw *urule; /* original rule pointer */
|
||||
caddr_t urule; /* original rule pointer */
|
||||
struct obj_idx obuf[8]; /* table references storage */
|
||||
};
|
||||
|
||||
/* Legacy interface support */
|
||||
/*
|
||||
* FreeBSD 8 export rule format
|
||||
*/
|
||||
struct ip_fw_rule0 {
|
||||
struct ip_fw *x_next; /* linked list of rules */
|
||||
struct ip_fw *next_rule; /* ptr to next [skipto] rule */
|
||||
/* 'next_rule' is used to pass up 'set_disable' status */
|
||||
|
||||
uint16_t act_ofs; /* offset of action in 32-bit units */
|
||||
uint16_t cmd_len; /* # of 32-bit words in cmd */
|
||||
uint16_t rulenum; /* rule number */
|
||||
uint8_t set; /* rule set (0..31) */
|
||||
uint8_t _pad; /* padding */
|
||||
uint32_t id; /* rule id */
|
||||
|
||||
/* These fields are present in all rules. */
|
||||
uint64_t pcnt; /* Packet counter */
|
||||
uint64_t bcnt; /* Byte counter */
|
||||
uint32_t timestamp; /* tv_sec of last match */
|
||||
|
||||
ipfw_insn cmd[1]; /* storage for commands */
|
||||
};
|
||||
|
||||
struct ip_fw_bcounter0 {
|
||||
uint64_t pcnt; /* Packet counter */
|
||||
uint64_t bcnt; /* Byte counter */
|
||||
uint32_t timestamp; /* tv_sec of last match */
|
||||
};
|
||||
|
||||
/* Kernel rule length */
|
||||
/*
|
||||
* RULE _K_ SIZE _V_ ->
|
||||
* get kernel size from userland rool version _V_.
|
||||
* RULE _U_ SIZE _V_ ->
|
||||
* get user size version _V_ from kernel rule
|
||||
* RULESIZE _V_ ->
|
||||
* get user size rule length
|
||||
*/
|
||||
/* FreeBSD8 <> current kernel format */
|
||||
#define RULEUSIZE0(r) (sizeof(struct ip_fw_rule0) + (r)->cmd_len * 4 - 4)
|
||||
#define RULEKSIZE0(r) roundup2((sizeof(struct ip_fw) + (r)->cmd_len*4 - 4), 8)
|
||||
/* FreeBSD11 <> current kernel format */
|
||||
#define RULEUSIZE1(r) (roundup2(sizeof(struct ip_fw_rule) + \
|
||||
(r)->cmd_len * 4 - 4, 8))
|
||||
#define RULEKSIZE1(r) roundup2((sizeof(struct ip_fw) + (r)->cmd_len*4 - 4), 8)
|
||||
|
||||
|
||||
/* In ip_fw_sockopt.c */
|
||||
int ipfw_find_rule(struct ip_fw_chain *chain, uint32_t key, uint32_t id);
|
||||
int ipfw_ctl(struct sockopt *sopt);
|
||||
int ipfw_chk(struct ip_fw_args *args);
|
||||
void ipfw_reap_rules(struct ip_fw *head);
|
||||
void ipfw_init_counters(void);
|
||||
void ipfw_destroy_counters(void);
|
||||
struct ip_fw *ipfw_alloc_rule(struct ip_fw_chain *chain, size_t rulesize);
|
||||
|
||||
caddr_t ipfw_get_sopt_space(struct sockopt_data *sd, size_t needed);
|
||||
caddr_t ipfw_get_sopt_header(struct sockopt_data *sd, size_t needed);
|
||||
|
@ -69,6 +69,13 @@ __FBSDID("$FreeBSD$");
|
||||
#include <security/mac/mac_framework.h>
|
||||
#endif
|
||||
|
||||
static int check_ipfw_rule_body(ipfw_insn *cmd, int cmd_len,
|
||||
struct rule_check_info *ci);
|
||||
static int check_ipfw_rule1(struct ip_fw_rule *rule, int size,
|
||||
struct rule_check_info *ci);
|
||||
static int check_ipfw_rule0(struct ip_fw_rule0 *rule, int size,
|
||||
struct rule_check_info *ci);
|
||||
|
||||
#define NAMEDOBJ_HASH_SIZE 32
|
||||
|
||||
struct namedobj_instance {
|
||||
@ -92,9 +99,79 @@ static int ipfw_flush_sopt_data(struct sockopt_data *sd);
|
||||
MALLOC_DEFINE(M_IPFW, "IpFw/IpAcct", "IpFw/IpAcct chain's");
|
||||
|
||||
/*
|
||||
* static variables followed by global ones (none in this file)
|
||||
* static variables followed by global ones
|
||||
*/
|
||||
|
||||
#ifndef USERSPACE
|
||||
|
||||
static VNET_DEFINE(uma_zone_t, ipfw_cntr_zone);
|
||||
#define V_ipfw_cntr_zone VNET(ipfw_cntr_zone)
|
||||
|
||||
void
|
||||
ipfw_init_counters()
|
||||
{
|
||||
|
||||
V_ipfw_cntr_zone = uma_zcreate("IPFW counters",
|
||||
sizeof(ip_fw_cntr), NULL, NULL, NULL, NULL,
|
||||
UMA_ALIGN_PTR, UMA_ZONE_PCPU);
|
||||
}
|
||||
|
||||
void
|
||||
ipfw_destroy_counters()
|
||||
{
|
||||
|
||||
uma_zdestroy(V_ipfw_cntr_zone);
|
||||
}
|
||||
|
||||
struct ip_fw *
|
||||
ipfw_alloc_rule(struct ip_fw_chain *chain, size_t rulesize)
|
||||
{
|
||||
struct ip_fw *rule;
|
||||
|
||||
rule = malloc(rulesize, M_IPFW, M_WAITOK | M_ZERO);
|
||||
rule->cntr = uma_zalloc(V_ipfw_cntr_zone, M_WAITOK | M_ZERO);
|
||||
|
||||
return (rule);
|
||||
}
|
||||
|
||||
static void
|
||||
free_rule(struct ip_fw *rule)
|
||||
{
|
||||
|
||||
uma_zfree(V_ipfw_cntr_zone, rule->cntr);
|
||||
free(rule, M_IPFW);
|
||||
}
|
||||
#else
|
||||
void
|
||||
ipfw_init_counters()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ipfw_destroy_counters()
|
||||
{
|
||||
}
|
||||
|
||||
struct ip_fw *
|
||||
ipfw_alloc_rule(struct ip_fw_chain *chain, size_t rulesize)
|
||||
{
|
||||
struct ip_fw *rule;
|
||||
|
||||
rule = malloc(rulesize, M_IPFW, M_WAITOK | M_ZERO);
|
||||
|
||||
return (rule);
|
||||
}
|
||||
|
||||
static void
|
||||
free_rule(struct ip_fw *rule)
|
||||
{
|
||||
|
||||
free(rule, M_IPFW);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Find the smallest rule >= key, id.
|
||||
* We could use bsearch but it is so simple that we code it directly
|
||||
@ -167,20 +244,151 @@ swap_map(struct ip_fw_chain *chain, struct ip_fw **new_map, int new_len)
|
||||
return old_map;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
export_cntr1_base(struct ip_fw *krule, struct ip_fw_bcounter *cntr)
|
||||
{
|
||||
|
||||
cntr->size = sizeof(*cntr);
|
||||
|
||||
if (krule->cntr != NULL) {
|
||||
cntr->pcnt = counter_u64_fetch(krule->cntr);
|
||||
cntr->bcnt = counter_u64_fetch(krule->cntr + 1);
|
||||
cntr->timestamp = krule->timestamp;
|
||||
}
|
||||
if (cntr->timestamp > 0)
|
||||
cntr->timestamp += boottime.tv_sec;
|
||||
}
|
||||
|
||||
static void
|
||||
export_cntr0_base(struct ip_fw *krule, struct ip_fw_bcounter0 *cntr)
|
||||
{
|
||||
|
||||
if (krule->cntr != NULL) {
|
||||
cntr->pcnt = counter_u64_fetch(krule->cntr);
|
||||
cntr->bcnt = counter_u64_fetch(krule->cntr + 1);
|
||||
cntr->timestamp = krule->timestamp;
|
||||
}
|
||||
if (cntr->timestamp > 0)
|
||||
cntr->timestamp += boottime.tv_sec;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copies rule @urule from userland format to kernel @krule.
|
||||
* Copies rule @urule from v1 userland format
|
||||
* to kernel @krule.
|
||||
* Assume @krule is zeroed.
|
||||
*/
|
||||
static void
|
||||
copy_rule(struct ip_fw *urule, struct ip_fw *krule)
|
||||
import_rule1(struct rule_check_info *ci)
|
||||
{
|
||||
int l;
|
||||
struct ip_fw_rule *urule;
|
||||
struct ip_fw *krule;
|
||||
|
||||
l = RULESIZE(urule);
|
||||
bcopy(urule, krule, l);
|
||||
/* clear fields not settable from userland */
|
||||
krule->x_next = NULL;
|
||||
krule->next_rule = NULL;
|
||||
IPFW_ZERO_RULE_COUNTER(krule);
|
||||
urule = (struct ip_fw_rule *)ci->urule;
|
||||
krule = (struct ip_fw *)ci->krule;
|
||||
|
||||
/* copy header */
|
||||
krule->act_ofs = urule->act_ofs;
|
||||
krule->cmd_len = urule->cmd_len;
|
||||
krule->rulenum = urule->rulenum;
|
||||
krule->set = urule->set;
|
||||
krule->flags = urule->flags;
|
||||
|
||||
/* Save rulenum offset */
|
||||
ci->urule_numoff = offsetof(struct ip_fw_rule, rulenum);
|
||||
|
||||
/* Copy opcodes */
|
||||
memcpy(krule->cmd, urule->cmd, krule->cmd_len * sizeof(uint32_t));
|
||||
}
|
||||
|
||||
/*
|
||||
* Export rule into v1 format (Current).
|
||||
* Layout:
|
||||
* [ ipfw_obj_tlv(IPFW_TLV_RULE_ENT)
|
||||
* [ ip_fw_rule ] OR
|
||||
* [ ip_fw_bcounter ip_fw_rule] (depends on rcntrs).
|
||||
* ]
|
||||
* Assume @data is zeroed.
|
||||
*/
|
||||
static void
|
||||
export_rule1(struct ip_fw *krule, caddr_t data, int len, int rcntrs)
|
||||
{
|
||||
struct ip_fw_bcounter *cntr;
|
||||
struct ip_fw_rule *urule;
|
||||
ipfw_obj_tlv *tlv;
|
||||
|
||||
/* Fill in TLV header */
|
||||
tlv = (ipfw_obj_tlv *)data;
|
||||
tlv->type = IPFW_TLV_RULE_ENT;
|
||||
tlv->length = len;
|
||||
|
||||
if (rcntrs != 0) {
|
||||
/* Copy counters */
|
||||
cntr = (struct ip_fw_bcounter *)(tlv + 1);
|
||||
urule = (struct ip_fw_rule *)(cntr + 1);
|
||||
export_cntr1_base(krule, cntr);
|
||||
} else
|
||||
urule = (struct ip_fw_rule *)(tlv + 1);
|
||||
|
||||
/* copy header */
|
||||
urule->act_ofs = krule->act_ofs;
|
||||
urule->cmd_len = krule->cmd_len;
|
||||
urule->rulenum = krule->rulenum;
|
||||
urule->set = krule->set;
|
||||
urule->flags = krule->flags;
|
||||
urule->id = krule->id;
|
||||
|
||||
/* Copy opcodes */
|
||||
memcpy(urule->cmd, krule->cmd, krule->cmd_len * sizeof(uint32_t));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Copies rule @urule from FreeBSD8 userland format (v0)
|
||||
* to kernel @krule.
|
||||
* Assume @krule is zeroed.
|
||||
*/
|
||||
static void
|
||||
import_rule0(struct rule_check_info *ci)
|
||||
{
|
||||
struct ip_fw_rule0 *urule;
|
||||
struct ip_fw *krule;
|
||||
|
||||
urule = (struct ip_fw_rule0 *)ci->urule;
|
||||
krule = (struct ip_fw *)ci->krule;
|
||||
|
||||
/* copy header */
|
||||
krule->act_ofs = urule->act_ofs;
|
||||
krule->cmd_len = urule->cmd_len;
|
||||
krule->rulenum = urule->rulenum;
|
||||
krule->set = urule->set;
|
||||
if ((urule->_pad & 1) != 0)
|
||||
krule->flags |= IPFW_RULE_NOOPT;
|
||||
|
||||
/* Save rulenum offset */
|
||||
ci->urule_numoff = offsetof(struct ip_fw_rule0, rulenum);
|
||||
|
||||
/* Copy opcodes */
|
||||
memcpy(krule->cmd, urule->cmd, krule->cmd_len * sizeof(uint32_t));
|
||||
}
|
||||
|
||||
static void
|
||||
export_rule0(struct ip_fw *krule, struct ip_fw_rule0 *urule, int len)
|
||||
{
|
||||
/* copy header */
|
||||
memset(urule, 0, len);
|
||||
urule->act_ofs = krule->act_ofs;
|
||||
urule->cmd_len = krule->cmd_len;
|
||||
urule->rulenum = krule->rulenum;
|
||||
urule->set = krule->set;
|
||||
if ((krule->flags & IPFW_RULE_NOOPT) != 0)
|
||||
urule->_pad |= 1;
|
||||
|
||||
/* Copy opcodes */
|
||||
memcpy(urule->cmd, krule->cmd, krule->cmd_len * sizeof(uint32_t));
|
||||
|
||||
/* Export counters */
|
||||
export_cntr0_base(krule, (struct ip_fw_bcounter0 *)&urule->pcnt);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -191,9 +399,10 @@ copy_rule(struct ip_fw *urule, struct ip_fw *krule)
|
||||
static int
|
||||
commit_rules(struct ip_fw_chain *chain, struct rule_check_info *rci, int count)
|
||||
{
|
||||
int error, i, l, insert_before, tcount;
|
||||
int error, i, insert_before, tcount;
|
||||
uint16_t rulenum, *pnum;
|
||||
struct rule_check_info *ci;
|
||||
struct ip_fw *rule, *urule;
|
||||
struct ip_fw *krule;
|
||||
struct ip_fw **map; /* the new array of pointers */
|
||||
|
||||
/* Check if we need to do table remap */
|
||||
@ -264,31 +473,33 @@ commit_rules(struct ip_fw_chain *chain, struct rule_check_info *rci, int count)
|
||||
|
||||
/* FIXME: Handle count > 1 */
|
||||
ci = rci;
|
||||
rule = ci->krule;
|
||||
urule = ci->urule;
|
||||
l = RULESIZE(rule);
|
||||
krule = ci->krule;
|
||||
rulenum = krule->rulenum;
|
||||
|
||||
/* find the insertion point, we will insert before */
|
||||
insert_before = rule->rulenum ? rule->rulenum + 1 : IPFW_DEFAULT_RULE;
|
||||
insert_before = rulenum ? rulenum + 1 : IPFW_DEFAULT_RULE;
|
||||
i = ipfw_find_rule(chain, insert_before, 0);
|
||||
/* duplicate first part */
|
||||
if (i > 0)
|
||||
bcopy(chain->map, map, i * sizeof(struct ip_fw *));
|
||||
map[i] = rule;
|
||||
map[i] = krule;
|
||||
/* duplicate remaining part, we always have the default rule */
|
||||
bcopy(chain->map + i, map + i + 1,
|
||||
sizeof(struct ip_fw *) *(chain->n_rules - i));
|
||||
if (rule->rulenum == 0) {
|
||||
/* write back the number */
|
||||
rule->rulenum = i > 0 ? map[i-1]->rulenum : 0;
|
||||
if (rule->rulenum < IPFW_DEFAULT_RULE - V_autoinc_step)
|
||||
rule->rulenum += V_autoinc_step;
|
||||
urule->rulenum = rule->rulenum;
|
||||
if (rulenum == 0) {
|
||||
/* Compute rule number and write it back */
|
||||
rulenum = i > 0 ? map[i-1]->rulenum : 0;
|
||||
if (rulenum < IPFW_DEFAULT_RULE - V_autoinc_step)
|
||||
rulenum += V_autoinc_step;
|
||||
krule->rulenum = rulenum;
|
||||
/* Save number to userland rule */
|
||||
pnum = (uint16_t *)((caddr_t)ci->urule + ci->urule_numoff);
|
||||
*pnum = rulenum;
|
||||
}
|
||||
|
||||
rule->id = chain->id + 1;
|
||||
krule->id = chain->id + 1;
|
||||
map = swap_map(chain, map, chain->n_rules + 1);
|
||||
chain->static_len += l;
|
||||
chain->static_len += RULEUSIZE0(krule);
|
||||
IPFW_UH_WUNLOCK(chain);
|
||||
if (map)
|
||||
free(map, M_IPFW);
|
||||
@ -307,7 +518,7 @@ ipfw_reap_rules(struct ip_fw *head)
|
||||
|
||||
while ((rule = head) != NULL) {
|
||||
head = head->x_next;
|
||||
free(rule, M_IPFW);
|
||||
free_rule(rule);
|
||||
}
|
||||
}
|
||||
|
||||
@ -466,7 +677,7 @@ del_entry(struct ip_fw_chain *chain, uint32_t arg)
|
||||
rule = map[i];
|
||||
if (keep_rule(rule, cmd, new_set, num))
|
||||
continue;
|
||||
chain->static_len -= RULESIZE(rule);
|
||||
chain->static_len -= RULEUSIZE0(rule);
|
||||
if (cmd != 1)
|
||||
ipfw_expire_dyn_rules(chain, rule, RESVD_SET);
|
||||
rule->x_next = chain->reap;
|
||||
@ -600,23 +811,24 @@ zero_entry(struct ip_fw_chain *chain, u_int32_t arg, int log_only)
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Check validity of the structure before insert.
|
||||
* Rules are simple, so this mostly need to check rule sizes.
|
||||
* Check rule head in FreeBSD11 format
|
||||
*
|
||||
*/
|
||||
static int
|
||||
check_ipfw_struct(struct ip_fw *rule, int size, struct rule_check_info *ci)
|
||||
check_ipfw_rule1(struct ip_fw_rule *rule, int size,
|
||||
struct rule_check_info *ci)
|
||||
{
|
||||
int l, cmdlen = 0;
|
||||
int have_action=0;
|
||||
ipfw_insn *cmd;
|
||||
int l;
|
||||
|
||||
if (size < sizeof(*rule)) {
|
||||
printf("ipfw: rule too short\n");
|
||||
return (EINVAL);
|
||||
}
|
||||
/* first, check for valid size */
|
||||
l = RULESIZE(rule);
|
||||
|
||||
/* Check for valid cmd_len */
|
||||
l = roundup2(RULESIZE(rule), sizeof(uint64_t));
|
||||
if (l != size) {
|
||||
printf("ipfw: size mismatch (have %d want %d)\n", size, l);
|
||||
return (EINVAL);
|
||||
@ -630,12 +842,55 @@ check_ipfw_struct(struct ip_fw *rule, int size, struct rule_check_info *ci)
|
||||
if (rule->rulenum > IPFW_DEFAULT_RULE - 1)
|
||||
return (EINVAL);
|
||||
|
||||
return (check_ipfw_rule_body(rule->cmd, rule->cmd_len, ci));
|
||||
}
|
||||
|
||||
/*
|
||||
* Check rule head in FreeBSD8 format
|
||||
*
|
||||
*/
|
||||
static int
|
||||
check_ipfw_rule0(struct ip_fw_rule0 *rule, int size,
|
||||
struct rule_check_info *ci)
|
||||
{
|
||||
int l;
|
||||
|
||||
if (size < sizeof(*rule)) {
|
||||
printf("ipfw: rule too short\n");
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
/* Check for valid cmd_len */
|
||||
l = sizeof(*rule) + rule->cmd_len * 4 - 4;
|
||||
if (l != size) {
|
||||
printf("ipfw: size mismatch (have %d want %d)\n", size, l);
|
||||
return (EINVAL);
|
||||
}
|
||||
if (rule->act_ofs >= rule->cmd_len) {
|
||||
printf("ipfw: bogus action offset (%u > %u)\n",
|
||||
rule->act_ofs, rule->cmd_len - 1);
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
if (rule->rulenum > IPFW_DEFAULT_RULE - 1)
|
||||
return (EINVAL);
|
||||
|
||||
return (check_ipfw_rule_body(rule->cmd, rule->cmd_len, ci));
|
||||
}
|
||||
|
||||
static int
|
||||
check_ipfw_rule_body(ipfw_insn *cmd, int cmd_len, struct rule_check_info *ci)
|
||||
{
|
||||
int cmdlen, l;
|
||||
int have_action;
|
||||
|
||||
have_action = 0;
|
||||
|
||||
/*
|
||||
* Now go for the individual checks. Very simple ones, basically only
|
||||
* instruction sizes.
|
||||
*/
|
||||
for (l = rule->cmd_len, cmd = rule->cmd ;
|
||||
l > 0 ; l -= cmdlen, cmd += cmdlen) {
|
||||
for (l = cmd_len; l > 0 ; l -= cmdlen, cmd += cmdlen) {
|
||||
cmdlen = F_LEN(cmd);
|
||||
if (cmdlen > l) {
|
||||
printf("ipfw: opcode %d size truncated\n",
|
||||
@ -854,14 +1109,14 @@ check_ipfw_struct(struct ip_fw *rule, int size, struct rule_check_info *ci)
|
||||
printf("ipfw: opcode %d, multiple actions"
|
||||
" not allowed\n",
|
||||
cmd->opcode);
|
||||
return EINVAL;
|
||||
return (EINVAL);
|
||||
}
|
||||
have_action = 1;
|
||||
if (l != cmdlen) {
|
||||
printf("ipfw: opcode %d, action must be"
|
||||
" last opcode\n",
|
||||
cmd->opcode);
|
||||
return EINVAL;
|
||||
return (EINVAL);
|
||||
}
|
||||
break;
|
||||
#ifdef INET6
|
||||
@ -904,25 +1159,25 @@ check_ipfw_struct(struct ip_fw *rule, int size, struct rule_check_info *ci)
|
||||
case O_IP6_DST_MASK:
|
||||
case O_ICMP6TYPE:
|
||||
printf("ipfw: no IPv6 support in kernel\n");
|
||||
return EPROTONOSUPPORT;
|
||||
return (EPROTONOSUPPORT);
|
||||
#endif
|
||||
default:
|
||||
printf("ipfw: opcode %d, unknown opcode\n",
|
||||
cmd->opcode);
|
||||
return EINVAL;
|
||||
return (EINVAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (have_action == 0) {
|
||||
printf("ipfw: missing action\n");
|
||||
return EINVAL;
|
||||
return (EINVAL);
|
||||
}
|
||||
return 0;
|
||||
|
||||
bad_size:
|
||||
printf("ipfw: opcode %d size %d wrong\n",
|
||||
cmd->opcode, cmdlen);
|
||||
return EINVAL;
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
|
||||
@ -954,8 +1209,8 @@ struct ip_fw7 {
|
||||
ipfw_insn cmd[1]; /* storage for commands */
|
||||
};
|
||||
|
||||
int convert_rule_to_7(struct ip_fw *rule);
|
||||
int convert_rule_to_8(struct ip_fw *rule);
|
||||
static int convert_rule_to_7(struct ip_fw_rule0 *rule);
|
||||
static int convert_rule_to_8(struct ip_fw_rule0 *rule);
|
||||
|
||||
#ifndef RULESIZE7
|
||||
#define RULESIZE7(rule) (sizeof(struct ip_fw7) + \
|
||||
@ -973,7 +1228,8 @@ ipfw_getrules(struct ip_fw_chain *chain, void *buf, size_t space)
|
||||
{
|
||||
char *bp = buf;
|
||||
char *ep = bp + space;
|
||||
struct ip_fw *rule, *dst;
|
||||
struct ip_fw *rule;
|
||||
struct ip_fw_rule0 *dst;
|
||||
int error, i, l, warnflag;
|
||||
time_t boot_seconds;
|
||||
|
||||
@ -989,10 +1245,10 @@ ipfw_getrules(struct ip_fw_chain *chain, void *buf, size_t space)
|
||||
if (bp + l + sizeof(uint32_t) <= ep) {
|
||||
bcopy(rule, bp, l + sizeof(uint32_t));
|
||||
error = ipfw_rewrite_table_kidx(chain,
|
||||
(struct ip_fw *)bp);
|
||||
(struct ip_fw_rule0 *)bp);
|
||||
if (error != 0)
|
||||
return (0);
|
||||
error = convert_rule_to_7((struct ip_fw *) bp);
|
||||
error = convert_rule_to_7((struct ip_fw_rule0 *) bp);
|
||||
if (error)
|
||||
return 0; /*XXX correct? */
|
||||
/*
|
||||
@ -1010,14 +1266,13 @@ ipfw_getrules(struct ip_fw_chain *chain, void *buf, size_t space)
|
||||
continue; /* go to next rule */
|
||||
}
|
||||
|
||||
/* normal mode, don't touch rules */
|
||||
l = RULESIZE(rule);
|
||||
l = RULEUSIZE0(rule);
|
||||
if (bp + l > ep) { /* should not happen */
|
||||
printf("overflow dumping static rules\n");
|
||||
break;
|
||||
}
|
||||
dst = (struct ip_fw *)bp;
|
||||
bcopy(rule, dst, l);
|
||||
dst = (struct ip_fw_rule0 *)bp;
|
||||
export_rule0(rule, dst, l);
|
||||
error = ipfw_rewrite_table_kidx(chain, dst);
|
||||
|
||||
/*
|
||||
@ -1058,6 +1313,7 @@ struct dump_args {
|
||||
uint32_t rcount; /* number of rules */
|
||||
uint32_t rsize; /* rules size */
|
||||
uint32_t tcount; /* number of tables */
|
||||
int rcounters; /* counters */
|
||||
};
|
||||
|
||||
/*
|
||||
@ -1073,8 +1329,8 @@ dump_static_rules(struct ip_fw_chain *chain, struct dump_args *da,
|
||||
int i, l;
|
||||
uint32_t tcount;
|
||||
ipfw_obj_ctlv *ctlv;
|
||||
struct ip_fw *dst, *rule;
|
||||
time_t boot_seconds;
|
||||
struct ip_fw *krule;
|
||||
caddr_t dst;
|
||||
|
||||
/* Dump table names first (if any) */
|
||||
if (da->tcount > 0) {
|
||||
@ -1112,19 +1368,17 @@ dump_static_rules(struct ip_fw_chain *chain, struct dump_args *da,
|
||||
ctlv->head.length = da->rsize + sizeof(*ctlv);
|
||||
ctlv->count = da->rcount;
|
||||
|
||||
boot_seconds = boottime.tv_sec;
|
||||
for (i = da->b; i < da->e; i++) {
|
||||
rule = chain->map[i];
|
||||
krule = chain->map[i];
|
||||
|
||||
l = RULESIZE(rule);
|
||||
/* XXX: align to u64 */
|
||||
dst = (struct ip_fw *)ipfw_get_sopt_space(sd, l);
|
||||
if (rule == NULL)
|
||||
l = RULEUSIZE1(krule) + sizeof(ipfw_obj_tlv);
|
||||
if (da->rcounters != 0)
|
||||
l += sizeof(struct ip_fw_bcounter);
|
||||
dst = (caddr_t)ipfw_get_sopt_space(sd, l);
|
||||
if (dst == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
bcopy(rule, dst, l);
|
||||
if (dst->timestamp != 0)
|
||||
dst->timestamp += boot_seconds;
|
||||
export_rule1(krule, dst, l, da->rcounters);
|
||||
}
|
||||
|
||||
return (0);
|
||||
@ -1137,8 +1391,10 @@ dump_static_rules(struct ip_fw_chain *chain, struct dump_args *da,
|
||||
* size = ipfw_cfg_lheader.size
|
||||
* Reply: [ ipfw_rules_lheader
|
||||
* [ ipfw_obj_ctlv(IPFW_TLV_TBL_LIST) ipfw_obj_ntlv x N ] (optional)
|
||||
* [ ipfw_obj_ctlv(IPFW_TLV_RULE_LIST) ip_fw x N ] (optional)
|
||||
* [ ipfw_obj_ctlv(IPFW_TLV_STATE_LIST) ipfw_dyn_rule x N ] (optional)
|
||||
* [ ipfw_obj_ctlv(IPFW_TLV_RULE_LIST)
|
||||
* ipfw_obj_tlv(IPFW_TLV_RULE_ENT) [ ip_fw_bcounter (optional) ip_fw_rule ]
|
||||
* ] (optional)
|
||||
* [ ipfw_obj_ctlv(IPFW_TLV_STATE_LIST) ipfw_obj_dyntlv x N ] (optional)
|
||||
* ]
|
||||
* * NOTE IPFW_TLV_STATE_LIST has the single valid field: objsize.
|
||||
* The rest (size, count) are set to zero and needs to be ignored.
|
||||
@ -1190,10 +1446,15 @@ dump_config(struct ip_fw_chain *chain, struct sockopt_data *sd)
|
||||
if (hdr->flags & IPFW_CFG_GET_STATIC) {
|
||||
for (i = da.b; i < da.e; i++) {
|
||||
rule = chain->map[i];
|
||||
da.rsize += RULESIZE(rule);
|
||||
da.rsize += RULEUSIZE1(rule) + sizeof(ipfw_obj_tlv);
|
||||
da.rcount++;
|
||||
da.tcount += ipfw_mark_table_kidx(chain, rule, bmask);
|
||||
}
|
||||
/* Add counters if requested */
|
||||
if (hdr->flags & IPFW_CFG_GET_COUNTERS) {
|
||||
da.rsize += sizeof(struct ip_fw_bcounter) * da.rcount;
|
||||
da.rcounters = 1;
|
||||
}
|
||||
|
||||
if (da.tcount > 0)
|
||||
sz += da.tcount * sizeof(ipfw_obj_ntlv) +
|
||||
@ -1202,7 +1463,8 @@ dump_config(struct ip_fw_chain *chain, struct sockopt_data *sd)
|
||||
}
|
||||
|
||||
if (hdr->flags & IPFW_CFG_GET_STATES)
|
||||
sz += ipfw_dyn_get_count() * sizeof(ipfw_obj_dyntlv);
|
||||
sz += ipfw_dyn_get_count() * sizeof(ipfw_obj_dyntlv) +
|
||||
sizeof(ipfw_obj_ctlv);
|
||||
|
||||
/* Fill header anyway */
|
||||
hdr->size = sz;
|
||||
@ -1286,7 +1548,7 @@ add_entry(struct ip_fw_chain *chain, struct sockopt_data *sd)
|
||||
ipfw_obj_ntlv *ntlv;
|
||||
int clen, error, idx;
|
||||
uint32_t count, read;
|
||||
struct ip_fw *r;
|
||||
struct ip_fw_rule *r;
|
||||
struct rule_check_info rci, *ci, *cbuf;
|
||||
ip_fw3_opheader *op3;
|
||||
int i, rsize;
|
||||
@ -1308,8 +1570,11 @@ add_entry(struct ip_fw_chain *chain, struct sockopt_data *sd)
|
||||
|
||||
if (ctlv->head.type == IPFW_TLV_TBLNAME_LIST) {
|
||||
clen = ctlv->head.length;
|
||||
/* Check size and alignment */
|
||||
if (clen > sd->valsize || clen < sizeof(*ctlv))
|
||||
return (EINVAL);
|
||||
if ((clen % sizeof(uint64_t)) != 0)
|
||||
return (EINVAL);
|
||||
|
||||
/*
|
||||
* Some table names or other named objects.
|
||||
@ -1354,6 +1619,8 @@ add_entry(struct ip_fw_chain *chain, struct sockopt_data *sd)
|
||||
clen = ctlv->head.length;
|
||||
if (clen + read > sd->valsize || clen < sizeof(*ctlv))
|
||||
return (EINVAL);
|
||||
if ((clen % sizeof(uint64_t)) != 0)
|
||||
return (EINVAL);
|
||||
|
||||
/*
|
||||
* TODO: Permit adding multiple rules at once
|
||||
@ -1363,7 +1630,7 @@ add_entry(struct ip_fw_chain *chain, struct sockopt_data *sd)
|
||||
|
||||
clen -= sizeof(*ctlv);
|
||||
|
||||
if (ctlv->count > clen / sizeof(struct ip_fw))
|
||||
if (ctlv->count > clen / sizeof(struct ip_fw_rule))
|
||||
return (EINVAL);
|
||||
|
||||
/* Allocate state for each rule or use stack */
|
||||
@ -1377,36 +1644,38 @@ add_entry(struct ip_fw_chain *chain, struct sockopt_data *sd)
|
||||
|
||||
/*
|
||||
* Check each rule for validness.
|
||||
* Ensure numbered rules are sorted ascending.
|
||||
* Ensure numbered rules are sorted ascending
|
||||
* and properly aligned
|
||||
*/
|
||||
idx = -1;
|
||||
r = (struct ip_fw *)(ctlv + 1);
|
||||
idx = 0;
|
||||
r = (struct ip_fw_rule *)(ctlv + 1);
|
||||
count = 0;
|
||||
error = 0;
|
||||
while (clen > 0) {
|
||||
rsize = RULESIZE(r);
|
||||
rsize = roundup2(RULESIZE(r), sizeof(uint64_t));
|
||||
if (rsize > clen || ctlv->count <= count) {
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
ci->ctlv = tstate;
|
||||
error = check_ipfw_struct(r, rsize, ci);
|
||||
error = check_ipfw_rule1(r, rsize, ci);
|
||||
if (error != 0)
|
||||
break;
|
||||
|
||||
/* Check sorting */
|
||||
if (r->rulenum != 0 && r->rulenum < idx) {
|
||||
printf("rulenum %d idx %d\n", r->rulenum, idx);
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
idx = r->rulenum;
|
||||
|
||||
ci->urule = r;
|
||||
ci->urule = (caddr_t)r;
|
||||
|
||||
rsize = roundup2(rsize, sizeof(uint64_t));
|
||||
clen -= rsize;
|
||||
r = (struct ip_fw *)((caddr_t)r + rsize);
|
||||
r = (struct ip_fw_rule *)((caddr_t)r + rsize);
|
||||
count++;
|
||||
ci++;
|
||||
}
|
||||
@ -1433,8 +1702,9 @@ add_entry(struct ip_fw_chain *chain, struct sockopt_data *sd)
|
||||
* Allocate storage and try to add them to chain.
|
||||
*/
|
||||
for (i = 0, ci = cbuf; i < rtlv->count; i++, ci++) {
|
||||
ci->krule = malloc(RULESIZE(ci->urule), M_IPFW, M_WAITOK);
|
||||
copy_rule(ci->urule, ci->krule);
|
||||
clen = RULEKSIZE1((struct ip_fw_rule *)ci->urule);
|
||||
ci->krule = ipfw_alloc_rule(chain, clen);
|
||||
import_rule1(ci);
|
||||
}
|
||||
|
||||
if ((error = commit_rules(chain, cbuf, rtlv->count)) != 0) {
|
||||
@ -1458,7 +1728,8 @@ ipfw_ctl(struct sockopt *sopt)
|
||||
#define RULE_MAXSIZE (256*sizeof(u_int32_t))
|
||||
int error;
|
||||
size_t bsize_max, size, valsize;
|
||||
struct ip_fw *buf, *rule;
|
||||
struct ip_fw *buf;
|
||||
struct ip_fw_rule0 *rule;
|
||||
struct ip_fw_chain *chain;
|
||||
u_int32_t rulenum[2];
|
||||
uint32_t opt;
|
||||
@ -1569,7 +1840,7 @@ ipfw_ctl(struct sockopt *sopt)
|
||||
size += ipfw_dyn_len();
|
||||
if (size >= sopt->sopt_valsize)
|
||||
break;
|
||||
buf = malloc(size, M_TEMP, M_WAITOK);
|
||||
buf = malloc(size, M_TEMP, M_WAITOK | M_ZERO);
|
||||
IPFW_UH_RLOCK(chain);
|
||||
/* check again how much space we need */
|
||||
want = chain->static_len + ipfw_dyn_len();
|
||||
@ -1613,29 +1884,27 @@ ipfw_ctl(struct sockopt *sopt)
|
||||
* the first ipfw command is 'ipfw [pipe] list')
|
||||
* the ipfw binary may crash or loop infinitly...
|
||||
*/
|
||||
if (sopt->sopt_valsize == RULESIZE7(rule)) {
|
||||
size = sopt->sopt_valsize;
|
||||
if (size == RULESIZE7(rule)) {
|
||||
is7 = 1;
|
||||
error = convert_rule_to_8(rule);
|
||||
if (error) {
|
||||
free(rule, M_TEMP);
|
||||
return error;
|
||||
}
|
||||
if (error == 0)
|
||||
error = check_ipfw_struct(rule, RULESIZE(rule), &ci);
|
||||
} else {
|
||||
size = RULESIZE(rule);
|
||||
} else
|
||||
is7 = 0;
|
||||
if (error == 0)
|
||||
error = check_ipfw_struct(rule, sopt->sopt_valsize,&ci);
|
||||
}
|
||||
error = check_ipfw_rule0(rule, size, &ci);
|
||||
if (error == 0) {
|
||||
/* locking is done within add_rule() */
|
||||
struct ip_fw *krule;
|
||||
krule = malloc(RULESIZE(rule), M_IPFW, M_WAITOK);
|
||||
copy_rule(rule, krule);
|
||||
ci.urule = rule;
|
||||
krule = ipfw_alloc_rule(chain, RULEKSIZE0(rule));
|
||||
ci.urule = (caddr_t)rule;
|
||||
ci.krule = krule;
|
||||
import_rule0(&ci);
|
||||
error = commit_rules(chain, &ci, 1);
|
||||
size = RULESIZE(rule);
|
||||
if (!error && sopt->sopt_dir == SOPT_GET) {
|
||||
if (is7) {
|
||||
error = convert_rule_to_7(rule);
|
||||
@ -1971,8 +2240,8 @@ ipfw_get_sopt_header(struct sockopt_data *sd, size_t needed)
|
||||
#define RULE_MAXSIZE (256*sizeof(u_int32_t))
|
||||
|
||||
/* Functions to convert rules 7.2 <==> 8.0 */
|
||||
int
|
||||
convert_rule_to_7(struct ip_fw *rule)
|
||||
static int
|
||||
convert_rule_to_7(struct ip_fw_rule0 *rule)
|
||||
{
|
||||
/* Used to modify original rule */
|
||||
struct ip_fw7 *rule7 = (struct ip_fw7 *)rule;
|
||||
@ -1990,7 +2259,7 @@ convert_rule_to_7(struct ip_fw *rule)
|
||||
bcopy(rule, tmp, RULE_MAXSIZE);
|
||||
|
||||
/* Copy fields */
|
||||
rule7->_pad = tmp->_pad;
|
||||
//rule7->_pad = tmp->_pad;
|
||||
rule7->set = tmp->set;
|
||||
rule7->rulenum = tmp->rulenum;
|
||||
rule7->cmd_len = tmp->cmd_len;
|
||||
@ -1998,9 +2267,7 @@ convert_rule_to_7(struct ip_fw *rule)
|
||||
rule7->next_rule = (struct ip_fw7 *)tmp->next_rule;
|
||||
rule7->next = (struct ip_fw7 *)tmp->x_next;
|
||||
rule7->cmd_len = tmp->cmd_len;
|
||||
rule7->pcnt = tmp->pcnt;
|
||||
rule7->bcnt = tmp->bcnt;
|
||||
rule7->timestamp = tmp->timestamp;
|
||||
export_cntr1_base(tmp, (struct ip_fw_bcounter *)&rule7->pcnt);
|
||||
|
||||
/* Copy commands */
|
||||
for (ll = tmp->cmd_len, ccmd = tmp->cmd, dst = rule7->cmd ;
|
||||
@ -2026,8 +2293,8 @@ convert_rule_to_7(struct ip_fw *rule)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
convert_rule_to_8(struct ip_fw *rule)
|
||||
static int
|
||||
convert_rule_to_8(struct ip_fw_rule0 *rule)
|
||||
{
|
||||
/* Used to modify original rule */
|
||||
struct ip_fw7 *rule7 = (struct ip_fw7 *) rule;
|
||||
|
@ -1893,7 +1893,7 @@ bind_table_rule(struct ip_fw_chain *ch, struct ip_fw *rule,
|
||||
* Raises error on any other tables.
|
||||
*/
|
||||
int
|
||||
ipfw_rewrite_table_kidx(struct ip_fw_chain *chain, struct ip_fw *rule)
|
||||
ipfw_rewrite_table_kidx(struct ip_fw_chain *chain, struct ip_fw_rule0 *rule)
|
||||
{
|
||||
int cmdlen, error, l;
|
||||
ipfw_insn *cmd;
|
||||
|
@ -118,6 +118,8 @@ int ipfw_create_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd);
|
||||
int ipfw_modify_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd);
|
||||
int ipfw_flush_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd);
|
||||
/* Exported to support legacy opcodes */
|
||||
int add_table_entry(struct ip_fw_chain *ch, struct tid_info *ti,
|
||||
struct tentry_info *tei);
|
||||
@ -125,11 +127,10 @@ int del_table_entry(struct ip_fw_chain *ch, struct tid_info *ti,
|
||||
struct tentry_info *tei);
|
||||
int flush_table(struct ip_fw_chain *ch, struct tid_info *ti);
|
||||
|
||||
int ipfw_flush_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd);
|
||||
int ipfw_rewrite_table_uidx(struct ip_fw_chain *chain,
|
||||
struct rule_check_info *ci);
|
||||
int ipfw_rewrite_table_kidx(struct ip_fw_chain *chain, struct ip_fw *rule);
|
||||
int ipfw_rewrite_table_kidx(struct ip_fw_chain *chain,
|
||||
struct ip_fw_rule0 *rule);
|
||||
int ipfw_mark_table_kidx(struct ip_fw_chain *chain, struct ip_fw *rule,
|
||||
uint32_t *bmask);
|
||||
int ipfw_export_table_ntlv(struct ip_fw_chain *ch, uint16_t kidx,
|
||||
|
Loading…
Reference in New Issue
Block a user