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