[patch] pfctl: allow multiple tags in "tagged" statement

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

[patch] pfctl: allow multiple tags in "tagged" statement

Pierre-Yves Ritschard-2
Attached you'll find a patch that extends pfctl's syntax.
It allows pf rules such as this one:

pass in quick on re0 proto tcp all tag TCP
pass in quick on re0 proto udp all tag UDP
pass out quick on re0 all tagged { TCP, UDP }

This maps to:
 > sudo pfctl -s rules  
pass in quick on re0 proto tcp all tag TCP
pass in quick on re0 proto udp all tag UDP
pass out quick on re0 all tagged TCP
pass out quick on re0 all tagged UDP
pass out all

When using many tags it can help make the rules easier to read.
Only parse.y is modified.
Tested on sparc64, i386 and amd64, tell me what you think.
--- parse.y.orig Fri Feb  3 12:18:55 2006
+++ parse.y Fri Feb  3 12:44:17 2006
@@ -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;
 
@@ -275,7 +281,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 *,
@@ -385,6 +391,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;
@@ -455,6 +462,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
 %%
 
@@ -615,13 +623,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);
@@ -629,7 +630,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 {
@@ -649,7 +650,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 {
@@ -690,7 +691,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 {
@@ -802,7 +803,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, "");
  }
  ;
 
@@ -944,7 +945,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));
@@ -963,7 +964,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);
  }
@@ -1531,13 +1532,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;
@@ -1828,7 +1822,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, "");
  }
  ;
 
@@ -1914,9 +1908,9 @@
  | TAG string {
  filter_opts.tag = $2;
  }
- | not TAGGED string {
- filter_opts.match_tag = $3;
- filter_opts.match_tag_not = $1;
+ | not matchtag {
+ filter_opts.match_tags = $2;
+ filter_opts.match_tag_not = $1;
  }
  | PROBABILITY STRING {
  char *e;
@@ -1942,6 +1936,39 @@
  }
  ;
 
+matchtag : TAGGED matchtag_item {
+ $$ = $2;
+ }
+ | TAGGED '{' matchtag_list '}' {
+ $$ = $3;
+ filter_opts.match_tag_not = 0;
+ }
+ ;
+
+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; }
  ;
@@ -3367,7 +3394,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);
  }
  ;
@@ -4327,14 +4354,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;
@@ -4343,9 +4369,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;
@@ -4360,6 +4383,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 */
@@ -4395,7 +4419,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,
@@ -4484,7 +4510,7 @@
  added++;
  }
 
- ))))))))));
+ )))))))))));
 
  FREE_LIST(struct node_if, interfaces);
  FREE_LIST(struct node_proto, protos);
@@ -4497,6 +4523,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");

Reply | Threaded
Open this post in threaded view
|

Re: [patch] pfctl: allow multiple tags in "tagged" statement

Daniel Hartmeier
On Fri, Feb 03, 2006 at 01:07:41PM +0100, Pierre-Yves Ritschard wrote:

> When using many tags it can help make the rules easier to read.
> Only parse.y is modified.

Works for me, and it fits with how other items can be listed.

> @@ -1942,6 +1936,39 @@
>   }
>   ;
>  
> +matchtag : TAGGED matchtag_item {
> + $$ = $2;
> + }
> + | TAGGED '{' matchtag_list '}' {
> + $$ = $3;
> + filter_opts.match_tag_not = 0;

Not sure what this last line is supposed to achieve. It's not required,
as the 'not' flag is initialized in the upper production (afterwards!),
anyway, no?

I bet someone will soon write

  pass ! tagged { bad, evil }

with the intention of "pass anything not tagged bad OR evil", but
actually getting the expansion

  pass all ! tagged bad
  pass all ! tagged evil

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 ;)

Daniel

Reply | Threaded
Open this post in threaded view
|

Re: [patch] pfctl: allow multiple tags in "tagged" statement

Pierre-Yves Ritschard-2
* Daniel Hartmeier ([hidden email]) wrote:

> On Fri, Feb 03, 2006 at 01:07:41PM +0100, Pierre-Yves Ritschard wrote:
>
> > When using many tags it can help make the rules easier to read.
> > Only parse.y is modified.
>
> Works for me, and it fits with how other items can be listed.
>
> > @@ -1942,6 +1936,39 @@
> >   }
> >   ;
> >  
> > +matchtag : TAGGED matchtag_item {
> > + $$ = $2;
> > + }
> > + | TAGGED '{' matchtag_list '}' {
> > + $$ = $3;
> > + filter_opts.match_tag_not = 0;
>
> Not sure what this last line is supposed to achieve. It's not required,
> as the 'not' flag is initialized in the upper production (afterwards!),
> anyway, no?
>
> I bet someone will soon write
>
>   pass ! tagged { bad, evil }
>
> with the intention of "pass anything not tagged bad OR evil", but
> actually getting the expansion
>
>   pass all ! tagged bad
>   pass all ! tagged evil

Ok, I'll send a diff correcting this and a diff for the manpage as well.

Reply | Threaded
Open this post in threaded view
|

Re: [patch] pfctl: allow multiple tags in "tagged" statement

Pierre-Yves Ritschard-2
In reply to this post by Daniel Hartmeier
* Daniel Hartmeier ([hidden email]) 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.

Reply | Threaded
Open this post in threaded view
|

Re: [patch] pfctl: allow multiple tags in "tagged" statement

Pierre-Yves Ritschard-2
In reply to this post by Daniel Hartmeier
Of course actually including the diff is a better idea...

* Daniel Hartmeier ([hidden email]) 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"%"

Reply | Threaded
Open this post in threaded view
|

Re: [patch] pfctl: allow multiple tags in "tagged" statement

Daniel Hartmeier
Commited, thank you!

Daniel