From owner-svn-src-all@FreeBSD.ORG Thu May 8 19:11:16 2014 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 45E66E4C; Thu, 8 May 2014 19:11:16 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 312C38A0; Thu, 8 May 2014 19:11:16 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s48JBGNd060658; Thu, 8 May 2014 19:11:16 GMT (envelope-from melifaro@svn.freebsd.org) Received: (from melifaro@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s48JBEre060044; Thu, 8 May 2014 19:11:14 GMT (envelope-from melifaro@svn.freebsd.org) Message-Id: <201405081911.s48JBEre060044@svn.freebsd.org> From: "Alexander V. Chernikov" Date: Thu, 8 May 2014 19:11:14 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org Subject: svn commit: r265699 - in stable/9: sbin/ipfw sys/netpfil/ipfw X-SVN-Group: stable-9 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 08 May 2014 19:11:16 -0000 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 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: