One more (hopefully the last one) step in cleaning up the syntax,

following Julian's good suggestion: since you can specify any match
pattern as an option, rules now have the following format:

	[<proto> from <src> to <dst>] [options]

i.e. the first part is now entirely optional (and left there just
for compatibility with ipfw1 rulesets).

Add a "-c" flag to show/list rules in the compact form
(i.e. without the "ip from any to any" part) when possible.
The default is to include it so that scripts processing ipfw's
canonical output will still work.
Note that as part of this cleanup (and to remove ambiguity), MAC
fields now can only be specified in the options part.

Update the manpage to reflect the syntax.

Clarify the behaviour when a match is attempted on fields which
are not present in the packet, e.g. port numbers on non TCP/UDP
packets, and the "not" operator is specified. E.g.

	ipfw add allow not src-port 80

will match also ICMP packets because they do not have port numbers, so
"src-port 80" will fail and "not src-port 80" will succeed. For such
cases it is advised to insert further options to prevent undesired results
(e.g. in the case above, "ipfw add allow proto tcp not src-port 80").

We definitely need to rewrite the parser using lex and yacc!
This commit is contained in:
Luigi Rizzo 2002-08-19 12:36:54 +00:00
parent cb4abe67ef
commit 5a155b405e
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=102098
2 changed files with 102 additions and 61 deletions

View File

