svn commit: r265699 - in stable/9: sbin/ipfw sys/netpfil/ipfw
Alexander V. Chernikov
melifaro at FreeBSD.org
Thu May 8 19:11:16 UTC 2014
Author: melifaro
Date: Thu May 8 19:11:14 2014
New Revision: 265699
URL: http://svnweb.freebsd.org/changeset/base/265699
Log:
Merge r258708, r258711, r260247, r261117.
r258708:
Check ipfw table numbers in both user and kernel space before rule addition.
Found by: Saychik Pavel <umka at 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
Modified:
stable/9/sbin/ipfw/ipfw2.c
stable/9/sbin/ipfw/ipfw2.h
stable/9/sys/netpfil/ipfw/ip_fw2.c
stable/9/sys/netpfil/ipfw/ip_fw_private.h
stable/9/sys/netpfil/ipfw/ip_fw_sockopt.c
stable/9/sys/netpfil/ipfw/ip_fw_table.c
Directory Properties:
stable/9/sbin/ (props changed)
stable/9/sbin/ipfw/ (props changed)
stable/9/sys/ (props changed)
stable/9/sys/netpfil/ (props changed)
Modified: stable/9/sbin/ipfw/ipfw2.c
==============================================================================
--- stable/9/sbin/ipfw/ipfw2.c Thu May 8 19:10:04 2014 (r265698)
+++ stable/9/sbin/ipfw/ipfw2.c Thu May 8 19:11:14 2014 (r265699)
@@ -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
@@ -2202,6 +2204,7 @@ fill_ip(ipfw_insn_ip *cmd, char *av, int
{
int len = 0;
uint32_t *d = ((ipfw_insn_u32 *)cmd)->d;
+ uint32_t tables_max;
cmd->o.len &= ~F_LEN_MASK; /* zero len */
@@ -2220,6 +2223,10 @@ fill_ip(ipfw_insn_ip *cmd, char *av, int
*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);
@@ -4108,6 +4115,33 @@ static void table_list(uint16_t num, int
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]
* ipfw table N delete addr[/masklen]
@@ -4120,19 +4154,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));
Modified: stable/9/sbin/ipfw/ipfw2.h
==============================================================================
--- stable/9/sbin/ipfw/ipfw2.h Thu May 8 19:10:04 2014 (r265698)
+++ stable/9/sbin/ipfw/ipfw2.h Thu May 8 19:11:14 2014 (r265699)
@@ -228,6 +228,8 @@ char const *match_value(struct _s_x *p,
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);
Modified: stable/9/sys/netpfil/ipfw/ip_fw2.c
==============================================================================
--- stable/9/sys/netpfil/ipfw/ip_fw2.c Thu May 8 19:10:04 2014 (r265698)
+++ stable/9/sys/netpfil/ipfw/ip_fw2.c Thu May 8 19:11:14 2014 (r265699)
@@ -2395,38 +2395,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: {
@@ -2657,7 +2654,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);
Modified: stable/9/sys/netpfil/ipfw/ip_fw_private.h
==============================================================================
--- stable/9/sys/netpfil/ipfw/ip_fw_private.h Thu May 8 19:10:04 2014 (r265698)
+++ stable/9/sys/netpfil/ipfw/ip_fw_private.h Thu May 8 19:11:14 2014 (r265699)
@@ -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 */
Modified: stable/9/sys/netpfil/ipfw/ip_fw_sockopt.c
==============================================================================
--- stable/9/sys/netpfil/ipfw/ip_fw_sockopt.c Thu May 8 19:10:04 2014 (r265698)
+++ stable/9/sys/netpfil/ipfw/ip_fw_sockopt.c Thu May 8 19:11:14 2014 (r265699)
@@ -159,7 +159,7 @@ ipfw_add_rule(struct ip_fw_chain *chain,
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);
@@ -655,7 +655,7 @@ check_ipfw_struct(struct ip_fw *rule, in
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);
Modified: stable/9/sys/netpfil/ipfw/ip_fw_table.c
==============================================================================
--- stable/9/sys/netpfil/ipfw/ip_fw_table.c Thu May 8 19:10:04 2014 (r265698)
+++ stable/9/sys/netpfil/ipfw/ip_fw_table.c Thu May 8 19:11:14 2014 (r265699)
@@ -544,7 +544,7 @@ ipfw_lookup_table(struct ip_fw_chain *ch
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_
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_
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:
More information about the svn-src-stable-9
mailing list