It is hard to limit pf rules to specific rdomains. This diff extends the
syntax so that it is possible to specify an rdomain on pass and block
rules similar to the way a interface is specified.
So it is possible to write now rules like:
block in on rdomain 0
or a bit more complex:
pass out on rdomain 1 proto {tcp, udp} to port domain rtable 0 nat-to (egress)

-- 
:wq Claudio

Index: share/man/man5/pf.conf.5
===================================================================
RCS file: /cvs/src/share/man/man5/pf.conf.5,v
retrieving revision 1.490
diff -u -p -r1.490 pf.conf.5
--- share/man/man5/pf.conf.5    25 Mar 2011 11:09:38 -0000      1.490
+++ share/man/man5/pf.conf.5    3 Apr 2011 11:57:19 -0000
@@ -267,6 +267,9 @@ see the
 .Ic group
 keyword in
 .Xr ifconfig 8 .
+.It Ar on Ar rdomain Aq Ar number
+This rule applies only to packets coming in on, or going out through, this
+particular routing domain.
 .It Aq Ar af
 This rule applies only to packets of this address family.
 Supported values are
@@ -2653,7 +2656,8 @@ option         = "set" ( [ "timeout" ( t
 
 pf-rule        = action [ ( "in" | "out" ) ]
                  [ "log" [ "(" logopts ")"] ] [ "quick" ]
-                 [ "on" ifspec ] [ af ] [ protospec ] hosts [ filteropts ]
+                 [ "on" ( ifspec | "rdomain" number ) ] [ af ]
+                 [ protospec ] hosts [ filteropts ]
 
 logopts        = logopt [ [ "," ] logopts ]
 logopt         = "all" | "matches" | "user" | "to" interface-name
Index: sys/net/pf.c
===================================================================
RCS file: /cvs/src/sys/net/pf.c,v
retrieving revision 1.730
diff -u -p -r1.730 pf.c
--- sys/net/pf.c        24 Mar 2011 20:09:44 -0000      1.730
+++ sys/net/pf.c        3 Apr 2011 11:57:19 -0000
@@ -1452,6 +1452,9 @@ pf_calc_skip_steps(struct pf_rulequeue *
                        PF_SET_SKIP_STEPS(PF_SKIP_IFP);
                if (cur->direction != prev->direction)
                        PF_SET_SKIP_STEPS(PF_SKIP_DIR);
+               if (cur->onrdomain != prev->onrdomain ||
+                   cur->ifnot != prev->ifnot)
+                       PF_SET_SKIP_STEPS(PF_SKIP_RDOM);
                if (cur->af != prev->af)
                        PF_SET_SKIP_STEPS(PF_SKIP_AF);
                if (cur->proto != prev->proto)
@@ -2813,6 +2816,9 @@ pf_test_rule(struct pf_rule **rm, struct
                        r = r->skip[PF_SKIP_IFP].ptr;
                else if (r->direction && r->direction != direction)
                        r = r->skip[PF_SKIP_DIR].ptr;
+               else if (r->onrdomain >= 0  &&
+                   (r->onrdomain == pd->rdomain) == r->ifnot)
+                       r = r->skip[PF_SKIP_RDOM].ptr;
                else if (r->af && r->af != af)
                        r = r->skip[PF_SKIP_AF].ptr;
                else if (r->proto && r->proto != pd->proto)
@@ -3397,6 +3403,9 @@ pf_test_fragment(struct pf_rule **rm, in
                        r = r->skip[PF_SKIP_IFP].ptr;
                else if (r->direction && r->direction != direction)
                        r = r->skip[PF_SKIP_DIR].ptr;
+               else if (r->onrdomain >= 0  &&
+                   (r->onrdomain == pd->rdomain) == r->ifnot)
+                       r = r->skip[PF_SKIP_RDOM].ptr;
                else if (r->af && r->af != af)
                        r = r->skip[PF_SKIP_AF].ptr;
                else if (r->proto && r->proto != pd->proto)
Index: sys/net/pf_ioctl.c
===================================================================
RCS file: /cvs/src/sys/net/pf_ioctl.c,v
retrieving revision 1.237
diff -u -p -r1.237 pf_ioctl.c
--- sys/net/pf_ioctl.c  25 Mar 2011 10:54:22 -0000      1.237
+++ sys/net/pf_ioctl.c  3 Apr 2011 11:57:19 -0000
@@ -2517,8 +2517,13 @@ pf_rule_copyin(struct pf_rule *from, str
        to->os_fingerprint = from->os_fingerprint;
 
        to->rtableid = from->rtableid;
-       if (to->rtableid > 0 && !rtable_exists(to->rtableid))
+       if (to->rtableid >= 0 && !rtable_exists(to->rtableid))
                return (EBUSY);
+       to->onrdomain = from->onrdomain;
+       if (to->onrdomain >= 0 && !rtable_exists(to->onrdomain))
+               return (EBUSY);
+       if (to->onrdomain >= 0)         /* make sure it is a real rdomain */
+               to->onrdomain = rtable_l2(to->onrdomain);
 
        for (i = 0; i < PFTM_MAX; i++)
                to->timeout[i] = from->timeout[i];
Index: sys/net/pfvar.h
===================================================================
RCS file: /cvs/src/sys/net/pfvar.h,v
retrieving revision 1.324
diff -u -p -r1.324 pfvar.h
--- sys/net/pfvar.h     25 Mar 2011 10:54:22 -0000      1.324
+++ sys/net/pfvar.h     3 Apr 2011 11:57:19 -0000
@@ -543,13 +543,14 @@ struct pf_rule {
        struct pf_rule_addr      dst;
 #define PF_SKIP_IFP            0
 #define PF_SKIP_DIR            1
-#define PF_SKIP_AF             2
-#define PF_SKIP_PROTO          3
-#define PF_SKIP_SRC_ADDR       4
-#define PF_SKIP_SRC_PORT       5
-#define PF_SKIP_DST_ADDR       6
-#define PF_SKIP_DST_PORT       7
-#define PF_SKIP_COUNT          8
+#define PF_SKIP_RDOM           2
+#define PF_SKIP_AF             3
+#define PF_SKIP_PROTO          4
+#define PF_SKIP_SRC_ADDR       5
+#define PF_SKIP_SRC_PORT       6
+#define PF_SKIP_DST_ADDR       7
+#define PF_SKIP_DST_PORT       8
+#define PF_SKIP_COUNT          9
        union pf_rule_ptr        skip[PF_SKIP_COUNT];
 #define PF_RULE_LABEL_SIZE      64
        char                     label[PF_RULE_LABEL_SIZE];
@@ -581,6 +582,7 @@ struct pf_rule {
        pf_osfp_t                os_fingerprint;
 
        int                      rtableid;
+       int                      onrdomain;
        u_int32_t                timeout[PFTM_MAX];
        u_int32_t                states_cur;
        u_int32_t                states_tot;
Index: sbin/pfctl/parse.y
===================================================================
RCS file: /cvs/src/sbin/pfctl/parse.y,v
retrieving revision 1.597
diff -u -p -r1.597 parse.y
--- sbin/pfctl/parse.y  31 Dec 2010 12:15:31 -0000      1.597
+++ sbin/pfctl/parse.y  3 Apr 2011 11:57:19 -0000
@@ -461,7 +461,7 @@ int parseport(char *, struct range *r, i
 %token ANTISPOOF FOR INCLUDE MATCHES
 %token BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT PROBABILITY
 %token ALTQ CBQ PRIQ HFSC BANDWIDTH TBRSIZE LINKSHARE REALTIME UPPERLIMIT
-%token QUEUE PRIORITY QLIMIT RTABLE
+%token QUEUE PRIORITY QLIMIT RTABLE RDOMAIN
 %token LOAD RULESET_OPTIMIZATION
 %token STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE
 %token MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH SLOPPY PFLOW
@@ -2544,6 +2544,20 @@ if_item          : STRING                        {
                        $$->next = NULL;
                        $$->tail = $$;
                }
+               | RDOMAIN NUMBER                {
+                       if ($2 < 0 || $2 > RT_TABLEID_MAX) {
+                               yyerror("rdomain outside range");
+                               YYERROR;
+                       }
+                       $$ = calloc(1, sizeof(struct node_if));
+                       if ($$ == NULL)
+                               err(1, "if_item: calloc");
+                       $$->not = 0;
+                       $$->use_rdomain = 1;
+                       $$->rdomain = $2;
+                       $$->next = NULL;
+                       $$->tail = $$;
+               }
                ;
 
 af             : /* empty */                   { $$ = 0; }
@@ -4303,6 +4317,9 @@ expand_altq(struct pf_altq *a, struct no
                if (interface->not) {
                        yyerror("altq on ! <interface> is not supported");
                        errs++;
+               } else if (interface->use_rdomain) {
+                       yyerror("altq on rdomain <num> is not supported");
+                       errs++;
                } else {
                        if (eval_pfaltq(pf, &pa, &bwspec, opts))
                                errs++;
@@ -4759,6 +4776,10 @@ expand_rule(struct pf_rule *r, int keepr
                else
                        memset(r->ifname, '\0', sizeof(r->ifname));
 
+               if (interface->use_rdomain)
+                       r->onrdomain = interface->rdomain;
+               else
+                       r->onrdomain = -1;
                if (strlcpy(r->label, label, sizeof(r->label)) >=
                    sizeof(r->label))
                        errx(1, "expand_rule: strlcpy");
@@ -4969,6 +4990,9 @@ expand_skip_interface(struct node_if *in
                if (interface->not) {
                        yyerror("skip on ! <interface> is not supported");
                        errs++;
+               } else if (interface->use_rdomain) {
+                       yyerror("skip on rdomain <num> is not supported");
+                       errs++;
                } else
                        errs += pfctl_set_interface_flags(pf,
                            interface->ifname, PFI_IFLAG_SKIP, 1);
@@ -5099,6 +5123,7 @@ lookup(char *s)
                { "quick",              QUICK},
                { "random",             RANDOM},
                { "random-id",          RANDOMID},
+               { "rdomain",            RDOMAIN},
                { "rdr-to",             RDRTO},
                { "realtime",           REALTIME},
                { "reassemble",         REASSEMBLE},
Index: sbin/pfctl/pfctl_optimize.c
===================================================================
RCS file: /cvs/src/sbin/pfctl/pfctl_optimize.c,v
retrieving revision 1.25
diff -u -p -r1.25 pfctl_optimize.c
--- sbin/pfctl/pfctl_optimize.c 23 Mar 2010 13:31:29 -0000      1.25
+++ sbin/pfctl/pfctl_optimize.c 3 Apr 2011 11:57:19 -0000
@@ -173,6 +173,8 @@ struct pf_rule_field {
     PF_RULE_FIELD(dst.port_op,         NOMERGE),
     PF_RULE_FIELD(src.neg,             NOMERGE),
     PF_RULE_FIELD(dst.neg,             NOMERGE),
+    PF_RULE_FIELD(rtableid,            NOMERGE),
+    PF_RULE_FIELD(onrdomain,           NOMERGE),
 
     /* These fields can be merged */
     PF_RULE_FIELD(src.addr,            COMBINED),
@@ -227,6 +229,7 @@ int skip_compare(int, struct pf_skip_ste
 void   skip_init(void);
 int    skip_cmp_af(struct pf_rule *, struct pf_rule *);
 int    skip_cmp_dir(struct pf_rule *, struct pf_rule *);
+int    skip_cmp_rdom(struct pf_rule *, struct pf_rule *);
 int    skip_cmp_dst_addr(struct pf_rule *, struct pf_rule *);
 int    skip_cmp_dst_port(struct pf_rule *, struct pf_rule *);
 int    skip_cmp_ifp(struct pf_rule *, struct pf_rule *);
@@ -242,6 +245,7 @@ const char *skip_comparitors_names[PF_SK
 #define PF_SKIP_COMPARITORS {                          \
     { "ifp", PF_SKIP_IFP, skip_cmp_ifp },              \
     { "dir", PF_SKIP_DIR, skip_cmp_dir },              \
+    { "rdomain", PF_SKIP_RDOM, skip_cmp_rdom },                \
     { "af", PF_SKIP_AF, skip_cmp_af },                 \
     { "proto", PF_SKIP_PROTO, skip_cmp_proto },                \
     { "saddr", PF_SKIP_SRC_ADDR, skip_cmp_src_addr },  \
@@ -1034,6 +1038,15 @@ skip_cmp_dir(struct pf_rule *a, struct p
        if (a->direction == 0 || a->direction != b->direction)
                return (1);
        return (0);
+}
+
+/* Compare two rules ON RDOMAIN field for skiplist construction */
+int
+skip_cmp_rdom(struct pf_rule *a, struct pf_rule *b)
+{
+       if (a->onrdomain == -1 || a->onrdomain != b->onrdomain)
+               return (1);
+       return (a->ifnot != b->ifnot);
 }
 
 /* Compare two rules DST Address field for skiplist construction */
Index: sbin/pfctl/pfctl_parser.c
===================================================================
RCS file: /cvs/src/sbin/pfctl/pfctl_parser.c,v
retrieving revision 1.273
diff -u -p -r1.273 pfctl_parser.c
--- sbin/pfctl/pfctl_parser.c   23 Jan 2011 11:19:55 -0000      1.273
+++ sbin/pfctl/pfctl_parser.c   3 Apr 2011 11:57:19 -0000
@@ -771,6 +771,12 @@ print_rule(struct pf_rule *r, const char
                else
                        printf(" on %s", r->ifname);
        }
+       if (r->onrdomain >= 0) {
+               if (r->ifnot)
+                       printf(" on ! rdomain %i", r->onrdomain);
+               else
+                       printf(" on rdomain %i", r->onrdomain);
+       }
        if (r->af) {
                if (r->af == AF_INET)
                        printf(" inet");
Index: sbin/pfctl/pfctl_parser.h
===================================================================
RCS file: /cvs/src/sbin/pfctl/pfctl_parser.h,v
retrieving revision 1.94
diff -u -p -r1.94 pfctl_parser.h
--- sbin/pfctl/pfctl_parser.h   25 Jun 2010 23:27:47 -0000      1.94
+++ sbin/pfctl/pfctl_parser.h   3 Apr 2011 11:57:19 -0000
@@ -103,7 +103,9 @@ struct node_if {
        char                     ifname[IFNAMSIZ];
        u_int8_t                 not;
        u_int8_t                 dynamic; /* antispoof */
+       u_int8_t                 use_rdomain;
        u_int                    ifa_flags;
+       int                      rdomain;
        struct node_if          *next;
        struct node_if          *tail;
 };

Reply via email to