Merge r258708, r258711, r260247, r261117.
r258708: Check ipfw table numbers in both user and kernel space before rule addition. Found by: Saychik Pavel <umka@localka.net> r258711: Simplify O_NAT opcode handling. r260247: Use rnh_matchaddr instead of rnh_lookup for longest-prefix match. rnh_lookup is effectively the same as rnh_matchaddr if called with empy network mask. r261117: Reorder struct ip_fw_chain: * move rarely-used fields down * move uh_lock to different cacheline * remove some usused fields
This commit is contained in:
parent
768038fadc
commit
89bf7e80ea
@ -60,6 +60,8 @@ int resvd_set_number = RESVD_SET;
|
||||
|
||||
int ipfw_socket = -1;
|
||||
|
||||
uint32_t ipfw_tables_max = 0; /* Number of tables supported by kernel */
|
||||
|
||||
#ifndef s6_addr32
|
||||
#define s6_addr32 __u6_addr.__u6_addr32
|
||||
#endif
|
||||
@ -2203,6 +2205,7 @@ fill_ip(ipfw_insn_ip *cmd, char *av, int cblen)
|
||||
{
|
||||
int len = 0;
|
||||
uint32_t *d = ((ipfw_insn_u32 *)cmd)->d;
|
||||
uint32_t tables_max;
|
||||
|
||||
cmd->o.len &= ~F_LEN_MASK; /* zero len */
|
||||
|
||||
@ -2221,6 +2224,10 @@ fill_ip(ipfw_insn_ip *cmd, char *av, int cblen)
|
||||
*p++ = '\0';
|
||||
cmd->o.opcode = O_IP_DST_LOOKUP;
|
||||
cmd->o.arg1 = strtoul(av + 6, NULL, 0);
|
||||
tables_max = ipfw_get_tables_max();
|
||||
if (cmd->o.arg1 > tables_max)
|
||||
errx(EX_USAGE, "The table number exceeds the maximum "
|
||||
"allowed value (%u)", tables_max - 1);
|
||||
if (p) {
|
||||
cmd->o.len |= F_INSN_SIZE(ipfw_insn_u32);
|
||||
d[0] = strtoul(p, NULL, 0);
|
||||
@ -4118,6 +4125,33 @@ ipfw_flush(int force)
|
||||
static void table_list(uint16_t num, int need_header);
|
||||
static void table_fill_xentry(char *arg, ipfw_table_xentry *xent);
|
||||
|
||||
/*
|
||||
* Retrieve maximum number of tables supported by ipfw(4) module.
|
||||
*/
|
||||
uint32_t
|
||||
ipfw_get_tables_max()
|
||||
{
|
||||
size_t len;
|
||||
uint32_t tables_max;
|
||||
|
||||
if (ipfw_tables_max != 0)
|
||||
return (ipfw_tables_max);
|
||||
|
||||
len = sizeof(tables_max);
|
||||
if (sysctlbyname("net.inet.ip.fw.tables_max", &tables_max, &len,
|
||||
NULL, 0) == -1) {
|
||||
if (co.test_only)
|
||||
tables_max = 128; /* Old conservative default */
|
||||
else
|
||||
errx(1, "Can't determine maximum number of ipfw tables."
|
||||
" Perhaps you forgot to load ipfw module?");
|
||||
}
|
||||
|
||||
ipfw_tables_max = tables_max;
|
||||
|
||||
return (ipfw_tables_max);
|
||||
}
|
||||
|
||||
/*
|
||||
* This one handles all table-related commands
|
||||
* ipfw table N add addr[/masklen] [value]
|
||||
@ -4131,19 +4165,10 @@ ipfw_table_handler(int ac, char *av[])
|
||||
ipfw_table_xentry xent;
|
||||
int do_add;
|
||||
int is_all;
|
||||
size_t len;
|
||||
uint32_t a;
|
||||
uint32_t tables_max;
|
||||
|
||||
len = sizeof(tables_max);
|
||||
if (sysctlbyname("net.inet.ip.fw.tables_max", &tables_max, &len,
|
||||
NULL, 0) == -1) {
|
||||
if (co.test_only)
|
||||
tables_max = 128; /* Old conservative default */
|
||||
else
|
||||
errx(1, "Can't determine maximum number of ipfw tables."
|
||||
" Perhaps you forgot to load ipfw module?");
|
||||
}
|
||||
tables_max = ipfw_get_tables_max();
|
||||
|
||||
memset(&xent, 0, sizeof(xent));
|
||||
|
||||
|
@ -228,6 +228,8 @@ char const *match_value(struct _s_x *p, int value);
|
||||
|
||||
int do_cmd(int optname, void *optval, uintptr_t optlen);
|
||||
|
||||
uint32_t ipfw_get_tables_max(void);
|
||||
|
||||
struct in6_addr;
|
||||
void n2mask(struct in6_addr *mask, int n);
|
||||
int contigmask(uint8_t *p, int len);
|
||||
|
@ -2404,38 +2404,35 @@ do { \
|
||||
}
|
||||
|
||||
case O_NAT:
|
||||
l = 0; /* exit inner loop */
|
||||
done = 1; /* exit outer loop */
|
||||
if (!IPFW_NAT_LOADED) {
|
||||
retval = IP_FW_DENY;
|
||||
} else {
|
||||
struct cfg_nat *t;
|
||||
int nat_id;
|
||||
break;
|
||||
}
|
||||
|
||||
set_match(args, f_pos, chain);
|
||||
/* Check if this is 'global' nat rule */
|
||||
if (cmd->arg1 == 0) {
|
||||
retval = ipfw_nat_ptr(args, NULL, m);
|
||||
l = 0;
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
t = ((ipfw_insn_nat *)cmd)->nat;
|
||||
if (t == NULL) {
|
||||
struct cfg_nat *t;
|
||||
int nat_id;
|
||||
|
||||
set_match(args, f_pos, chain);
|
||||
/* Check if this is 'global' nat rule */
|
||||
if (cmd->arg1 == 0) {
|
||||
retval = ipfw_nat_ptr(args, NULL, m);
|
||||
break;
|
||||
}
|
||||
t = ((ipfw_insn_nat *)cmd)->nat;
|
||||
if (t == NULL) {
|
||||
nat_id = IP_FW_ARG_TABLEARG(cmd->arg1);
|
||||
t = (*lookup_nat_ptr)(&chain->nat, nat_id);
|
||||
|
||||
if (t == NULL) {
|
||||
retval = IP_FW_DENY;
|
||||
l = 0; /* exit inner loop */
|
||||
done = 1; /* exit outer loop */
|
||||
break;
|
||||
}
|
||||
if (cmd->arg1 != IP_FW_TABLEARG)
|
||||
((ipfw_insn_nat *)cmd)->nat = t;
|
||||
}
|
||||
retval = ipfw_nat_ptr(args, t, m);
|
||||
}
|
||||
l = 0; /* exit inner loop */
|
||||
done = 1; /* exit outer loop */
|
||||
retval = ipfw_nat_ptr(args, t, m);
|
||||
break;
|
||||
|
||||
case O_REASS: {
|
||||
@ -2660,7 +2657,7 @@ vnet_ipfw_init(const void *unused)
|
||||
rule->set = RESVD_SET;
|
||||
rule->cmd[0].len = 1;
|
||||
rule->cmd[0].opcode = default_to_accept ? O_ACCEPT : O_DENY;
|
||||
chain->rules = chain->default_rule = chain->map[0] = rule;
|
||||
chain->default_rule = chain->map[0] = rule;
|
||||
chain->id = rule->id = 1;
|
||||
|
||||
IPFW_LOCK_INIT(chain);
|
||||
|
@ -213,25 +213,27 @@ 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 */
|
||||
struct ip_fw *reap; /* list of rules to reap */
|
||||
struct ip_fw *default_rule;
|
||||
int n_rules; /* number of static rules */
|
||||
int static_len; /* total len of static rules */
|
||||
struct ip_fw **map; /* array of rule ptrs to ease lookup */
|
||||
uint32_t id; /* ruleset id */
|
||||
int n_rules; /* number of static rules */
|
||||
LIST_HEAD(nat_list, cfg_nat) nat; /* list of nat entries */
|
||||
struct radix_node_head **tables; /* IPv4 tables */
|
||||
struct radix_node_head **xtables; /* extended tables */
|
||||
uint8_t *tabletype; /* Array of table types */
|
||||
#if defined( __linux__ ) || defined( _WIN32 )
|
||||
spinlock_t rwmtx;
|
||||
spinlock_t uh_lock;
|
||||
#else
|
||||
struct rwlock rwmtx;
|
||||
#endif
|
||||
int static_len; /* total len of static rules */
|
||||
uint32_t gencnt; /* NAT generation count */
|
||||
struct ip_fw *reap; /* list of rules to reap */
|
||||
struct ip_fw *default_rule;
|
||||
#if defined( __linux__ ) || defined( _WIN32 )
|
||||
spinlock_t uh_lock;
|
||||
#else
|
||||
struct rwlock uh_lock; /* lock for upper half */
|
||||
#endif
|
||||
uint32_t id; /* ruleset id */
|
||||
uint32_t gencnt; /* generation count */
|
||||
};
|
||||
|
||||
struct sockopt; /* used by tcp_var.h */
|
||||
|
@ -159,7 +159,7 @@ ipfw_add_rule(struct ip_fw_chain *chain, struct ip_fw *input_rule)
|
||||
int i, l, insert_before;
|
||||
struct ip_fw **map; /* the new array of pointers */
|
||||
|
||||
if (chain->rules == NULL || input_rule->rulenum > IPFW_DEFAULT_RULE-1)
|
||||
if (chain->map == NULL || input_rule->rulenum > IPFW_DEFAULT_RULE - 1)
|
||||
return (EINVAL);
|
||||
|
||||
l = RULESIZE(input_rule);
|
||||
@ -653,7 +653,7 @@ check_ipfw_struct(struct ip_fw *rule, int size)
|
||||
|
||||
case O_IP_SRC_LOOKUP:
|
||||
case O_IP_DST_LOOKUP:
|
||||
if (cmd->arg1 >= IPFW_TABLES_MAX) {
|
||||
if (cmd->arg1 >= V_fw_tables_max) {
|
||||
printf("ipfw: invalid table number %d\n",
|
||||
cmd->arg1);
|
||||
return (EINVAL);
|
||||
|
@ -544,7 +544,7 @@ ipfw_lookup_table(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr,
|
||||
return (0);
|
||||
KEY_LEN(sa) = KEY_LEN_INET;
|
||||
sa.sin_addr.s_addr = addr;
|
||||
ent = (struct table_entry *)(rnh->rnh_lookup(&sa, NULL, rnh));
|
||||
ent = (struct table_entry *)(rnh->rnh_matchaddr(&sa, rnh));
|
||||
if (ent != NULL) {
|
||||
*val = ent->value;
|
||||
return (1);
|
||||
@ -570,7 +570,7 @@ ipfw_lookup_table_extended(struct ip_fw_chain *ch, uint16_t tbl, void *paddr,
|
||||
case IPFW_TABLE_CIDR:
|
||||
KEY_LEN(sa6) = KEY_LEN_INET6;
|
||||
memcpy(&sa6.sin6_addr, paddr, sizeof(struct in6_addr));
|
||||
xent = (struct table_xentry *)(rnh->rnh_lookup(&sa6, NULL, rnh));
|
||||
xent = (struct table_xentry *)(rnh->rnh_matchaddr(&sa6, rnh));
|
||||
break;
|
||||
|
||||
case IPFW_TABLE_INTERFACE:
|
||||
@ -578,7 +578,7 @@ ipfw_lookup_table_extended(struct ip_fw_chain *ch, uint16_t tbl, void *paddr,
|
||||
strlcpy(iface.ifname, (char *)paddr, IF_NAMESIZE) + 1;
|
||||
/* Assume direct match */
|
||||
/* FIXME: Add interface pattern matching */
|
||||
xent = (struct table_xentry *)(rnh->rnh_lookup(&iface, NULL, rnh));
|
||||
xent = (struct table_xentry *)(rnh->rnh_matchaddr(&iface, rnh));
|
||||
break;
|
||||
|
||||
default:
|
||||
|
Loading…
x
Reference in New Issue
Block a user