summaryrefslogtreecommitdiffstats
path: root/sbin
diff options
context:
space:
mode:
authormelifaro <melifaro@FreeBSD.org>2014-05-08 19:11:41 +0000
committermelifaro <melifaro@FreeBSD.org>2014-05-08 19:11:41 +0000
commit89bf7e80ea7ce88fd4bbd25c5f6576c40dea5acd (patch)
tree757fb0f228e9335e00a5a6d852a808bcee62a934 /sbin
parent768038fadc43d4f5ab1e0d53d353bb7f5a892321 (diff)
downloadFreeBSD-src-89bf7e80ea7ce88fd4bbd25c5f6576c40dea5acd.zip
FreeBSD-src-89bf7e80ea7ce88fd4bbd25c5f6576c40dea5acd.tar.gz
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
Diffstat (limited to 'sbin')
-rw-r--r--sbin/ipfw/ipfw2.c45
-rw-r--r--sbin/ipfw/ipfw2.h2
2 files changed, 37 insertions, 10 deletions
diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c
index 196067d..98b25b3 100644
--- a/sbin/ipfw/ipfw2.c
+++ b/sbin/ipfw/ipfw2.c
@@ -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);
@@ -4119,6 +4126,33 @@ 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]
* ipfw table N delete addr[/masklen]
@@ -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));
diff --git a/sbin/ipfw/ipfw2.h b/sbin/ipfw/ipfw2.h
index 9abe6ee..6e895b8 100644
--- a/sbin/ipfw/ipfw2.h
+++ b/sbin/ipfw/ipfw2.h
@@ -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);
OpenPOWER on IntegriCloud