This is a discussion on Re: [patch] pfctl: allow multiple tags in "tagged" statement within the lucky.openbsd.tech forums, part of the OpenBSD category; --> Of course actually including the diff is a better idea... * Daniel Hartmeier (daniel@benzedrine.cx) wrote: > > which matches ...
| |||||||
| FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read |
| ||||
| Of course actually including the diff is a better idea... * Daniel Hartmeier (daniel@benzedrine.cx) wrote: > > which matches every packet. So you might want to add > > | not matchtag { > filter_opts.match_tags = $2; > filter_opts.match_tag_not = $1; > if ($1 && $2->tail != $2) { > yyerror("tag list negation matches all"); > YYERROR; > } > } > > or at least explain it in the man page Hi, sorry for the delay, I broke my arm. Good point regarding negation, I fixed it and also modified the man page anyway to reflect the code change. If it is deemed necessary similar changes can be done for nat-rules and rdr-rules. Index: sbin/pfctl/parse.y ================================================== ================= RCS file: /space/release/cvs/src/sbin/pfctl/parse.y,v retrieving revision 1.496 diff -u -r1.496 parse.y --- sbin/pfctl/parse.y 6 Apr 2006 21:54:56 -0000 1.496 +++ sbin/pfctl/parse.y 18 Apr 2006 13:39:05 -0000 @@ -117,6 +117,12 @@ struct node_icmp *tail; }; +struct node_matchtag { + char tagname[PF_TAG_NAME_SIZE]; + struct node_matchtag *next; + struct node_matchtag *tail; +}; + enum { PF_STATE_OPT_MAX, PF_STATE_OPT_NOSYNC, PF_STATE_OPT_SRCTRACK, PF_STATE_OPT_MAX_SRC_STATES, PF_STATE_OPT_MAX_SRC_CONN, PF_STATE_OPT_MAX_SRC_CONN_RATE, PF_STATE_OPT_MAX_SRC_NODES, @@ -197,7 +203,7 @@ char *label; struct node_qassign queues; char *tag; - char *match_tag; + struct node_matchtag *match_tags; u_int8_t match_tag_not; } filter_opts; @@ -276,7 +282,7 @@ struct node_proto *, struct node_os*, struct node_host *, struct node_port *, struct node_host *, struct node_port *, struct node_uid *, struct node_gid *, struct node_icmp *, - const char *); + struct node_matchtag *, const char *); int expand_altq(struct pf_altq *, struct node_if *, struct node_queue *, struct node_queue_bw bwspec, struct node_queue_opt *); int expand_queue(struct pf_altq *, struct node_if *, struct node_queue *, @@ -386,6 +392,7 @@ struct table_opts table_opts; struct pool_opts pool_opts; struct node_hfsc_opts hfsc_opts; + struct node_matchtag *matchtag_opts; } v; int lineno; } YYSTYPE; @@ -456,6 +463,7 @@ %type <v.scrub_opts> scrub_opts scrub_opt scrub_opts_l %type <v.table_opts> table_opts table_opt table_opts_l %type <v.pool_opts> pool_opts pool_opt pool_opts_l +%type <v.matchtag_opts> matchtag matchtag_list matchtag_item %type <v.tagged> tagged %% @@ -616,13 +624,6 @@ r.af = $5; r.prob = $8.prob; - if ($8.match_tag) - if (strlcpy(r.match_tagname, $8.match_tag, - PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) { - yyerror("tag too long, max %u chars", - PF_TAG_NAME_SIZE - 1); - YYERROR; - } r.match_tag_not = $8.match_tag_not; decide_address_family($7.src.host, &r.af); @@ -630,7 +631,7 @@ expand_rule(&r, $4, NULL, $6, $7.src_os, $7.src.host, $7.src.port, $7.dst.host, $7.dst.port, - 0, 0, 0, $2); + 0, 0, 0, $8.match_tags, $2); free($2); } | NATANCHOR string interface af proto fromto { @@ -650,7 +651,7 @@ expand_rule(&r, $3, NULL, $5, $6.src_os, $6.src.host, $6.src.port, $6.dst.host, $6.dst.port, - 0, 0, 0, $2); + 0, 0, 0, 0, $2); free($2); } | RDRANCHOR string interface af proto fromto { @@ -691,7 +692,7 @@ expand_rule(&r, $3, NULL, $5, $6.src_os, $6.src.host, $6.src.port, $6.dst.host, $6.dst.port, - 0, 0, 0, $2); + 0, 0, 0, 0, $2); free($2); } | BINATANCHOR string interface af proto fromto { @@ -803,7 +804,7 @@ expand_rule(&r, $4, NULL, $6, $7.src_os, $7.src.host, $7.src.port, $7.dst.host, $7.dst.port, - NULL, NULL, NULL, ""); + NULL, NULL, NULL, NULL, ""); } ; @@ -945,7 +946,7 @@ if (h != NULL) expand_rule(&r, j, NULL, NULL, NULL, h, NULL, NULL, NULL, NULL, NULL, - NULL, ""); + NULL, NULL, ""); if ((i->ifa_flags & IFF_LOOPBACK) == 0) { bzero(&r, sizeof(r)); @@ -964,7 +965,7 @@ if (h != NULL) expand_rule(&r, NULL, NULL, NULL, NULL, h, NULL, NULL, - NULL, NULL, NULL, NULL, ""); + NULL, NULL, NULL, NULL, NULL, ""); } else free(hh); } @@ -1536,13 +1537,6 @@ PF_TAG_NAME_SIZE - 1); YYERROR; } - if ($9.match_tag) - if (strlcpy(r.match_tagname, $9.match_tag, - PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) { - yyerror("tag too long, max %u chars", - PF_TAG_NAME_SIZE - 1); - YYERROR; - } r.match_tag_not = $9.match_tag_not; if (rule_label(&r, $9.label)) YYERROR; @@ -1833,7 +1827,7 @@ expand_rule(&r, $4, $5.host, $7, $8.src_os, $8.src.host, $8.src.port, $8.dst.host, $8.dst.port, - $9.uid, $9.gid, $9.icmpspec, ""); + $9.uid, $9.gid, $9.icmpspec, $9.match_tags, ""); } ; @@ -1919,9 +1913,13 @@ | TAG string { filter_opts.tag = $2; } - | not TAGGED string { - filter_opts.match_tag = $3; + | not matchtag { + filter_opts.match_tags = $2; filter_opts.match_tag_not = $1; + if ($1 && ($2 != $2->tail)) { + yyerror("cannot negate tag list"); + YYERROR; + } } | PROBABILITY STRING { char *e; @@ -1947,6 +1945,38 @@ } ; +matchtag : TAGGED matchtag_item { + $$ = $2; + } + | TAGGED '{' matchtag_list '}' { + $$ = $3; + } + ; + +matchtag_list : matchtag_item { $$ = $1; } + | matchtag_list comma matchtag_item { + $1->tail->next = $3; + $1->tail = $3; + $$ = $1; + } + ; + +matchtag_item : STRING { + $$ = calloc(1, sizeof (struct node_matchtag)); + if ($$ == NULL) + err(1, "matchtag_item: calloc"); + if ((strlcpy($$->tagname,$1,PF_TAG_NAME_SIZE)) >= + PF_TAG_NAME_SIZE) { + yyerror("tag too long, max %u chars", + PF_TAG_NAME_SIZE - 1); + YYERROR; + } + free($1); + $$->next = NULL; + $$->tail = $$; + } + ; + action : PASS { $$.b1 = PF_PASS; $$.b2 = $$.w = 0; } | BLOCK blockspec { $$ = $2; $$.b1 = PF_DROP; } ; @@ -3385,7 +3415,7 @@ expand_rule(&r, $2, $8 == NULL ? NULL : $8->host, $4, $5.src_os, $5.src.host, $5.src.port, $5.dst.host, - $5.dst.port, 0, 0, 0, ""); + $5.dst.port, 0, 0, 0, 0, ""); free($8); } ; @@ -4362,14 +4392,13 @@ struct node_host *src_hosts, struct node_port *src_ports, struct node_host *dst_hosts, struct node_port *dst_ports, struct node_uid *uids, struct node_gid *gids, struct node_icmp *icmp_types, - const char *anchor_call) + struct node_matchtag *match_tags, const char *anchor_call) { sa_family_t af = r->af; int added = 0, error = 0; char ifname[IF_NAMESIZE]; char label[PF_RULE_LABEL_SIZE]; char tagname[PF_TAG_NAME_SIZE]; - char match_tagname[PF_TAG_NAME_SIZE]; struct pf_pooladdr *pa; struct node_host *h; u_int8_t flags, flagset, keep_state; @@ -4378,9 +4407,6 @@ errx(1, "expand_rule: strlcpy"); if (strlcpy(tagname, r->tagname, sizeof(tagname)) >= sizeof(tagname)) errx(1, "expand_rule: strlcpy"); - if (strlcpy(match_tagname, r->match_tagname, sizeof(match_tagname)) >= - sizeof(match_tagname)) - errx(1, "expand_rule: strlcpy"); flags = r->flags; flagset = r->flagset; keep_state = r->keep_state; @@ -4395,6 +4421,7 @@ LOOP_THROUGH(struct node_port, dst_port, dst_ports, LOOP_THROUGH(struct node_uid, uid, uids, LOOP_THROUGH(struct node_gid, gid, gids, + LOOP_THROUGH(struct node_matchtag, match_tag, match_tags, r->af = af; /* for link-local IPv6 address, interface must match up */ @@ -4430,7 +4457,9 @@ if (strlcpy(r->tagname, tagname, sizeof(r->tagname)) >= sizeof(r->tagname)) errx(1, "expand_rule: strlcpy"); - if (strlcpy(r->match_tagname, match_tagname, + if (!match_tag->tagname) + errx(1, "expand_rule: no tagname"); + if (strlcpy(r->match_tagname, match_tag->tagname, sizeof(r->match_tagname)) >= sizeof(r->match_tagname)) errx(1, "expand_rule: strlcpy"); expand_label(r->label, PF_RULE_LABEL_SIZE, r->ifname, r->af, @@ -4519,7 +4548,7 @@ added++; } - )))))))))); + ))))))))))); FREE_LIST(struct node_if, interfaces); FREE_LIST(struct node_proto, protos); @@ -4532,6 +4561,7 @@ FREE_LIST(struct node_gid, gids); FREE_LIST(struct node_icmp, icmp_types); FREE_LIST(struct node_host, rpool_hosts); + FREE_LIST(struct node_matchtag, match_tags); if (!added) yyerror("rule expands to no valid combination"); Index: share/man/man5/pf.conf.5 ================================================== ================= RCS file: /space/release/cvs/src/share/man/man5/pf.conf.5,v retrieving revision 1.342 diff -u -r1.342 pf.conf.5 --- share/man/man5/pf.conf.5 14 Mar 2006 11:09:44 -0000 1.342 +++ share/man/man5/pf.conf.5 27 Apr 2006 12:24:36 -0000 @@ -1584,15 +1584,16 @@ .Ar binat rules in addition to filter rules. Tags take the same macros as labels (see above). -.It Ar tagged <string> +.It Ar tagged <string> | { <string>, <string> } Used with filter or translation rules to specify that packets must already -be tagged with the given tag in order to match the rule. -Inverse tag matching can also be done +be tagged with any of the given tags in order to match the rule. +If only one tag is given, inverse tag matching can also be done by specifying the .Cm !\& operator before the .Ar tagged -keyword. +keyword. A list of tags cannot be negated as it would expand to a useless +rule. .It Ar probability <number> A probability attribute can be attached to a rule, with a value set between 0 and 1, bounds not included. @@ -2654,6 +2655,7 @@ "max-mss" number | "random-id" | "reassemble tcp" | fragmentation | "allow-opts" | "label" string | "tag" string | [ ! ] "tagged" string | + "tagged" "{" string [ [ "," ] string ] "}" | "queue" ( string | "(" string [ [ "," ] string ] ")" ) | "probability" number"%" |