1
|
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
|
2
|
index 53fee93..c4f9941 100644
|
3
|
--- a/sbin/pfctl/parse.y
|
4
|
+++ b/sbin/pfctl/parse.y
|
5
|
@@ -239,6 +239,9 @@ struct filter_opts {
|
6
|
char *tag;
|
7
|
char *match_tag;
|
8
|
u_int8_t match_tag_not;
|
9
|
+ u_int32_t dnpipe;
|
10
|
+ u_int32_t pdnpipe;
|
11
|
+ u_int32_t free_flags;
|
12
|
u_int rtableid;
|
13
|
struct {
|
14
|
struct node_host *addr;
|
15
|
@@ -450,6 +453,7 @@ int parseport(char *, struct range *r, int);
|
16
|
%token BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT PROBABILITY
|
17
|
%token ALTQ CBQ PRIQ HFSC BANDWIDTH TBRSIZE LINKSHARE REALTIME UPPERLIMIT
|
18
|
%token QUEUE PRIORITY QLIMIT RTABLE
|
19
|
+%token DNPIPE DNQUEUE
|
20
|
%token LOAD RULESET_OPTIMIZATION
|
21
|
%token STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE
|
22
|
%token MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH SLOPPY
|
23
|
@@ -1600,14 +1604,22 @@ bandwidth : STRING {
|
24
|
|
25
|
bps = strtod($1, &cp);
|
26
|
if (cp != NULL) {
|
27
|
- if (!strcmp(cp, "b"))
|
28
|
+ if (!strcmp(cp, "b") || !strcmp(cp, "bit"))
|
29
|
; /* nothing */
|
30
|
- else if (!strcmp(cp, "Kb"))
|
31
|
+ else if (!strcmp(cp, "Kb") || !strcmp(cp, "Kbit"))
|
32
|
bps *= 1000;
|
33
|
- else if (!strcmp(cp, "Mb"))
|
34
|
+ else if (!strcmp(cp, "Mb") || !strcmp(cp, "Mbit"))
|
35
|
bps *= 1000 * 1000;
|
36
|
- else if (!strcmp(cp, "Gb"))
|
37
|
+ else if (!strcmp(cp, "Gb") || !strcmp(cp, "Gbit"))
|
38
|
bps *= 1000 * 1000 * 1000;
|
39
|
+ else if (!strcmp(cp, "B") || !strcmp(cp, "Byte"))
|
40
|
+ ; /* nothing */
|
41
|
+ else if (!strcmp(cp, "KB") || !strcmp(cp, "Kbyte"))
|
42
|
+ bps *= 1024;
|
43
|
+ else if (!strcmp(cp, "MB") || !strcmp(cp, "Mbyte"))
|
44
|
+ bps *= 1024 * 1024;
|
45
|
+ else if (!strcmp(cp, "GB") || !strcmp(cp, "Gbyte"))
|
46
|
+ bps *= 1024 * 1024 * 1024;
|
47
|
else if (!strcmp(cp, "%")) {
|
48
|
if (bps < 0 || bps > 100) {
|
49
|
yyerror("bandwidth spec "
|
50
|
@@ -2255,6 +2267,15 @@ pfrule : action dir logquick interface route af proto fromto
|
51
|
}
|
52
|
#endif
|
53
|
|
54
|
+ if ($9.dnpipe) {
|
55
|
+ r.dnpipe = $9.dnpipe;
|
56
|
+ if ($9.free_flags & PFRULE_DN_IS_PIPE)
|
57
|
+ r.free_flags |= PFRULE_DN_IS_PIPE;
|
58
|
+ else
|
59
|
+ r.free_flags |= PFRULE_DN_IS_QUEUE;
|
60
|
+ r.pdnpipe = $9.pdnpipe;
|
61
|
+ }
|
62
|
+
|
63
|
expand_rule(&r, $4, $5.host, $7, $8.src_os,
|
64
|
$8.src.host, $8.src.port, $8.dst.host, $8.dst.port,
|
65
|
$9.uid, $9.gid, $9.icmpspec, "");
|
66
|
@@ -2352,6 +2373,32 @@ filter_opt : USER uids {
|
67
|
}
|
68
|
filter_opts.queues = $1;
|
69
|
}
|
70
|
+ | DNPIPE number {
|
71
|
+ filter_opts.dnpipe = $2;
|
72
|
+ filter_opts.free_flags |= PFRULE_DN_IS_PIPE;
|
73
|
+ }
|
74
|
+ | DNPIPE '(' number ')' {
|
75
|
+ filter_opts.dnpipe = $3;
|
76
|
+ filter_opts.free_flags |= PFRULE_DN_IS_PIPE;
|
77
|
+ }
|
78
|
+ | DNPIPE '(' number comma number ')' {
|
79
|
+ filter_opts.pdnpipe = $5;
|
80
|
+ filter_opts.dnpipe = $3;
|
81
|
+ filter_opts.free_flags |= PFRULE_DN_IS_PIPE;
|
82
|
+ }
|
83
|
+ | DNQUEUE number {
|
84
|
+ filter_opts.dnpipe = $2;
|
85
|
+ filter_opts.free_flags |= PFRULE_DN_IS_QUEUE;
|
86
|
+ }
|
87
|
+ | DNQUEUE '(' number comma number ')' {
|
88
|
+ filter_opts.pdnpipe = $5;
|
89
|
+ filter_opts.dnpipe = $3;
|
90
|
+ filter_opts.free_flags |= PFRULE_DN_IS_QUEUE;
|
91
|
+ }
|
92
|
+ | DNQUEUE '(' number ')' {
|
93
|
+ filter_opts.dnpipe = $3;
|
94
|
+ filter_opts.free_flags |= PFRULE_DN_IS_QUEUE;
|
95
|
+ }
|
96
|
| TAG string {
|
97
|
filter_opts.tag = $2;
|
98
|
}
|
99
|
@@ -4503,6 +4550,11 @@ filter_consistent(struct pf_rule *r, int anchor_call)
|
100
|
yyerror("tos and dscp cannot be used together");
|
101
|
problems++;
|
102
|
}
|
103
|
+ if (r->dnpipe && r->pdnpipe && !r->direction) {
|
104
|
+ yyerror("dummynet cannot be specified without direction");
|
105
|
+ problems++;
|
106
|
+ }
|
107
|
+
|
108
|
return (-problems);
|
109
|
}
|
110
|
|
111
|
@@ -5295,6 +5347,8 @@ lookup(char *s)
|
112
|
{ "debug", DEBUG},
|
113
|
{ "divert-reply", DIVERTREPLY},
|
114
|
{ "divert-to", DIVERTTO},
|
115
|
+ { "dnpipe", DNPIPE},
|
116
|
+ { "dnqueue", DNQUEUE},
|
117
|
{ "drop", DROP},
|
118
|
{ "drop-ovl", FRAGDROP},
|
119
|
{ "dscp", DSCP},
|
120
|
diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c
|
121
|
index 544bc22..8f23a7b 100644
|
122
|
--- a/sbin/pfctl/pfctl_parser.c
|
123
|
+++ b/sbin/pfctl/pfctl_parser.c
|
124
|
@@ -1001,6 +1001,14 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose, int numeric)
|
125
|
}
|
126
|
if (r->label[0])
|
127
|
printf(" label \"%s\"", r->label);
|
128
|
+ if (r->dnpipe && r->pdnpipe)
|
129
|
+ printf(" %s(%d, %d)",
|
130
|
+ r->free_flags & PFRULE_DN_IS_PIPE ? "dnpipe" : "dnqueue",
|
131
|
+ r->dnpipe, r->pdnpipe);
|
132
|
+ else if (r->dnpipe)
|
133
|
+ printf(" %s %d",
|
134
|
+ r->free_flags & PFRULE_DN_IS_PIPE ? "dnpipe" : "dnqueue",
|
135
|
+ r->dnpipe);
|
136
|
if (r->qname[0] && r->pqname[0])
|
137
|
printf(" queue(%s, %s)", r->qname, r->pqname);
|
138
|
else if (r->qname[0])
|
139
|
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
|
140
|
index b1c28d2..d97166e 100644
|
141
|
--- a/sys/net/pfvar.h
|
142
|
+++ b/sys/net/pfvar.h
|
143
|
@@ -523,6 +523,11 @@ struct pf_rule {
|
144
|
} max_src_conn_rate;
|
145
|
u_int32_t qid;
|
146
|
u_int32_t pqid;
|
147
|
+ u_int32_t dnpipe;
|
148
|
+ u_int32_t pdnpipe;
|
149
|
+#define PFRULE_DN_IS_PIPE 0x00000010
|
150
|
+#define PFRULE_DN_IS_QUEUE 0x00000020
|
151
|
+ u_int32_t free_flags;
|
152
|
u_int32_t rt_listid;
|
153
|
u_int32_t nr;
|
154
|
u_int32_t prob;
|
155
|
diff --git a/sys/netpfil/ipfw/ip_dn_io.c b/sys/netpfil/ipfw/ip_dn_io.c
|
156
|
index 9a4b486..c842ce0 100644
|
157
|
--- a/sys/netpfil/ipfw/ip_dn_io.c
|
158
|
+++ b/sys/netpfil/ipfw/ip_dn_io.c
|
159
|
@@ -651,6 +651,7 @@ dummynet_send(struct mbuf *m)
|
160
|
* to carry reinject info.
|
161
|
*/
|
162
|
dst = pkt->dn_dir;
|
163
|
+ pkt->rule.info |= IPFW_IS_DUMMYNET;
|
164
|
ifp = pkt->ifp;
|
165
|
tag->m_tag_cookie = MTAG_IPFW_RULE;
|
166
|
tag->m_tag_id = 0;
|
167
|
diff --git a/sys/netpfil/ipfw/ip_dummynet.c b/sys/netpfil/ipfw/ip_dummynet.c
|
168
|
index 4de2156..b4b87c7 100644
|
169
|
--- a/sys/netpfil/ipfw/ip_dummynet.c
|
170
|
+++ b/sys/netpfil/ipfw/ip_dummynet.c
|
171
|
@@ -2290,7 +2290,6 @@ static moduledata_t dummynet_mod = {
|
172
|
#define DN_SI_SUB SI_SUB_PROTO_IFATTACHDOMAIN
|
173
|
#define DN_MODEV_ORD (SI_ORDER_ANY - 128) /* after ipfw */
|
174
|
DECLARE_MODULE(dummynet, dummynet_mod, DN_SI_SUB, DN_MODEV_ORD);
|
175
|
-MODULE_DEPEND(dummynet, ipfw, 2, 2, 2);
|
176
|
MODULE_VERSION(dummynet, 3);
|
177
|
|
178
|
/*
|
179
|
diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
|
180
|
index bdbddd2..6e15d72 100644
|
181
|
--- a/sys/netpfil/pf/pf.c
|
182
|
+++ b/sys/netpfil/pf/pf.c
|
183
|
@@ -86,6 +86,8 @@ __FBSDID("$FreeBSD$");
|
184
|
#include <netinet/udp_var.h>
|
185
|
|
186
|
#include <netpfil/ipfw/ip_fw_private.h> /* XXX: only for DIR_IN/DIR_OUT */
|
187
|
+#include <netinet/ip_fw.h>
|
188
|
+#include <netinet/ip_dummynet.h>
|
189
|
|
190
|
#ifdef INET6
|
191
|
#include <netinet/ip6.h>
|
192
|
@@ -259,7 +261,8 @@ static int pf_test_state_icmp(struct pf_state **, int,
|
193
|
struct pfi_kif *, struct mbuf *, int,
|
194
|
void *, struct pf_pdesc *, u_short *);
|
195
|
static int pf_test_state_other(struct pf_state **, int,
|
196
|
- struct pfi_kif *, struct mbuf *, struct pf_pdesc *);
|
197
|
+ struct pfi_kif *, struct mbuf *, int,
|
198
|
+ struct pf_pdesc *);
|
199
|
static u_int8_t pf_get_wscale(struct mbuf *, int, u_int16_t,
|
200
|
sa_family_t);
|
201
|
static u_int16_t pf_get_mss(struct mbuf *, int, u_int16_t,
|
202
|
@@ -284,6 +287,10 @@ static u_int pf_purge_expired_states(u_int, int);
|
203
|
static void pf_purge_unlinked_rules(void);
|
204
|
static int pf_mtag_init(void *, int, int);
|
205
|
static void pf_mtag_free(struct m_tag *);
|
206
|
+static void pf_packet_redo_nat(struct mbuf *, struct pf_pdesc *,
|
207
|
+ int, struct pf_state *, int);
|
208
|
+static void pf_packet_undo_nat(struct mbuf *, struct pf_pdesc *,
|
209
|
+ int, struct pf_state *, int);
|
210
|
#ifdef INET
|
211
|
static void pf_route(struct mbuf **, struct pf_rule *, int,
|
212
|
struct ifnet *, struct pf_state *,
|
213
|
@@ -303,16 +310,19 @@ VNET_DECLARE(int, pf_end_threads);
|
214
|
|
215
|
VNET_DEFINE(struct pf_limit, pf_limits[PF_LIMIT_MAX]);
|
216
|
|
217
|
-#define PACKET_LOOPED(pd) ((pd)->pf_mtag && \
|
218
|
- (pd)->pf_mtag->flags & PF_PACKET_LOOPED)
|
219
|
+#define PACKET_LOOPED(mtag) ((mtag)->flags & PF_PACKET_LOOPED)
|
220
|
|
221
|
#define STATE_LOOKUP(i, k, d, s, pd) \
|
222
|
do { \
|
223
|
(s) = pf_find_state((i), (k), (d)); \
|
224
|
if ((s) == NULL) \
|
225
|
return (PF_DROP); \
|
226
|
- if (PACKET_LOOPED(pd)) \
|
227
|
- return (PF_PASS); \
|
228
|
+ if (PACKET_LOOPED(pd->pf_mtag)) { \
|
229
|
+ if ((s)->key[PF_SK_WIRE] != (s)->key[PF_SK_STACK]) { \
|
230
|
+ pf_packet_redo_nat(m, pd, off, s, direction); \
|
231
|
+ } \
|
232
|
+ return (PF_PASS); \
|
233
|
+ } \
|
234
|
if ((d) == PF_OUT && \
|
235
|
(((s)->rule.ptr->rt == PF_ROUTETO && \
|
236
|
(s)->rule.ptr->direction == PF_OUT) || \
|
237
|
@@ -373,6 +383,142 @@ VNET_DEFINE(void *, pf_swi_cookie);
|
238
|
VNET_DEFINE(uint32_t, pf_hashseed);
|
239
|
#define V_pf_hashseed VNET(pf_hashseed)
|
240
|
|
241
|
+static void
|
242
|
+pf_packet_undo_nat(struct mbuf *m, struct pf_pdesc *pd, int off,
|
243
|
+ struct pf_state *state, int direction)
|
244
|
+{
|
245
|
+ struct pf_state_key *nk = (state)->key[pd->didx];
|
246
|
+
|
247
|
+ switch (pd->proto) {
|
248
|
+ case IPPROTO_TCP: {
|
249
|
+ struct tcphdr *th = pd->hdr.tcp;
|
250
|
+
|
251
|
+ if (direction == PF_OUT) {
|
252
|
+ pf_change_ap(pd->src, &th->th_sport, pd->ip_sum,
|
253
|
+ &th->th_sum, &nk->addr[pd->sidx],
|
254
|
+ nk->port[pd->sidx], 0, pd->af);
|
255
|
+ } else {
|
256
|
+ pf_change_ap(pd->dst, &th->th_dport, pd->ip_sum,
|
257
|
+ &th->th_sum, &nk->addr[pd->didx],
|
258
|
+ nk->port[pd->didx], 0, pd->af);
|
259
|
+ }
|
260
|
+ m_copyback(m, off, sizeof(*th), (caddr_t)th);
|
261
|
+ }
|
262
|
+ break;
|
263
|
+ case IPPROTO_UDP: {
|
264
|
+ struct udphdr *uh = pd->hdr.udp;
|
265
|
+
|
266
|
+ if (direction == PF_OUT) {
|
267
|
+ pf_change_ap(pd->src, &uh->uh_sport, pd->ip_sum,
|
268
|
+ &uh->uh_sum, &nk->addr[pd->sidx],
|
269
|
+ nk->port[pd->sidx], 1, pd->af);
|
270
|
+ } else {
|
271
|
+ pf_change_ap(pd->dst, &uh->uh_dport, pd->ip_sum,
|
272
|
+ &uh->uh_sum, &nk->addr[pd->didx],
|
273
|
+ nk->port[pd->didx], 1, pd->af);
|
274
|
+ }
|
275
|
+ m_copyback(m, off, sizeof(*uh), (caddr_t)uh);
|
276
|
+ }
|
277
|
+ break;
|
278
|
+ case IPPROTO_ICMP:
|
279
|
+ /* XXX: If we want to do this for icmp is probably wrong!?! */
|
280
|
+ break;
|
281
|
+ default:
|
282
|
+ if (direction == PF_OUT) {
|
283
|
+ switch (pd->af) {
|
284
|
+ case AF_INET:
|
285
|
+ pf_change_a(&pd->src->v4.s_addr,
|
286
|
+ pd->ip_sum, nk->addr[pd->sidx].v4.s_addr,
|
287
|
+ 0);
|
288
|
+ break;
|
289
|
+ case AF_INET6:
|
290
|
+ PF_ACPY(pd->src, &nk->addr[pd->sidx], pd->af);
|
291
|
+ break;
|
292
|
+ }
|
293
|
+ } else {
|
294
|
+ switch (pd->af) {
|
295
|
+ case AF_INET:
|
296
|
+ pf_change_a(&pd->dst->v4.s_addr,
|
297
|
+ pd->ip_sum, nk->addr[pd->didx].v4.s_addr,
|
298
|
+ 0);
|
299
|
+ break;
|
300
|
+ case AF_INET6:
|
301
|
+ PF_ACPY(pd->dst, &nk->addr[pd->didx], pd->af);
|
302
|
+ break;
|
303
|
+ }
|
304
|
+ }
|
305
|
+ break;
|
306
|
+ }
|
307
|
+}
|
308
|
+
|
309
|
+static void
|
310
|
+pf_packet_redo_nat(struct mbuf *m, struct pf_pdesc *pd, int off,
|
311
|
+ struct pf_state *state, int direction)
|
312
|
+{
|
313
|
+ struct pf_state_key *nk = state->key[pd->didx];
|
314
|
+
|
315
|
+ switch (pd->proto) {
|
316
|
+ case IPPROTO_TCP: {
|
317
|
+ struct tcphdr *th = pd->hdr.tcp;
|
318
|
+
|
319
|
+ if (direction == PF_OUT) {
|
320
|
+ pf_change_ap(pd->src, &th->th_sport, pd->ip_sum,
|
321
|
+ &th->th_sum, &nk->addr[pd->sidx],
|
322
|
+ nk->port[pd->sidx], 0, pd->af);
|
323
|
+ } else {
|
324
|
+ pf_change_ap(pd->dst, &th->th_dport, pd->ip_sum,
|
325
|
+ &th->th_sum, &nk->addr[pd->didx],
|
326
|
+ nk->port[pd->didx], 0, pd->af);
|
327
|
+ }
|
328
|
+ m_copyback(m, off, sizeof(*th), (caddr_t)th);
|
329
|
+ }
|
330
|
+ break;
|
331
|
+ case IPPROTO_UDP: {
|
332
|
+ struct udphdr *uh = pd->hdr.udp;
|
333
|
+
|
334
|
+ if (direction == PF_OUT) {
|
335
|
+ pf_change_ap(pd->src, &uh->uh_sport, pd->ip_sum,
|
336
|
+ &uh->uh_sum, &nk->addr[pd->sidx],
|
337
|
+ nk->port[pd->sidx], 1, pd->af);
|
338
|
+ } else {
|
339
|
+ pf_change_ap(pd->dst, &uh->uh_dport, pd->ip_sum,
|
340
|
+ &uh->uh_sum, &nk->addr[pd->didx],
|
341
|
+ nk->port[pd->didx], 1, pd->af);
|
342
|
+ }
|
343
|
+ m_copyback(m, off, sizeof(*uh), (caddr_t)uh);
|
344
|
+ }
|
345
|
+ break;
|
346
|
+ case IPPROTO_ICMP:
|
347
|
+ /* XXX: If we want to do this for icmp is probably wrong!?! */
|
348
|
+ break;
|
349
|
+ default:
|
350
|
+ if (direction == PF_OUT) {
|
351
|
+ switch (pd->af) {
|
352
|
+ case AF_INET:
|
353
|
+ pf_change_a(&pd->src->v4.s_addr,
|
354
|
+ pd->ip_sum, nk->addr[pd->sidx].v4.s_addr,
|
355
|
+ 0);
|
356
|
+ break;
|
357
|
+ case AF_INET6:
|
358
|
+ PF_ACPY(pd->src, &nk->addr[pd->sidx], pd->af);
|
359
|
+ break;
|
360
|
+ }
|
361
|
+ } else {
|
362
|
+ switch (pd->af) {
|
363
|
+ case AF_INET:
|
364
|
+ pf_change_a(&pd->dst->v4.s_addr,
|
365
|
+ pd->ip_sum, nk->addr[pd->didx].v4.s_addr,
|
366
|
+ 0);
|
367
|
+ break;
|
368
|
+ case AF_INET6:
|
369
|
+ PF_ACPY(pd->dst, &nk->addr[pd->didx], pd->af);
|
370
|
+ break;
|
371
|
+ }
|
372
|
+ }
|
373
|
+ break;
|
374
|
+ }
|
375
|
+}
|
376
|
+
|
377
|
static __inline uint32_t
|
378
|
pf_hashkey(struct pf_state_key *sk)
|
379
|
{
|
380
|
@@ -4977,7 +5123,7 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
|
381
|
|
382
|
static int
|
383
|
pf_test_state_other(struct pf_state **state, int direction, struct pfi_kif *kif,
|
384
|
- struct mbuf *m, struct pf_pdesc *pd)
|
385
|
+ struct mbuf *m, int off, struct pf_pdesc *pd)
|
386
|
{
|
387
|
struct pf_state_peer *src, *dst;
|
388
|
struct pf_state_key_cmp key;
|
389
|
@@ -5669,7 +5815,9 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp)
|
390
|
struct pf_state *s = NULL;
|
391
|
struct pf_ruleset *ruleset = NULL;
|
392
|
struct pf_pdesc pd;
|
393
|
- int off, dirndx, pqid = 0;
|
394
|
+ int off = 0, dirndx, pqid = 0;
|
395
|
+ int loopedfrom = 0;
|
396
|
+ struct ip_fw_args dnflow;
|
397
|
|
398
|
M_ASSERTPKTHDR(m);
|
399
|
|
400
|
@@ -5695,22 +5843,24 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp)
|
401
|
|
402
|
PF_RULES_RLOCK();
|
403
|
|
404
|
- if (ip_divert_ptr != NULL &&
|
405
|
+ if ((ip_divert_ptr != NULL || ip_dn_io_ptr != NULL) &&
|
406
|
((ipfwtag = m_tag_locate(m, MTAG_IPFW_RULE, 0, NULL)) != NULL)) {
|
407
|
struct ipfw_rule_ref *rr = (struct ipfw_rule_ref *)(ipfwtag+1);
|
408
|
+ pd.pf_mtag->flags |= PF_PACKET_LOOPED;
|
409
|
+ if (rr->info & IPFW_IS_DUMMYNET)
|
410
|
+ loopedfrom = 1;
|
411
|
if (rr->info & IPFW_IS_DIVERT && rr->rulenum == 0) {
|
412
|
if (pd.pf_mtag == NULL &&
|
413
|
((pd.pf_mtag = pf_get_mtag(m)) == NULL)) {
|
414
|
action = PF_DROP;
|
415
|
goto done;
|
416
|
}
|
417
|
- pd.pf_mtag->flags |= PF_PACKET_LOOPED;
|
418
|
- m_tag_delete(m, ipfwtag);
|
419
|
}
|
420
|
if (pd.pf_mtag && pd.pf_mtag->flags & PF_FASTFWD_OURS_PRESENT) {
|
421
|
m->m_flags |= M_FASTFWD_OURS;
|
422
|
pd.pf_mtag->flags &= ~PF_FASTFWD_OURS_PRESENT;
|
423
|
}
|
424
|
+ m_tag_delete(m, ipfwtag);
|
425
|
} else if (pf_normalize_ip(m0, dir, kif, &reason, &pd) != PF_PASS) {
|
426
|
/* We do IP header normalization and packet reassembly here */
|
427
|
action = PF_DROP;
|
428
|
@@ -5753,6 +5903,10 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp)
|
429
|
struct tcphdr th;
|
430
|
|
431
|
pd.hdr.tcp = &th;
|
432
|
+ dnflow.f_id._flags = th.th_flags;
|
433
|
+ dnflow.f_id.dst_port = ntohs(th.th_dport);
|
434
|
+ dnflow.f_id.src_port = ntohs(th.th_sport);
|
435
|
+
|
436
|
if (!pf_pull_hdr(m, off, &th, sizeof(th),
|
437
|
&action, &reason, AF_INET)) {
|
438
|
log = action != PF_PASS;
|
439
|
@@ -5782,6 +5936,9 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp)
|
440
|
struct udphdr uh;
|
441
|
|
442
|
pd.hdr.udp = &uh;
|
443
|
+ dnflow.f_id.dst_port = ntohs(uh.uh_dport);
|
444
|
+ dnflow.f_id.src_port = ntohs(uh.uh_sport);
|
445
|
+
|
446
|
if (!pf_pull_hdr(m, off, &uh, sizeof(uh),
|
447
|
&action, &reason, AF_INET)) {
|
448
|
log = action != PF_PASS;
|
449
|
@@ -5840,7 +5997,7 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp)
|
450
|
#endif
|
451
|
|
452
|
default:
|
453
|
- action = pf_test_state_other(&s, dir, kif, m, &pd);
|
454
|
+ action = pf_test_state_other(&s, dir, kif, m, off, &pd);
|
455
|
if (action == PF_PASS) {
|
456
|
if (pfsync_update_state_ptr != NULL)
|
457
|
pfsync_update_state_ptr(s);
|
458
|
@@ -5888,6 +6045,54 @@ done:
|
459
|
}
|
460
|
#endif /* ALTQ */
|
461
|
|
462
|
+ if (r->dnpipe && ip_dn_io_ptr != NULL && loopedfrom != 1) {
|
463
|
+ if (dir != r->direction && r->pdnpipe) {
|
464
|
+ dnflow.rule.info = r->pdnpipe;
|
465
|
+ } else if (dir == r->direction) {
|
466
|
+ dnflow.rule.info = r->dnpipe;
|
467
|
+ } else
|
468
|
+ goto continueprocessing;
|
469
|
+
|
470
|
+ if (r->free_flags & PFRULE_DN_IS_PIPE)
|
471
|
+ dnflow.rule.info |= IPFW_IS_PIPE;
|
472
|
+ dnflow.f_id.addr_type = 4; /* IPv4 type */
|
473
|
+ dnflow.f_id.proto = pd.proto;
|
474
|
+ if (dir == PF_OUT && s != NULL && s->nat_rule.ptr != NULL &&
|
475
|
+ s->nat_rule.ptr->action == PF_NAT)
|
476
|
+ dnflow.f_id.src_ip = ntohl(s->key[(s->direction == PF_IN)]->
|
477
|
+ addr[(s->direction == PF_OUT)].v4.s_addr);
|
478
|
+ else
|
479
|
+ dnflow.f_id.src_ip = ntohl(h->ip_src.s_addr);
|
480
|
+ dnflow.f_id.dst_ip = ntohl(h->ip_dst.s_addr);
|
481
|
+ dnflow.f_id.extra = dnflow.rule.info;
|
482
|
+
|
483
|
+ if (m->m_flags & M_FASTFWD_OURS) {
|
484
|
+ pd.pf_mtag->flags |= PF_FASTFWD_OURS_PRESENT;
|
485
|
+ m->m_flags &= ~M_FASTFWD_OURS;
|
486
|
+ }
|
487
|
+
|
488
|
+ if (s != NULL && s->nat_rule.ptr)
|
489
|
+ pf_packet_undo_nat(m, &pd, off, s, dir);
|
490
|
+
|
491
|
+ ip_dn_io_ptr(m0,
|
492
|
+ (dir == PF_IN) ? DIR_IN : DIR_OUT,
|
493
|
+ &dnflow);
|
494
|
+ /* This is dummynet fast io processing */
|
495
|
+ if (*m0 != NULL) {
|
496
|
+ m_tag_delete(*m0, m_tag_first(*m0));
|
497
|
+ pd.pf_mtag->flags &= ~PF_PACKET_LOOPED;
|
498
|
+ if (s != NULL && s->nat_rule.ptr)
|
499
|
+ pf_packet_redo_nat(m, &pd, off, s, dir);
|
500
|
+ } else {
|
501
|
+ *m0 = NULL;
|
502
|
+ if (s)
|
503
|
+ PF_STATE_UNLOCK(s);
|
504
|
+ return (action);
|
505
|
+ }
|
506
|
+ } else
|
507
|
+ pd.pf_mtag->flags &= ~PF_PACKET_LOOPED;
|
508
|
+continueprocessing:
|
509
|
+
|
510
|
/*
|
511
|
* connections redirected to loopback should not match sockets
|
512
|
* bound specifically to loopback due to security implications,
|
513
|
@@ -6034,7 +6239,10 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp)
|
514
|
struct pf_state *s = NULL;
|
515
|
struct pf_ruleset *ruleset = NULL;
|
516
|
struct pf_pdesc pd;
|
517
|
- int off, terminal = 0, dirndx, rh_cnt = 0;
|
518
|
+ int off = 0, terminal = 0, dirndx, rh_cnt = 0;
|
519
|
+ int loopedfrom = 0;
|
520
|
+ struct m_tag *dn_tag;
|
521
|
+ struct ip_fw_args dnflow;
|
522
|
|
523
|
M_ASSERTPKTHDR(m);
|
524
|
|
525
|
@@ -6058,8 +6266,20 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp)
|
526
|
|
527
|
PF_RULES_RLOCK();
|
528
|
|
529
|
+ if (ip_dn_io_ptr != NULL &&
|
530
|
+ ((dn_tag = m_tag_locate(m, MTAG_IPFW_RULE, 0, NULL)) != NULL)) {
|
531
|
+ struct ipfw_rule_ref *rr = (struct ipfw_rule_ref *)(dn_tag+1);
|
532
|
+ pd.pf_mtag->flags |= PF_PACKET_LOOPED;
|
533
|
+ if (rr->info & IPFW_IS_DUMMYNET)
|
534
|
+ loopedfrom = 1;
|
535
|
+ if (pd.pf_mtag->flags & PF_FASTFWD_OURS_PRESENT) {
|
536
|
+ m->m_flags |= M_FASTFWD_OURS;
|
537
|
+ pd.pf_mtag->flags &= ~PF_FASTFWD_OURS_PRESENT;
|
538
|
+ }
|
539
|
+ m_tag_delete(m, dn_tag);
|
540
|
+ }
|
541
|
/* We do IP header normalization and packet reassembly here */
|
542
|
- if (pf_normalize_ip6(m0, dir, kif, &reason, &pd) != PF_PASS) {
|
543
|
+ else if (pf_normalize_ip6(m0, dir, kif, &reason, &pd) != PF_PASS) {
|
544
|
action = PF_DROP;
|
545
|
goto done;
|
546
|
}
|
547
|
@@ -6168,6 +6388,10 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp)
|
548
|
struct tcphdr th;
|
549
|
|
550
|
pd.hdr.tcp = &th;
|
551
|
+ dnflow.f_id._flags = th.th_flags;
|
552
|
+ dnflow.f_id.dst_port = th.th_dport;
|
553
|
+ dnflow.f_id.src_port = th.th_sport;
|
554
|
+
|
555
|
if (!pf_pull_hdr(m, off, &th, sizeof(th),
|
556
|
&action, &reason, AF_INET6)) {
|
557
|
log = action != PF_PASS;
|
558
|
@@ -6195,6 +6419,9 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp)
|
559
|
struct udphdr uh;
|
560
|
|
561
|
pd.hdr.udp = &uh;
|
562
|
+ dnflow.f_id.dst_port = uh.uh_dport;
|
563
|
+ dnflow.f_id.src_port = uh.uh_sport;
|
564
|
+
|
565
|
if (!pf_pull_hdr(m, off, &uh, sizeof(uh),
|
566
|
&action, &reason, AF_INET6)) {
|
567
|
log = action != PF_PASS;
|
568
|
@@ -6251,7 +6478,7 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp)
|
569
|
}
|
570
|
|
571
|
default:
|
572
|
- action = pf_test_state_other(&s, dir, kif, m, &pd);
|
573
|
+ action = pf_test_state_other(&s, dir, kif, m, off, &pd);
|
574
|
if (action == PF_PASS) {
|
575
|
if (pfsync_update_state_ptr != NULL)
|
576
|
pfsync_update_state_ptr(s);
|
577
|
@@ -6304,6 +6531,49 @@ done:
|
578
|
}
|
579
|
#endif /* ALTQ */
|
580
|
|
581
|
+ if (r->dnpipe && ip_dn_io_ptr != NULL && loopedfrom != 1) {
|
582
|
+ if (dir != r->direction && r->pdnpipe) {
|
583
|
+ dnflow.rule.info = r->pdnpipe;
|
584
|
+ } else if (dir == r->direction) {
|
585
|
+ dnflow.rule.info = r->dnpipe;
|
586
|
+ } else
|
587
|
+ goto continueprocessing6;
|
588
|
+
|
589
|
+ if (r->free_flags & PFRULE_DN_IS_PIPE)
|
590
|
+ dnflow.rule.info |= IPFW_IS_PIPE;
|
591
|
+ dnflow.f_id.addr_type = 6; /* IPv4 type */
|
592
|
+ dnflow.f_id.proto = pd.proto;
|
593
|
+ dnflow.f_id.src_ip = 0;
|
594
|
+ dnflow.f_id.dst_ip = 0;
|
595
|
+ if (dir == PF_OUT && s != NULL && s->nat_rule.ptr != NULL &&
|
596
|
+ s->nat_rule.ptr->action == PF_NAT)
|
597
|
+ dnflow.f_id.src_ip6 = s->key[(s->direction == PF_IN)]->addr[0].v6;
|
598
|
+ else
|
599
|
+ dnflow.f_id.src_ip6 = h->ip6_src;
|
600
|
+ dnflow.f_id.dst_ip6 = h->ip6_dst;
|
601
|
+
|
602
|
+ if (s != NULL && s->nat_rule.ptr)
|
603
|
+ pf_packet_undo_nat(m, &pd, off, s, dir);
|
604
|
+
|
605
|
+ ip_dn_io_ptr(m0,
|
606
|
+ (dir == PF_IN) ? DIR_IN : DIR_OUT,
|
607
|
+ &dnflow);
|
608
|
+ /* This is dummynet fast io processing */
|
609
|
+ if (*m0 != NULL) {
|
610
|
+ m_tag_delete(*m0, m_tag_first(*m0));
|
611
|
+ pd.pf_mtag->flags &= ~PF_PACKET_LOOPED;
|
612
|
+ if (s != NULL && s->nat_rule.ptr)
|
613
|
+ pf_packet_redo_nat(m, &pd, off, s, dir);
|
614
|
+ } else {
|
615
|
+ *m0 = NULL;
|
616
|
+ if (s)
|
617
|
+ PF_STATE_UNLOCK(s);
|
618
|
+ return (action);
|
619
|
+ }
|
620
|
+ } else
|
621
|
+ pd.pf_mtag->flags &= ~PF_PACKET_LOOPED;
|
622
|
+continueprocessing6:
|
623
|
+
|
624
|
if (dir == PF_IN && action == PF_PASS && (pd.proto == IPPROTO_TCP ||
|
625
|
pd.proto == IPPROTO_UDP) && s != NULL && s->nat_rule.ptr != NULL &&
|
626
|
(s->nat_rule.ptr->action == PF_RDR ||
|