Date: Wed, 21 May 2003 01:04:01 -0700 From: "Gregory P. Smith" <greg@electricrain.com> To: freebsd-net@freebsd.org Subject: CFR: patch to ipfw2 iplen to match a range of lengths Message-ID: <20030521080400.GB21522@zot.electricrain.com>
next in thread | raw e-mail | index | archive | help
--2fHTh5uZTiUOsy+g Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Here's a patch (attached) to make RELENG_5_0's ipfw2 iplen match a range of values rather than a single length. IMHO its much more useful than the current method of only matching an exact length. How often do you need to match only an exact packet length rather than "all packets less than 128 bytes" or "all packets over 500 bytes"? The ipfw command syntax doesn't change for those using the existing iplen rule. It adds the ability to say things like "iplen 28-128" any comments? Greg --2fHTh5uZTiUOsy+g Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="releng_5_0_ipfw2_iplen_range.patch" --- sbin/ipfw/ipfw.8.saved Mon May 19 23:01:38 2003 +++ sbin/ipfw/ipfw.8 Wed May 21 00:25:07 2003 @@ -885,10 +885,13 @@ .Cm ip_id field has value .Ar id . -.It Cm iplen Ar len +.It Cm iplen Ar len | minlen-maxlen Matches IP packets whose total length, including header and data, is .Ar len -bytes. +bytes or, if a range is given, is >= +.Ar minlen +and <= +.Ar maxlen. .It Cm ipoptions Ar spec Matches packets whose IP header contains the comma separated list of options specified in --- sbin/ipfw/ipfw2.c.saved Mon May 19 23:01:48 2003 +++ sbin/ipfw/ipfw2.c Wed May 21 00:44:54 2003 @@ -534,6 +534,42 @@ return i; } +/* + * fill the body of the command with the min & max u16s delimiting a range + */ +static void +fill_minmax(ipfw_insn_u16 *cmd, enum ipfw_opcodes opcode, char *av) +{ + u_int16_t *p = cmd->ports; + char *s = av; + u_int16_t min, max; + + min = strtol(av, &s, 0); + if (s == av) /* no parameter */ + errx(EX_DATAERR, "missing minimum or only value\n"); + if (*s == '-') { /* a range */ + av = s+1; + max = strtol(av, &s, 0); + if (s == av) { /* no parameter */ + errx(EX_DATAERR, "missing maximum value in range <%u->\n", min); + } else { + p[0] = min; + p[1] = max; + if (min > max) + errx(EX_DATAERR, "min > max in range <%u-%u>\n", min, max); + } + } else if (*s == '\0') { + p[0] = p[1] = min; + } else { /* invalid separator */ + errx(EX_DATAERR, "invalid separator <%c> in <%s>\n", + *s, av); + } + + cmd->o.opcode = opcode; + cmd->o.len |= 2; /* leave F_NOT and F_OR untouched */ +} + + static struct _s_x icmpcodes[] = { { "net", ICMP_UNREACH_NET }, { "host", ICMP_UNREACH_HOST }, @@ -1099,8 +1135,15 @@ printf(" ipprecedence %u", (cmd->arg1) >> 5 ); break; - case O_IPLEN: - printf(" iplen %u", cmd->arg1 ); + case O_IPLEN: { + u_int16_t min, max; + min = ((ipfw_insn_u16 *)cmd)->ports[0]; + max = ((ipfw_insn_u16 *)cmd)->ports[1]; + if (max != min) + printf(" iplen %u-%u", min, max ); + else + printf(" iplen %u", min ); + } break; case O_IPOPT: @@ -2903,8 +2946,8 @@ break; case TOK_IPLEN: - NEED1("iplen requires length"); - fill_cmd(cmd, O_IPLEN, 0, strtoul(*av, NULL, 0)); + NEED1("iplen requires length or a range of lengths"); + fill_minmax((ipfw_insn_u16 *)cmd, O_IPLEN, *av); ac--; av++; break; --- sys/netinet/ip_fw.h.saved Mon May 19 22:46:48 2003 +++ sys/netinet/ip_fw.h Mon May 19 23:00:50 2003 @@ -71,7 +71,7 @@ O_VIA, /* none */ O_IPOPT, /* arg1 = 2*u8 bitmap */ - O_IPLEN, /* arg1 = len */ + O_IPLEN, /* u16 min, u16 max */ O_IPID, /* arg1 = id */ O_IPTOS, /* arg1 = id */ --- sys/netinet/ip_fw2.c.saved Mon May 19 22:46:58 2003 +++ sys/netinet/ip_fw2.c Mon May 19 23:10:03 2003 @@ -1686,7 +1686,10 @@ break; case O_IPLEN: - match = (hlen > 0 && cmd->arg1 == ip_len); + /* match if min <= iplen <= max */ + match = (hlen > 0 && + ((ipfw_insn_u16 *)cmd)->ports[0] <= ip_len && + ((ipfw_insn_u16 *)cmd)->ports[1] >= ip_len); break; case O_IPPRECEDENCE: @@ -2303,7 +2306,6 @@ case O_IN: case O_FRAG: case O_IPOPT: - case O_IPLEN: case O_IPID: case O_IPTOS: case O_IPPRECEDENCE: @@ -2314,6 +2316,11 @@ case O_TCPOPTS: case O_ESTAB: if (cmdlen != F_INSN_SIZE(ipfw_insn)) + goto bad_size; + break; + + case O_IPLEN: + if (cmdlen != F_INSN_SIZE(ipfw_insn_u16)) goto bad_size; break; --2fHTh5uZTiUOsy+g--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030521080400.GB21522>