Add support for multiple values and ranges for the "iplen", "ipttl",
"ipid" options. This feature has been requested by several users. On passing, fix some minor bugs in the parser. This change is fully backward compatible so if you have an old /sbin/ipfw and a new kernel you are not in trouble (but you need to update /sbin/ipfw if you want to use the new features). Document the changes in the manpage. Now you can write things like ipfw add skipto 1000 iplen 0-500 which some people were asking to give preferential treatment to short packets. The 'MFC after' is just set as a reminder, because I still need to merge the Alpha/Sparc64 fixes for ipfw2 (which unfortunately change the size of certain kernel structures; not that it matters a lot since ipfw2 is entirely optional and not the default...) PR: bin/48015 MFC after: 1 week
This commit is contained in:
parent
b2922be00d
commit
52ba467ddf
@ -707,7 +707,7 @@ The
|
||||
or
|
||||
.Cm all
|
||||
keywords mean any protocol will match.
|
||||
.It Ar src No and Ar dst : ip-address | Cm { Ar ip-address Cm or ... } Op Ar ports
|
||||
.It Ar src No and Ar dst : ip-address | Cm { Ar ip-address Cm or ... } Op Oo Cm not Oc Ar ports
|
||||
A single
|
||||
.Ar ip-address
|
||||
, or an
|
||||
@ -776,7 +776,7 @@ masks, and resort to the
|
||||
format for contiguous masks, which is more compact and less
|
||||
error-prone.
|
||||
.El
|
||||
.It Ar ports : Oo Cm not Oc Bro Ar port | port Ns \&- Ns Ar port Ns Brc Op , Ns Ar ...
|
||||
.It Ar ports : Bro Ar port | port Ns \&- Ns Ar port Ns Brc Op , Ns Ar ports
|
||||
For protocols which support port numbers (such as TCP and UDP), optional
|
||||
.Cm ports
|
||||
may be specified as one or more ports or port ranges, separated
|
||||
@ -827,10 +827,10 @@ The following match patterns can be used (listed in alphabetical order):
|
||||
.Bl -tag -width indent
|
||||
.It Cm bridged
|
||||
Matches only bridged packets.
|
||||
.It Cm dst-ip Ar ip address
|
||||
.It Cm dst-ip Ar ip-address
|
||||
Matches IP packets whose destination IP is one of the address(es)
|
||||
specified as argument.
|
||||
.It Cm dst-port Ar source ports
|
||||
.It Cm dst-port Ar ports
|
||||
Matches IP packets whose destination port is one of the port(s)
|
||||
specified as argument.
|
||||
.It Cm established
|
||||
@ -892,15 +892,21 @@ are mutually exclusive (in fact,
|
||||
.Cm out
|
||||
is implemented as
|
||||
.Cm not in Ns No ).
|
||||
.It Cm ipid Ar id
|
||||
.It Cm ipid Ar id-list
|
||||
Matches IP packets whose
|
||||
.Cm ip_id
|
||||
field has value
|
||||
.Ar id .
|
||||
.It Cm iplen Ar len
|
||||
field has value included in
|
||||
.Ar id-list ,
|
||||
which is either a single value or a list of values or ranges
|
||||
specified in the same way as
|
||||
.Ar ports .
|
||||
.It Cm iplen Ar len-list
|
||||
Matches IP packets whose total length, including header and data, is
|
||||
.Ar len
|
||||
bytes.
|
||||
in the set
|
||||
.Ar len-list ,
|
||||
which is either a single value or a list of values or ranges
|
||||
specified in the same way as
|
||||
.Ar ports .
|
||||
.It Cm ipoptions Ar spec
|
||||
Matches packets whose IP header contains the comma separated list of
|
||||
options specified in
|
||||
@ -942,9 +948,12 @@ The supported IP types of service are:
|
||||
The absence of a particular type may be denoted
|
||||
with a
|
||||
.Ql \&! .
|
||||
.It Cm ipttl Ar ttl
|
||||
Matches IP packets whose time to live is
|
||||
.Ar ttl .
|
||||
.It Cm ipttl Ar ttl-list
|
||||
Matches IP packets whose time to live is included in
|
||||
.Ar ttl-list ,
|
||||
which is either a single value or a list of values or ranges
|
||||
specified in the same way as
|
||||
.Ar ports .
|
||||
.It Cm ipversion Ar ver
|
||||
Matches IP packets whose IP version field is
|
||||
.Ar ver .
|
||||
@ -1762,15 +1771,20 @@ The sysctl variable
|
||||
.Em net.link.ether.ipfw
|
||||
has no effect there.
|
||||
.It Options
|
||||
The following options are not supported in
|
||||
.Nm ipfw1
|
||||
In
|
||||
.Nm ipfw1 ,
|
||||
the following options only accept a single value as an argument:
|
||||
.Pp
|
||||
.Cm ipid, iplen, ipttl
|
||||
.Pp
|
||||
The following options are not implemented by
|
||||
.Nm ipfw1 :
|
||||
.Pp
|
||||
.Cm dst-ip, dst-port, layer2, mac, mac-type, src-ip, src-port.
|
||||
.Pp
|
||||
Additionally, the following options are not supported in
|
||||
Additionally, the RELENG_4 version of
|
||||
.Nm ipfw1
|
||||
(RELENG_4)
|
||||
rules:
|
||||
does not implement the following options:
|
||||
.Pp
|
||||
.Cm ipid, iplen, ipprecedence, iptos, ipttl,
|
||||
.Cm ipversion, tcpack, tcpseq, tcpwin .
|
||||
|
@ -418,13 +418,37 @@ print_newports(ipfw_insn_u16 *cmd, int proto, int opcode)
|
||||
{
|
||||
u_int16_t *p = cmd->ports;
|
||||
int i;
|
||||
char *sep= " ";
|
||||
char *sep;
|
||||
|
||||
if (cmd->o.len & F_NOT)
|
||||
printf(" not");
|
||||
if (opcode != 0)
|
||||
printf ("%s", opcode == O_MAC_TYPE ? " mac-type" :
|
||||
(opcode == O_IP_DSTPORT ? " dst-port" : " src-port"));
|
||||
if (opcode != 0) {
|
||||
switch (opcode) {
|
||||
case O_IP_DSTPORT:
|
||||
sep = "dst-port";
|
||||
break;
|
||||
case O_IP_SRCPORT:
|
||||
sep = "src-port";
|
||||
break;
|
||||
case O_IPID:
|
||||
sep = "ipid";
|
||||
break;
|
||||
case O_IPLEN:
|
||||
sep = "iplen";
|
||||
break;
|
||||
case O_IPTTL:
|
||||
sep = "ipttl";
|
||||
break;
|
||||
case O_MAC_TYPE:
|
||||
sep = "mac-type";
|
||||
break;
|
||||
default:
|
||||
sep = "???";
|
||||
break;
|
||||
}
|
||||
printf (" %s", sep);
|
||||
}
|
||||
sep = " ";
|
||||
for (i = F_LEN((ipfw_insn *)cmd) - 1; i > 0; i--, p += 2) {
|
||||
printf(sep);
|
||||
print_port(proto, p[0]);
|
||||
@ -1096,11 +1120,19 @@ show_ipfw(struct ip_fw *rule, int pcwidth, int bcwidth)
|
||||
break;
|
||||
|
||||
case O_IPID:
|
||||
printf(" ipid %u", cmd->arg1 );
|
||||
if (F_LEN(cmd) == 1)
|
||||
printf(" ipid %u", cmd->arg1 );
|
||||
else
|
||||
print_newports((ipfw_insn_u16 *)cmd, 0,
|
||||
O_IPID);
|
||||
break;
|
||||
|
||||
case O_IPTTL:
|
||||
printf(" ipttl %u", cmd->arg1 );
|
||||
if (F_LEN(cmd) == 1)
|
||||
printf(" ipttl %u", cmd->arg1 );
|
||||
else
|
||||
print_newports((ipfw_insn_u16 *)cmd, 0,
|
||||
O_IPTTL);
|
||||
break;
|
||||
|
||||
case O_IPVER:
|
||||
@ -1112,7 +1144,11 @@ show_ipfw(struct ip_fw *rule, int pcwidth, int bcwidth)
|
||||
break;
|
||||
|
||||
case O_IPLEN:
|
||||
printf(" iplen %u", cmd->arg1 );
|
||||
if (F_LEN(cmd) == 1)
|
||||
printf(" iplen %u", cmd->arg1 );
|
||||
else
|
||||
print_newports((ipfw_insn_u16 *)cmd, 0,
|
||||
O_IPLEN);
|
||||
break;
|
||||
|
||||
case O_IPOPT:
|
||||
@ -2971,19 +3007,31 @@ add(int ac, char *av[])
|
||||
|
||||
case TOK_IPTTL:
|
||||
NEED1("ipttl requires TTL");
|
||||
fill_cmd(cmd, O_IPTTL, 0, strtoul(*av, NULL, 0));
|
||||
if (strpbrk(*av, "-,")) {
|
||||
if (!add_ports(cmd, *av, 0, O_IPTTL))
|
||||
errx(EX_DATAERR, "invalid ipttl %s", *av);
|
||||
} else
|
||||
fill_cmd(cmd, O_IPTTL, 0, strtoul(*av, NULL, 0));
|
||||
ac--; av++;
|
||||
break;
|
||||
|
||||
case TOK_IPID:
|
||||
NEED1("ipid requires length");
|
||||
fill_cmd(cmd, O_IPID, 0, strtoul(*av, NULL, 0));
|
||||
NEED1("ipid requires id");
|
||||
if (strpbrk(*av, "-,")) {
|
||||
if (!add_ports(cmd, *av, 0, O_IPID))
|
||||
errx(EX_DATAERR, "invalid ipid %s", *av);
|
||||
} else
|
||||
fill_cmd(cmd, O_IPID, 0, strtoul(*av, NULL, 0));
|
||||
ac--; av++;
|
||||
break;
|
||||
|
||||
case TOK_IPLEN:
|
||||
NEED1("iplen requires length");
|
||||
fill_cmd(cmd, O_IPLEN, 0, strtoul(*av, NULL, 0));
|
||||
if (strpbrk(*av, "-,")) {
|
||||
if (!add_ports(cmd, *av, 0, O_IPLEN))
|
||||
errx(EX_DATAERR, "invalid ip len %s", *av);
|
||||
} else
|
||||
fill_cmd(cmd, O_IPLEN, 0, strtoul(*av, NULL, 0));
|
||||
ac--; av++;
|
||||
break;
|
||||
|
||||
|
@ -1730,17 +1730,30 @@ ipfw_chk(struct ip_fw_args *args)
|
||||
match = (hlen > 0 && cmd->arg1 == ip->ip_v);
|
||||
break;
|
||||
|
||||
case O_IPTTL:
|
||||
match = (hlen > 0 && cmd->arg1 == ip->ip_ttl);
|
||||
break;
|
||||
|
||||
case O_IPID:
|
||||
match = (hlen > 0 &&
|
||||
cmd->arg1 == ntohs(ip->ip_id));
|
||||
break;
|
||||
|
||||
case O_IPLEN:
|
||||
match = (hlen > 0 && cmd->arg1 == ip_len);
|
||||
case O_IPTTL:
|
||||
if (hlen > 0) { /* only for IP packets */
|
||||
uint16_t x;
|
||||
uint16_t *p;
|
||||
int i;
|
||||
|
||||
if (cmd->opcode == O_IPLEN)
|
||||
x = ip_len;
|
||||
else if (cmd->opcode == O_IPTTL)
|
||||
x = ip->ip_ttl;
|
||||
else /* must be IPID */
|
||||
x = ntohs(ip->ip_id);
|
||||
if (cmdlen == 1) {
|
||||
match = (cmd->arg1 == x);
|
||||
break;
|
||||
}
|
||||
/* otherwise we have ranges */
|
||||
p = ((ipfw_insn_u16 *)cmd)->ports;
|
||||
i = cmdlen - 1;
|
||||
for (; !match && i>0; i--, p += 2)
|
||||
match = (x >= p[0] && x <= p[1]);
|
||||
}
|
||||
break;
|
||||
|
||||
case O_IPPRECEDENCE:
|
||||
@ -2371,11 +2384,8 @@ check_ipfw_struct(struct ip_fw *rule, int size)
|
||||
case O_IN:
|
||||
case O_FRAG:
|
||||
case O_IPOPT:
|
||||
case O_IPLEN:
|
||||
case O_IPID:
|
||||
case O_IPTOS:
|
||||
case O_IPPRECEDENCE:
|
||||
case O_IPTTL:
|
||||
case O_IPVER:
|
||||
case O_TCPWIN:
|
||||
case O_TCPFLAGS:
|
||||
@ -2440,6 +2450,13 @@ check_ipfw_struct(struct ip_fw *rule, int size)
|
||||
goto bad_size;
|
||||
break;
|
||||
|
||||
case O_IPID:
|
||||
case O_IPTTL:
|
||||
case O_IPLEN:
|
||||
if (cmdlen < 1 || cmdlen > 31)
|
||||
goto bad_size;
|
||||
break;
|
||||
|
||||
case O_MAC_TYPE:
|
||||
case O_IP_SRCPORT:
|
||||
case O_IP_DSTPORT: /* XXX artificial limit, 30 port pairs */
|
||||
|
Loading…
Reference in New Issue
Block a user