1
|
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
|
2
|
index ce64898..bc9a8f7 100644
|
3
|
--- a/sbin/pfctl/parse.y
|
4
|
+++ b/sbin/pfctl/parse.y
|
5
|
@@ -446,7 +446,7 @@ int parseport(char *, struct range *r, int);
|
6
|
|
7
|
%}
|
8
|
|
9
|
-%token PASS BLOCK SCRUB RETURN IN OS OUT LOG QUICK ON FROM TO FLAGS
|
10
|
+%token PASS BLOCK MATCH SCRUB RETURN IN OS OUT LOG QUICK ON FROM TO FLAGS
|
11
|
%token RETURNRST RETURNICMP RETURNICMP6 PROTO INET INET6 ALL ANY ICMPTYPE
|
12
|
%token ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT ARROW NODF
|
13
|
%token MINTTL ERROR ALLOWOPTS FASTROUTE FILENAME ROUTETO DUPTO REPLYTO NO LABEL SCHEDULE
|
14
|
@@ -2565,6 +2565,7 @@ probability : STRING {
|
15
|
|
16
|
|
17
|
action : PASS { $$.b1 = PF_PASS; $$.b2 = $$.w = 0; }
|
18
|
+ | MATCH { $$.b1 = PF_MATCH; $$.b2 = $$.w = 0; }
|
19
|
| BLOCK blockspec { $$ = $2; $$.b1 = PF_DROP; }
|
20
|
;
|
21
|
|
22
|
@@ -5485,6 +5486,7 @@ lookup(char *s)
|
23
|
{ "load", LOAD},
|
24
|
{ "log", LOG},
|
25
|
{ "loginterface", LOGINTERFACE},
|
26
|
+ { "match", MATCH},
|
27
|
{ "max", MAXIMUM},
|
28
|
{ "max-mss", MAXMSS},
|
29
|
{ "max-src-conn", MAXSRCCONN},
|
30
|
diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c
|
31
|
index 8f23a7b..afc2b82 100644
|
32
|
--- a/sbin/pfctl/pfctl_parser.c
|
33
|
+++ b/sbin/pfctl/pfctl_parser.c
|
34
|
@@ -692,7 +692,9 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose, int numeric)
|
35
|
|
36
|
if (verbose)
|
37
|
printf("@%d ", r->nr);
|
38
|
- if (r->action > PF_NORDR)
|
39
|
+ if (r->action == PF_MATCH)
|
40
|
+ printf("match");
|
41
|
+ else if (r->action > PF_NORDR)
|
42
|
printf("action(%d)", r->action);
|
43
|
else if (anchor_call[0]) {
|
44
|
if (anchor_call[0] == '_') {
|
45
|
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
|
46
|
index e77d02e..6061763 100644
|
47
|
--- a/sys/net/pfvar.h
|
48
|
+++ b/sys/net/pfvar.h
|
49
|
@@ -465,6 +465,13 @@ struct pf_osfp_ioctl {
|
50
|
int fp_getnum; /* DIOCOSFPGET number */
|
51
|
};
|
52
|
|
53
|
+struct pf_rule_actions {
|
54
|
+ u_int16_t qid;
|
55
|
+ u_int16_t pqid;
|
56
|
+ u_int32_t pdnpipe;
|
57
|
+ u_int32_t dnpipe;
|
58
|
+ u_int8_t flags;
|
59
|
+};
|
60
|
|
61
|
union pf_rule_ptr {
|
62
|
struct pf_rule *ptr;
|
63
|
@@ -521,8 +528,8 @@ struct pf_rule {
|
64
|
u_int32_t limit;
|
65
|
u_int32_t seconds;
|
66
|
} max_src_conn_rate;
|
67
|
- u_int32_t qid;
|
68
|
- u_int32_t pqid;
|
69
|
+ u_int16_t qid;
|
70
|
+ u_int16_t pqid;
|
71
|
u_int32_t dnpipe;
|
72
|
u_int32_t pdnpipe;
|
73
|
#define PFRULE_DN_IS_PIPE 0x00000010
|
74
|
@@ -766,6 +773,10 @@ struct pf_state {
|
75
|
u_int32_t creation;
|
76
|
u_int32_t expire;
|
77
|
u_int32_t pfsync_time;
|
78
|
+ u_int16_t qid;
|
79
|
+ u_int16_t pqid;
|
80
|
+ u_int32_t pdnpipe;
|
81
|
+ u_int32_t dnpipe;
|
82
|
u_int16_t tag;
|
83
|
u_int8_t log;
|
84
|
u_int8_t state_flags;
|
85
|
@@ -1137,6 +1148,7 @@ struct pf_pdesc {
|
86
|
u_int16_t *sport;
|
87
|
u_int16_t *dport;
|
88
|
struct pf_mtag *pf_mtag;
|
89
|
+ struct pf_rule_actions act;
|
90
|
|
91
|
u_int32_t p_len; /* total length of payload */
|
92
|
|
93
|
diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
|
94
|
index 29c219e..f383822 100644
|
95
|
--- a/sys/netpfil/pf/pf.c
|
96
|
+++ b/sys/netpfil/pf/pf.c
|
97
|
@@ -229,6 +229,8 @@ static int pf_state_key_attach(struct pf_state_key *,
|
98
|
static void pf_state_key_detach(struct pf_state *, int);
|
99
|
static int pf_state_key_ctor(void *, int, void *, int);
|
100
|
static u_int32_t pf_tcp_iss(struct pf_pdesc *);
|
101
|
+void pf_rule_to_actions(struct pf_rule *,
|
102
|
+ struct pf_rule_actions *);
|
103
|
static int pf_test_rule(struct pf_rule **, struct pf_state **,
|
104
|
int, struct pfi_kif *, struct mbuf *, int,
|
105
|
struct pf_pdesc *, struct pf_rule **,
|
106
|
@@ -2892,6 +2894,21 @@ pf_addr_inc(struct pf_addr *addr, sa_family_t af)
|
107
|
}
|
108
|
#endif /* INET6 */
|
109
|
|
110
|
+void
|
111
|
+pf_rule_to_actions(struct pf_rule *r, struct pf_rule_actions *a)
|
112
|
+{
|
113
|
+ if (r->qid)
|
114
|
+ a->qid = r->qid;
|
115
|
+ if (r->pqid)
|
116
|
+ a->pqid = r->pqid;
|
117
|
+ if (r->pdnpipe)
|
118
|
+ a->pdnpipe = r->pdnpipe;
|
119
|
+ if (r->dnpipe)
|
120
|
+ a->dnpipe = r->dnpipe;
|
121
|
+ if (r->free_flags & PFRULE_DN_IS_PIPE)
|
122
|
+ a->flags |= PFRULE_DN_IS_PIPE;
|
123
|
+}
|
124
|
+
|
125
|
int
|
126
|
pf_socket_lookup(int direction, struct pf_pdesc *pd, struct mbuf *m)
|
127
|
{
|
128
|
@@ -3442,10 +3459,20 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
|
129
|
if (r->rtableid >= 0)
|
130
|
rtableid = r->rtableid;
|
131
|
if (r->anchor == NULL) {
|
132
|
- match = 1;
|
133
|
- *rm = r;
|
134
|
- *am = a;
|
135
|
- *rsm = ruleset;
|
136
|
+ if (r->action == PF_MATCH) {
|
137
|
+ r->packets[direction == PF_OUT]++;
|
138
|
+ r->bytes[direction == PF_OUT] += pd->tot_len;
|
139
|
+ pf_rule_to_actions(r, &pd->act);
|
140
|
+ if (r->log)
|
141
|
+ PFLOG_PACKET(kif, m, af,
|
142
|
+ direction, PFRES_MATCH, r,
|
143
|
+ a, ruleset, pd, 1);
|
144
|
+ } else {
|
145
|
+ match = 1;
|
146
|
+ *rm = r;
|
147
|
+ *am = a;
|
148
|
+ *rsm = ruleset;
|
149
|
+ }
|
150
|
if ((*rm)->quick)
|
151
|
break;
|
152
|
r = TAILQ_NEXT(r, entries);
|
153
|
@@ -3464,6 +3491,9 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
|
154
|
|
155
|
REASON_SET(&reason, PFRES_MATCH);
|
156
|
|
157
|
+ /* apply actions for last matching pass/block rule */
|
158
|
+ pf_rule_to_actions(r, &pd->act);
|
159
|
+
|
160
|
if (r->log || (nr != NULL && nr->log)) {
|
161
|
if (rewrite)
|
162
|
m_copyback(m, off, hdrlen, pd->hdr.any);
|
163
|
@@ -3637,6 +3667,11 @@ pf_create_state(struct pf_rule *r, struct pf_rule *nr, struct pf_rule *a,
|
164
|
s->state_flags |= PFSTATE_SLOPPY;
|
165
|
s->log = r->log & PF_LOG_ALL;
|
166
|
s->sync_state = PFSYNC_S_NONE;
|
167
|
+ s->qid = pd->act.qid;
|
168
|
+ s->pqid = pd->act.pqid;
|
169
|
+ s->pdnpipe = pd->act.pdnpipe;
|
170
|
+ s->dnpipe = pd->act.dnpipe;
|
171
|
+ s->state_flags |= pd->act.flags;
|
172
|
if (nr != NULL)
|
173
|
s->log |= nr->log & PF_LOG_ALL;
|
174
|
switch (pd->proto) {
|
175
|
@@ -3873,10 +3908,20 @@ pf_test_fragment(struct pf_rule **rm, int direction, struct pfi_kif *kif,
|
176
|
r = TAILQ_NEXT(r, entries);
|
177
|
else {
|
178
|
if (r->anchor == NULL) {
|
179
|
- match = 1;
|
180
|
- *rm = r;
|
181
|
- *am = a;
|
182
|
- *rsm = ruleset;
|
183
|
+ if (r->action == PF_MATCH) {
|
184
|
+ r->packets[direction == PF_OUT]++;
|
185
|
+ r->bytes[direction == PF_OUT] += pd->tot_len;
|
186
|
+ pf_rule_to_actions(r, &pd->act);
|
187
|
+ if (r->log)
|
188
|
+ PFLOG_PACKET(kif, m, af,
|
189
|
+ direction, PFRES_MATCH, r,
|
190
|
+ a, ruleset, pd, 1);
|
191
|
+ } else {
|
192
|
+ match = 1;
|
193
|
+ *rm = r;
|
194
|
+ *am = a;
|
195
|
+ *rsm = ruleset;
|
196
|
+ }
|
197
|
if ((*rm)->quick)
|
198
|
break;
|
199
|
r = TAILQ_NEXT(r, entries);
|
200
|
@@ -3895,6 +3940,9 @@ pf_test_fragment(struct pf_rule **rm, int direction, struct pfi_kif *kif,
|
201
|
|
202
|
REASON_SET(&reason, PFRES_MATCH);
|
203
|
|
204
|
+ /* apply actions for last matching pass/block rule */
|
205
|
+ pf_rule_to_actions(r, &pd->act);
|
206
|
+
|
207
|
if (r->log)
|
208
|
PFLOG_PACKET(kif, m, af, direction, reason, r, a, ruleset, pd,
|
209
|
1);
|
210
|
@@ -6158,34 +6206,46 @@ done:
|
211
|
M_SETFIB(m, r->rtableid);
|
212
|
|
213
|
#ifdef ALTQ
|
214
|
- if (action == PF_PASS && r->qid) {
|
215
|
- if (pd.pf_mtag == NULL &&
|
216
|
- ((pd.pf_mtag = pf_get_mtag(m)) == NULL)) {
|
217
|
- action = PF_DROP;
|
218
|
- REASON_SET(&reason, PFRES_MEMORY);
|
219
|
- }
|
220
|
+ if (s && s->qid) {
|
221
|
+ pd.act.pqid = s->pqid;
|
222
|
+ pd.act.qid = s->qid;
|
223
|
+ } else if (r->qid) {
|
224
|
+ pd.act.pqid = r->pqid;
|
225
|
+ pd.act.qid = r->qid;
|
226
|
+ }
|
227
|
+ if (action == PF_PASS && pd.act.qid) {
|
228
|
if (s)
|
229
|
pd.pf_mtag->qid_hash = pf_state_hash(s);
|
230
|
if (pqid || (pd.tos & IPTOS_LOWDELAY))
|
231
|
- pd.pf_mtag->qid = r->pqid;
|
232
|
+ pd.pf_mtag->qid = pd.act.pqid;
|
233
|
else
|
234
|
- pd.pf_mtag->qid = r->qid;
|
235
|
+ pd.pf_mtag->qid = pd.act.qid;
|
236
|
/* add hints for ecn */
|
237
|
pd.pf_mtag->hdr = h;
|
238
|
-
|
239
|
}
|
240
|
#endif /* ALTQ */
|
241
|
|
242
|
- if (r->dnpipe && ip_dn_io_ptr != NULL && loopedfrom != 1) {
|
243
|
- if (dir != r->direction && r->pdnpipe) {
|
244
|
- dnflow.rule.info = r->pdnpipe;
|
245
|
+ if (s && (s->dnpipe || s->pdnpipe)) {
|
246
|
+ pd.act.dnpipe = s->dnpipe;
|
247
|
+ pd.act.pdnpipe = s->pdnpipe;
|
248
|
+ pd.act.flags = s->state_flags;
|
249
|
+ } else if (r->dnpipe || r->pdnpipe) {
|
250
|
+ pd.act.dnpipe = r->dnpipe;
|
251
|
+ pd.act.dnpipe = r->pdnpipe;
|
252
|
+ pd.act.flags = r->free_flags;
|
253
|
+ }
|
254
|
+
|
255
|
+ if (pd.act.dnpipe && ip_dn_io_ptr != NULL && loopedfrom != 1) {
|
256
|
+ if (dir != r->direction && pd.act.pdnpipe) {
|
257
|
+ dnflow.rule.info = pd.act.pdnpipe;
|
258
|
} else if (dir == r->direction) {
|
259
|
- dnflow.rule.info = r->dnpipe;
|
260
|
+ dnflow.rule.info = pd.act.dnpipe;
|
261
|
} else
|
262
|
goto continueprocessing;
|
263
|
|
264
|
- if (r->free_flags & PFRULE_DN_IS_PIPE)
|
265
|
+ if (pd.act.flags & PFRULE_DN_IS_PIPE)
|
266
|
dnflow.rule.info |= IPFW_IS_PIPE;
|
267
|
+
|
268
|
dnflow.f_id.addr_type = 4; /* IPv4 type */
|
269
|
dnflow.f_id.proto = pd.proto;
|
270
|
if (dir == PF_OUT && s != NULL && s->nat_rule.ptr != NULL &&
|
271
|
@@ -6647,33 +6707,45 @@ done:
|
272
|
M_SETFIB(m, r->rtableid);
|
273
|
|
274
|
#ifdef ALTQ
|
275
|
- if (action == PF_PASS && r->qid) {
|
276
|
- if (pd.pf_mtag == NULL &&
|
277
|
- ((pd.pf_mtag = pf_get_mtag(m)) == NULL)) {
|
278
|
- action = PF_DROP;
|
279
|
- REASON_SET(&reason, PFRES_MEMORY);
|
280
|
- }
|
281
|
+ if (s && s->qid) {
|
282
|
+ pd.act.pqid = s->pqid;
|
283
|
+ pd.act.qid = s->qid;
|
284
|
+ } else if (r->qid) {
|
285
|
+ pd.act.pqid = r->pqid;
|
286
|
+ pd.act.qid = r->qid;
|
287
|
+ }
|
288
|
+ if (action == PF_PASS && pd.act.qid) {
|
289
|
if (s)
|
290
|
pd.pf_mtag->qid_hash = pf_state_hash(s);
|
291
|
if (pd.tos & IPTOS_LOWDELAY)
|
292
|
- pd.pf_mtag->qid = r->pqid;
|
293
|
+ pd.pf_mtag->qid = pd.act.pqid;
|
294
|
else
|
295
|
- pd.pf_mtag->qid = r->qid;
|
296
|
+ pd.pf_mtag->qid = pd.act.qid;
|
297
|
/* add hints for ecn */
|
298
|
pd.pf_mtag->hdr = h;
|
299
|
}
|
300
|
#endif /* ALTQ */
|
301
|
|
302
|
- if (r->dnpipe && ip_dn_io_ptr != NULL && loopedfrom != 1) {
|
303
|
- if (dir != r->direction && r->pdnpipe) {
|
304
|
- dnflow.rule.info = r->pdnpipe;
|
305
|
- } else if (dir == r->direction) {
|
306
|
- dnflow.rule.info = r->dnpipe;
|
307
|
+ if (s && (s->dnpipe || s->pdnpipe)) {
|
308
|
+ pd.act.dnpipe = s->dnpipe;
|
309
|
+ pd.act.pdnpipe = s->pdnpipe;
|
310
|
+ pd.act.flags = s->state_flags;
|
311
|
+ } else if (r->dnpipe || r->pdnpipe) {
|
312
|
+ pd.act.dnpipe = r->dnpipe;
|
313
|
+ pd.act.dnpipe = r->pdnpipe;
|
314
|
+ pd.act.flags = r->free_flags;
|
315
|
+ }
|
316
|
+ if ((pd.act.dnpipe || pd.act.pdnpipe) && ip_dn_io_ptr != NULL && loopedfrom != 1) {
|
317
|
+ if (dir != r->direction && pd.act.pdnpipe) {
|
318
|
+ dnflow.rule.info = pd.act.pdnpipe;
|
319
|
+ } else if (dir == r->direction && pd.act.dnpipe) {
|
320
|
+ dnflow.rule.info = pd.act.dnpipe;
|
321
|
} else
|
322
|
goto continueprocessing6;
|
323
|
|
324
|
- if (r->free_flags & PFRULE_DN_IS_PIPE)
|
325
|
+ if (pd.act.flags & PFRULE_DN_IS_PIPE)
|
326
|
dnflow.rule.info |= IPFW_IS_PIPE;
|
327
|
+
|
328
|
dnflow.f_id.addr_type = 6; /* IPv4 type */
|
329
|
dnflow.f_id.proto = pd.proto;
|
330
|
dnflow.f_id.src_ip = 0;
|
331
|
diff --git a/sys/netpfil/pf/pf.h b/sys/netpfil/pf/pf.h
|
332
|
index 7d692d4..f25adde 100644
|
333
|
--- a/sys/netpfil/pf/pf.h
|
334
|
+++ b/sys/netpfil/pf/pf.h
|
335
|
@@ -45,7 +45,8 @@
|
336
|
|
337
|
enum { PF_INOUT, PF_IN, PF_OUT };
|
338
|
enum { PF_PASS, PF_DROP, PF_SCRUB, PF_NOSCRUB, PF_NAT, PF_NONAT,
|
339
|
- PF_BINAT, PF_NOBINAT, PF_RDR, PF_NORDR, PF_SYNPROXY_DROP, PF_DEFER };
|
340
|
+ PF_BINAT, PF_NOBINAT, PF_RDR, PF_NORDR, PF_SYNPROXY_DROP, PF_DEFER,
|
341
|
+ PF_MATCH };
|
342
|
enum { PF_RULESET_SCRUB, PF_RULESET_FILTER, PF_RULESET_NAT,
|
343
|
PF_RULESET_BINAT, PF_RULESET_RDR, PF_RULESET_MAX };
|
344
|
enum { PF_OP_NONE, PF_OP_IRG, PF_OP_EQ, PF_OP_NE, PF_OP_LT,
|
345
|
diff --git a/sys/netpfil/pf/pf_ruleset.c b/sys/netpfil/pf/pf_ruleset.c
|
346
|
index 384e42b..2274359 100644
|
347
|
--- a/sys/netpfil/pf/pf_ruleset.c
|
348
|
+++ b/sys/netpfil/pf/pf_ruleset.c
|
349
|
@@ -120,6 +120,7 @@ pf_get_ruleset_number(u_int8_t action)
|
350
|
return (PF_RULESET_SCRUB);
|
351
|
break;
|
352
|
case PF_PASS:
|
353
|
+ case PF_MATCH:
|
354
|
case PF_DROP:
|
355
|
return (PF_RULESET_FILTER);
|
356
|
break;
|