Projet

Général

Profil

Télécharger (19,7 ko) Statistiques
| Branche: | Révision:

univnautes-tools / patches / stable / 10 / dummynet.RELENG_10.diff @ 4ab3b90b

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 ||
(16-16/67)