@ -14,11 +14,11 @@
.Nd IP firewall and traffic shaper control program .Nd IP firewall and traffic shaper control program
.Sh SYNOPSIS .Sh SYNOPSIS
.Nm .Nm
.Op Fl q .Op Fl cq
.Cm add .Cm add
.Ar rule .Ar rule
.Nm .Nm
.Op Fl adeftNS .Op Fl acdeftNS
.Brq Cm list | show .Brq Cm list | show
.Op Ar number ... .Op Ar number ...
.Nm .Nm
@ -219,6 +219,10 @@ While listing, show counter values.
The The
.Cm show .Cm show
command just implies this option. command just implies this option.
.It Fl c
When entering or showing rules, print them in compact form,
i.e. without the optional "ip from any to any" string
when this does not carry any additional information.
.It Fl d .It Fl d
While listing, show dynamic rules in addition to static ones. While listing, show dynamic rules in addition to static ones.
.It Fl e .It Fl e
@ -372,7 +376,12 @@ to match a MAC header when
.Nm .Nm
is called from is called from
.Cm ip_input() .Cm ip_input()
) the rule will simply not match. It is thus responsibility of ) the match pattern will not match. However, a
.Cm not
operator in front of such patterns will cause the pattern to
.Em always
match on those packets, which might cause undesired results.
It is thus responsibility of
the programmer, if necessary, to write a suitable ruleset to the programmer, if necessary, to write a suitable ruleset to
differentiate among the possible places. differentiate among the possible places.
.Cm skipto .Cm skipto
@ -648,12 +657,12 @@ specific source and destination addresses or ports,
protocol options, incoming or outgoing interfaces, etc.) protocol options, incoming or outgoing interfaces, etc.)
that the packet must match in order to be recognised. that the packet must match in order to be recognised.
In general, the patterns are connected by (implicit) In general, the patterns are connected by (implicit)
.Em and .Cm and
connectives -- i.e. all must match in order for the operators -- i.e. all must match in order for the
rule to match. rule to match.
Individual patterns can be prefixed by the Individual patterns can be prefixed by the
.Em not .Cm not
keyword to reverse the result of the match, as in operator to reverse the result of the match, as in
.Pp .Pp
.Dl "ipfw add 100 allow ip from not 1.2.3.4 to any" .Dl "ipfw add 100 allow ip from not 1.2.3.4 to any"
.Pp .Pp
@ -661,15 +670,16 @@ Additionally, sets of alternative match patterns (
.Em or-blocks .Em or-blocks
) can be constructed by putting the patterns in ) can be constructed by putting the patterns in
lists enclosed between parentheses ( ) or braces { }, and lists enclosed between parentheses ( ) or braces { }, and
using using the
.Cm or .Cm or
connectives as follows: operator as follows:
.Pp .Pp
.Dl "ipfw add 100 allow ip from { x or not y or z } to any" .Dl "ipfw add 100 allow ip from { x or not y or z } to any"
.Pp .Pp
Only one level of parentheses is allowed. Only one level of parentheses is allowed.
Beware that most shells have special meanings for parentheses Beware that most shells have special meanings for parentheses
or braces, so it is advisable to put a \\ in front of them. or braces, so it is advisable to put a backslash \\ in front of them
to prevent such interpretations.
.Pp .Pp
The body of a rule must in general include a source and destination The body of a rule must in general include a source and destination
addres specifier. addres specifier.
@ -678,35 +688,36 @@ The keyword
can be used in various places to specify that the content of can be used in various places to specify that the content of
a required field is irrelevant. a required field is irrelevant.
.Pp .Pp
The rule body format is one of the following: The rule body has the following format:
.Bd -ragged -offset indent .Bd -ragged -offset indent
.Ar proto .Op Ar proto Cm from Ar src Cm to Ar dst
.Cm from Ar src
.Cm to Ar dst
.Op Ar options .Op Ar options
.Pp
.Cm MAC Ar dst-mac src-mac Op Cm not
.Ar mac-type Op Ar options
.Ed .Ed
.Pp .Pp
where the second format allows you to specify MAC header fields The first part (protocol from src to dst) is for backward
instead of IPv4 header fields. compatibility with
Note that in practice both formats are equivalent, because the .Nm ipfw1 .
In
.Nm ipfw2
any match pattern (including MAC headers, IPv4 protocols,
addresses and ports) can be specified in the
.Ar options .Ar options
let you specify match patterns for all IP and MAC header fields. section.
.Pp .Pp
Rule fields have the following meaning: Rule fields have the following meaning:
.Bl -tag -width indent .Bl -tag -width indent
.It Ar proto .It Ar proto : protocol | Cm { Ar protocol Cm or ... }
An IPv4 protocol specified by number or name (for a complete An IPv4 protocol (or an
list see .Em or-block
with multiple protocols) specified by number or name
(for a complete list see
.Pa /etc/protocols ) . .Pa /etc/protocols ) .
The The
.Cm ip .Cm ip
or or
.Cm all .Cm all
keywords mean any protocol will match. keywords mean any protocol will match.
.It Ar src No and Ar dst : ip-address | { ip-address Cm or ... } Op Ar ports .It Ar src No and Ar dst : ip-address | Cm { Ar ip-address Cm or ... } Op Ar ports
A single A single
.Ar ip-address .Ar ip-address
, or an , or an
@ -786,7 +797,9 @@ A backslash
.Pq Ql \e .Pq Ql \e
can be used to escape the dash can be used to escape the dash
.Pq Ql - .Pq Ql -
character in a service name: character in a service name (from a shell, the backslash must be
typed twice to avoid that the shell itself uses it as an escape
character).
.Pp .Pp
.Dl "ipfw add count tcp from any ftp\e\e-data-ftp to any" .Dl "ipfw add count tcp from any ftp\e\e-data-ftp to any"
.Pp .Pp
@ -796,28 +809,6 @@ specifications.
See the See the
.Cm frag .Cm frag
option for details on matching fragmented packets. option for details on matching fragmented packets.
.It Ar dst-mac, src-mac
Destination and source MAC addresses, specified as
groups of hex digits separated by commas, and optionally
followed by a mask indicating how many bits are significant:
.Pp
.Dl "ipfw add allow MAC 10:20:30:40:50:60/30 any any
.Pp
Note that the order of MAC addresses (destination first,
source second) is
the same as on the wire, but the opposite of the one used for
IP addresses.
.It Ar mac-type
The value of the Ethernet Type field, specified in the same way as
.Cm port numbers
(i.e. one or more comma-separated single values or ranges).
You can use symbolic names for known values such as
.Em vlan , ipv4, ipv6 .
The values can be enter as decimal or hexadecimal, but they
are always printed as hexadecimal (unless the
.Cm -N
option is used, in which case symbolic resolution will be
attempted).
.El .El
.Ss RULE OPTIONS (MATCH PATTERNS) .Ss RULE OPTIONS (MATCH PATTERNS)
Additional match patterns can be used within Additional match patterns can be used within
@ -974,12 +965,36 @@ One or more
of source and destination addresses and ports can be of source and destination addresses and ports can be
specified. specified.
.It Cm { MAC | mac } Ar dst-mac src-mac .It Cm { MAC | mac } Ar dst-mac src-mac
Match packets with a given dst-mac and src-mac addresses, specified Match packets with a given
in one of the forms described earlier. .Ar dst-mac
and
Ar src-mac
addresses, specified as the
.Cm any
keyword (matching any MAC address), or six groups of hex digits
separated by commas,
and optionally followed by a mask indicating how many bits are
significant, as in
.Pp
.Dl "MAC 10:20:30:40:50:60/33 any"
.Pp
Note that the order of MAC addresses (destination first,
source second) is
the same as on the wire, but the opposite of the one used for
IP addresses.
.It Cm mac-type Ar mac-type .It Cm mac-type Ar mac-type
Matches packets whose Matches packets whose Ethernet Type field
.Ar mac-type
corresponds to one of those specified as argument. corresponds to one of those specified as argument.
.Ar mac-type
is specified in the same way as
.Cm port numbers
(i.e. one or more comma-separated single values or ranges).
You can use symbolic names for known values such as
.Em vlan , ipv4, ipv6 .
Values can be enter as decimal or hexadecimal (if prefixed by 0x),
and they are always printed as hexadecimal (unless the
.Cm -N
option is used, in which case symbolic resolution will be attempted).
.It Cm proto Ar protocol .It Cm proto Ar protocol
Matches packets with the corresponding IPv4 protocol. Matches packets with the corresponding IPv4 protocol.
.It Cm recv | xmit | via Brq Ar ifX | Ar if Ns Cm * | Ar ipno | Ar any .It Cm recv | xmit | via Brq Ar ifX | Ar if Ns Cm * | Ar ipno | Ar any
@ -1614,8 +1629,17 @@ To achieve the same behaviour as
.Nm ipfw1 .Nm ipfw1
you can use the following as the very first rule in your ruleset: you can use the following as the very first rule in your ruleset:
.Pp .Pp
.Dl "ipfw add 1 allow MAC any any not ip" .Dl "ipfw add 1 allow layer2 not mac-type ip"
.Pp .Pp
The
.Cm layer2
options might seem redundant, but it is necessary -- packets
passed to the firewall from layer3 will not have a MAC header,
so the
.Cm mac-type ip
pattern will always fail on them, and the
.Cm not
operator will make this rule into a pass-all.
.It Address sets .It Address sets
.Nm ipfw1 .Nm ipfw1
does not supports address sets (those in the form does not supports address sets (those in the form
@ -1684,11 +1708,16 @@ has no effect there.
.It Options .It Options
The following options are not supported in The following options are not supported in
.Nm ipfw1 .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
.Nm ipfw1
(RELENG_4) (RELENG_4)
rules: rules:
.Pp .Pp
.Cm layer2, ipid, iplen, ipprecedence, iptos, ipttl, .Cm ipid, iplen, ipprecedence, iptos, ipttl,
.Cm ipversion, tcpack, tcpseq, tcpwin . .Cm ipversion, .Cm tcpack, tcpseq, tcpwin .
.It Dummynet options .It Dummynet options
The following option for The following option for
.Nm dummynet .Nm dummynet

View File

@ -65,6 +65,7 @@ int s, /* main RAW socket */
do_sort, /* field to sort results (0 = no) */ do_sort, /* field to sort results (0 = no) */
do_dynamic, /* display dynamic rules */ do_dynamic, /* display dynamic rules */
do_expired, /* display expired dynamic rules */ do_expired, /* display expired dynamic rules */
do_compact, /* show rules in compact mode */
show_sets, /* display rule sets */ show_sets, /* display rule sets */
verbose; verbose;
@ -931,7 +932,8 @@ show_ipfw(struct ip_fw *rule)
* then print the body. * then print the body.
*/ */
if (rule->_pad & 1) { /* empty rules before options */ if (rule->_pad & 1) { /* empty rules before options */
printf (" all from any to any"); if (!do_compact)
printf(" ip from any to any");
flags |= HAVE_IP | HAVE_OPTIONS; flags |= HAVE_IP | HAVE_OPTIONS;
} }
@ -2325,7 +2327,7 @@ add_mac(ipfw_insn *cmd, int ac, char *av[])
ipfw_insn_mac *mac; ipfw_insn_mac *mac;
if (ac < 2) if (ac < 2)
errx(EX_DATAERR, "MAC dst src [not] type"); errx(EX_DATAERR, "MAC dst src");
cmd->opcode = O_MACADDR2; cmd->opcode = O_MACADDR2;
cmd->len = (cmd->len & (F_NOT | F_OR)) | F_INSN_SIZE(ipfw_insn_mac); cmd->len = (cmd->len & (F_NOT | F_OR)) | F_INSN_SIZE(ipfw_insn_mac);
@ -2362,7 +2364,7 @@ add_proto(ipfw_insn *cmd, char *av)
else if ((pe = getprotobyname(av)) != NULL) else if ((pe = getprotobyname(av)) != NULL)
proto = pe->p_proto; proto = pe->p_proto;
else else
errx(EX_DATAERR, "invalid protocol ``%s''", av); return NULL;
if (proto != IPPROTO_IP) if (proto != IPPROTO_IP)
fill_cmd(cmd, O_PROTO, 0, proto); fill_cmd(cmd, O_PROTO, 0, proto);
return cmd; return cmd;
@ -2673,6 +2675,8 @@ add(int ac, char *av[])
CLOSE_PAR; CLOSE_PAR;
first_cmd = cmd; first_cmd = cmd;
#if 0
/* /*
* MAC addresses, optional. * MAC addresses, optional.
* If we have this, we skip the part "proto from src to dst" * If we have this, we skip the part "proto from src to dst"
@ -2693,6 +2697,7 @@ add(int ac, char *av[])
ac--; av++; /* any or mac-type */ ac--; av++; /* any or mac-type */
goto read_options; goto read_options;
} }
#endif
/* /*
* protocol, mandatory * protocol, mandatory
@ -2709,7 +2714,10 @@ add(int ac, char *av[])
prev = cmd; prev = cmd;
cmd = next_cmd(cmd); cmd = next_cmd(cmd);
} }
} } else if (first_cmd != cmd) {
errx(EX_DATAERR, "invalid protocol ``%s''", av);
} else
goto read_options;
OR_BLOCK(get_proto); OR_BLOCK(get_proto);
/* /*
@ -3040,7 +3048,8 @@ add(int ac, char *av[])
if (add_proto(cmd, *av)) { if (add_proto(cmd, *av)) {
proto = cmd->arg1; proto = cmd->arg1;
ac--; av++; ac--; av++;
} } else
errx(EX_DATAERR, "invalid protocol ``%s''", av);
break; break;
case TOK_SRCIP: case TOK_SRCIP:
@ -3291,7 +3300,7 @@ ipfw_main(int ac, char **av)
do_force = !isatty(STDIN_FILENO); do_force = !isatty(STDIN_FILENO);
optind = optreset = 1; optind = optreset = 1;
while ((ch = getopt(ac, av, "hs:adefNqStv")) != -1) while ((ch = getopt(ac, av, "hs:acdefNqStv")) != -1)
switch (ch) { switch (ch) {
case 'h': /* help */ case 'h': /* help */
help(); help();
@ -3303,6 +3312,9 @@ ipfw_main(int ac, char **av)
case 'a': case 'a':
do_acct = 1; do_acct = 1;
break; break;
case 'c':
do_compact = 1;
break;
case 'd': case 'd':
do_dynamic = 1; do_dynamic = 1;
break; break;