Projet

Général

Profil

Télécharger (30,4 ko) Statistiques
| Branche: | Révision:

univnautes-tools / patches / stable / 10 / CP_speedup.diff @ 9d142a04

1
diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c
2
index 577d644..476f5da 100644
3
--- a/sbin/ipfw/ipfw2.c
4
+++ b/sbin/ipfw/ipfw2.c
5
@@ -4115,8 +4115,9 @@ ipfw_flush(int force)
6
 }
7
 
8
 
9
+static void table_list_entry(ipfw_table_xentry *);
10
 static void table_list(uint16_t num, int need_header);
11
-static void table_fill_xentry(char *arg, ipfw_table_xentry *xent);
12
+static void table_fill_xentry(int ac, char *av[], ipfw_table_xentry *xent);
13
 
14
 /*
15
  * This one handles all table-related commands
16
@@ -4169,29 +4170,9 @@ ipfw_table_handler(int ac, char *av[])
17
 	if (_substrcmp(*av, "add") == 0 ||
18
 	    _substrcmp(*av, "delete") == 0) {
19
 		do_add = **av == 'a';
20
-		ac--; av++;
21
-		if (!ac)
22
-			errx(EX_USAGE, "address required");
23
 
24
-		table_fill_xentry(*av, &xent);
25
+		table_fill_xentry(ac, av, &xent);
26
 
27
-		ac--; av++;
28
-		if (do_add && ac) {
29
-			unsigned int tval;
30
-			/* isdigit is a bit of a hack here.. */
31
-			if (strchr(*av, (int)'.') == NULL && isdigit(**av))  {
32
-				xent.value = strtoul(*av, NULL, 0);
33
-			} else {
34
-				if (lookup_host(*av, (struct in_addr *)&tval) == 0) {
35
-					/* The value must be stored in host order	 *
36
-					 * so that the values < 65k can be distinguished */
37
-		       			xent.value = ntohl(tval);
38
-				} else {
39
-					errx(EX_NOHOST, "hostname ``%s'' unknown", *av);
40
-				}
41
-			}
42
-		} else
43
-			xent.value = 0;
44
 		if (do_setcmd3(do_add ? IP_FW_TABLE_XADD : IP_FW_TABLE_XDEL,
45
 		    &xent, xent.len) < 0) {
46
 			/* If running silent, don't bomb out on these errors. */
47
@@ -4218,23 +4199,47 @@ ipfw_table_handler(int ac, char *av[])
48
 		do {
49
 			table_list(xent.tbl, is_all);
50
 		} while (++xent.tbl < a);
51
+	} else if (_substrcmp(*av, "entrystats") == 0) {
52
+		table_fill_xentry(ac, av, &xent);
53
+
54
+		if (do_setcmd3(IP_FW_TABLE_XLISTENTRY, &xent, xent.len) < 0) {
55
+			/* If running silent, don't bomb out on these errors. */
56
+			if (!(co.do_quiet))
57
+				err(EX_OSERR, "setsockopt(IP_FW_TABLE_XLISTENTRY)");
58
+		} else
59
+			table_list_entry(&xent);
60
+	} else if (_substrcmp(*av, "entryzerostats") == 0) {
61
+		table_fill_xentry(ac, av, &xent);
62
+
63
+		if (do_setcmd3(IP_FW_TABLE_XZEROENTRY, &xent, xent.len) < 0) {
64
+			/* If running silent, don't bomb out on these errors. */
65
+			if (!(co.do_quiet))
66
+				err(EX_OSERR, "setsockopt(IP_FW_TABLE_XZEROENTRY)");
67
+		}
68
 	} else
69
 		errx(EX_USAGE, "invalid table command %s", *av);
70
 }
71
 
72
 static void
73
-table_fill_xentry(char *arg, ipfw_table_xentry *xent)
74
+table_fill_xentry(int ac, char *av[], ipfw_table_xentry *xent)
75
 {
76
-	int addrlen, mask, masklen, type;
77
+	int addrlen, mask, masklen, type, do_add;
78
 	struct in6_addr *paddr;
79
 	uint32_t *pkey;
80
-	char *p;
81
+	char *p, *arg;
82
 	uint32_t key;
83
 
84
+	do_add = **av == 'a';
85
+	ac--; av++;
86
+	if (!ac)
87
+		errx(EX_USAGE, "address required");
88
+
89
 	mask = 0;
90
 	type = 0;
91
 	addrlen = 0;
92
 	masklen = 0;
93
+	arg = *av;
94
+	ac--; av++;
95
 
96
 	/* 
97
 	 * Let's try to guess type by agrument.
98
@@ -4245,7 +4250,18 @@ table_fill_xentry(char *arg, ipfw_table_xentry *xent)
99
 	 * 4) port, uid/gid or other u32 key (base 10 format)
100
 	 * 5) hostname
101
 	 */
102
-	paddr = &xent->k.addr6;
103
+	if (ac > 1 && av) {
104
+		if (_substrcmp(*av, "mac") == 0)  {
105
+			uint8_t _mask[8];
106
+
107
+			type = IPFW_TABLE_MIX;
108
+			get_mac_addr_mask(av[1], (uint8_t *)xent->k.mix.mac, _mask);
109
+			ac-=2; av+=2;
110
+			paddr = (struct in6_addr *)&xent->k.mix.addr;
111
+		} else
112
+			errx(EX_DATAERR, "wrong argument passed.");
113
+	} else
114
+		paddr = &xent->k.addr6;
115
 	if (ishexnumber(*arg) != 0 || *arg == ':') {
116
 		/* Remove / if exists */
117
 		if ((p = strchr(arg, '/')) != NULL) {
118
@@ -4258,8 +4274,11 @@ table_fill_xentry(char *arg, ipfw_table_xentry *xent)
119
 				errx(EX_DATAERR, "bad IPv4 mask width: %s",
120
 				    p + 1);
121
 
122
-			type = IPFW_TABLE_CIDR;
123
-			masklen = p ? mask : 32;
124
+			if (type == 0) {
125
+				type = IPFW_TABLE_CIDR;
126
+				masklen = p ? mask : 32;
127
+			} else
128
+				masklen = 32;
129
 			addrlen = sizeof(struct in_addr);
130
 		} else if (inet_pton(AF_INET6, arg, paddr) == 1) {
131
 			if (IN6_IS_ADDR_V4COMPAT(paddr))
132
@@ -4269,10 +4288,16 @@ table_fill_xentry(char *arg, ipfw_table_xentry *xent)
133
 				errx(EX_DATAERR, "bad IPv6 mask width: %s",
134
 				    p + 1);
135
 
136
-			type = IPFW_TABLE_CIDR;
137
-			masklen = p ? mask : 128;
138
+			if (type == 0) {
139
+				type = IPFW_TABLE_CIDR;
140
+				masklen = p ? mask : 128;
141
+			} else
142
+				masklen = 128;
143
 			addrlen = sizeof(struct in6_addr);
144
 		} else {
145
+			if (type != 0)
146
+				errx(EX_DATAERR, "Wrong value passed as address");
147
+
148
 			/* Port or any other key */
149
 			key = strtol(arg, &p, 10);
150
 			/* Skip non-base 10 entries like 'fa1' */
151
@@ -4304,9 +4329,91 @@ table_fill_xentry(char *arg, ipfw_table_xentry *xent)
152
 		addrlen = sizeof(struct in_addr);
153
 	}
154
 
155
+	if (do_add && ac) {
156
+		unsigned int tval;
157
+		/* isdigit is a bit of a hack here.. */
158
+		if (strchr(*av, (int)'.') == NULL && isdigit(**av))  {
159
+			xent->value = strtoul(*av, NULL, 0);
160
+		} else {
161
+			if (lookup_host(*av, (struct in_addr *)&tval) == 0) {
162
+				/* The value must be stored in host order	 *
163
+				 * so that the values < 65k can be distinguished */
164
+				xent->value = ntohl(tval);
165
+			} else {
166
+				errx(EX_NOHOST, "hostname ``%s'' unknown", *av);
167
+			}
168
+		}
169
+	} else
170
+		xent->value = 0;
171
+
172
 	xent->type = type;
173
 	xent->masklen = masklen;
174
-	xent->len = offsetof(ipfw_table_xentry, k) + addrlen;
175
+	if (IPFW_TABLE_MIX)
176
+		xent->len = offsetof(ipfw_table_xentry, k) + addrlen + ETHER_ADDR_LEN;
177
+	else
178
+		xent->len = offsetof(ipfw_table_xentry, k) + addrlen;
179
+}
180
+
181
+static void
182
+table_list_entry(ipfw_table_xentry *xent)
183
+{
184
+	struct in6_addr *addr6;
185
+	uint32_t tval;
186
+	char tbuf[128];
187
+
188
+	switch (xent->type) {
189
+	case IPFW_TABLE_CIDR:
190
+		/* IPv4 or IPv6 prefixes */
191
+		tval = xent->value;
192
+		addr6 = &xent->k.addr6;
193
+
194
+
195
+		if (IN6_IS_ADDR_V4COMPAT(addr6)) {
196
+			/* IPv4 address */
197
+			inet_ntop(AF_INET, &addr6->s6_addr32[3], tbuf, sizeof(tbuf));
198
+		} else {
199
+			/* IPv6 address */
200
+			inet_ntop(AF_INET6, addr6, tbuf, sizeof(tbuf));
201
+		}
202
+
203
+		if (co.do_value_as_ip) {
204
+			tval = htonl(tval);
205
+			printf("%s/%u %s %d %d %u\n", tbuf, xent->masklen,
206
+			    inet_ntoa(*(struct in_addr *)&tval), pr_u64(&xent->packets, 0), pr_u64(&xent->bytes, 0), xent->timestamp);
207
+		} else
208
+			printf("%s/%u %u %d %d %u\n", tbuf, xent->masklen, tval,
209
+			    pr_u64(&xent->packets, 0), pr_u64(&xent->bytes, 0), xent->timestamp);
210
+		break;
211
+	case IPFW_TABLE_INTERFACE:
212
+		/* Interface names */
213
+		tval = xent->value;
214
+		if (co.do_value_as_ip) {
215
+			tval = htonl(tval);
216
+			printf("%s %u %s %d %d %u\n", xent->k.iface, xent->masklen,
217
+			    inet_ntoa(*(struct in_addr *)&tval), pr_u64(&xent->packets, 0), pr_u64(&xent->bytes, 0), xent->timestamp);
218
+		} else
219
+			printf("%s %u %u %d %d %u\n", xent->k.iface, xent->masklen, tval,
220
+			    pr_u64(&xent->packets, 0), pr_u64(&xent->bytes, 0), xent->timestamp);
221
+
222
+		break;
223
+
224
+	case IPFW_TABLE_MIX:
225
+		/* mix of ip+mac */
226
+		tval = xent->value;
227
+
228
+		/* IPv4 address */
229
+		inet_ntop(AF_INET, &xent->k.mix.addr, tbuf, sizeof(tbuf));
230
+
231
+		if (co.do_value_as_ip) {
232
+			tval = htonl(tval);
233
+			printf("%s/%u %s %s %d %d %u\n", tbuf, xent->masklen - (8 * ETHER_ADDR_LEN), ether_ntoa((struct ether_addr *)xent->k.mix.mac),
234
+			    inet_ntoa(*(struct in_addr *)&tval),
235
+			    pr_u64(&xent->packets, 0), pr_u64(&xent->bytes, 0), xent->timestamp);
236
+		} else
237
+			printf("%s/%u %s %u %d %d %u\n", tbuf, xent->masklen - (8 * ETHER_ADDR_LEN), ether_ntoa((struct ether_addr *)xent->k.mix.mac), tval,
238
+			    pr_u64(&xent->packets, 0), pr_u64(&xent->bytes, 0), xent->timestamp);
239
+		break;
240
+	}
241
 }
242
 
243
 static void
244
@@ -4338,6 +4445,7 @@ table_list(uint16_t num, int need_header)
245
 	l = *a;
246
 	tbl = safe_calloc(1, l);
247
 	tbl->opheader.opcode = IP_FW_TABLE_XLIST;
248
+	tbl->opheader.ctxid = co.ctx;
249
 	tbl->tbl = num;
250
 	if (do_cmd(IP_FW3, tbl, (uintptr_t)&l) < 0)
251
 		err(EX_OSERR, "getsockopt(IP_FW_TABLE_XLIST)");
252
@@ -4377,6 +4485,23 @@ table_list(uint16_t num, int need_header)
253
 				    inet_ntoa(*(struct in_addr *)&tval));
254
 			} else
255
 				printf("%s %u\n", xent->k.iface, tval);
256
+
257
+			break;
258
+
259
+		case IPFW_TABLE_MIX:
260
+			/* mix of ip+mac */
261
+			tval = xent->value;
262
+
263
+			/* IPv4 address */
264
+			inet_ntop(AF_INET, &xent->k.mix.addr, tbuf, sizeof(tbuf));
265
+
266
+			if (co.do_value_as_ip) {
267
+				tval = htonl(tval);
268
+				printf("%s/%u %s %s\n", tbuf, xent->masklen - (8 * ETHER_ADDR_LEN), ether_ntoa((struct ether_addr *)xent->k.mix.mac),
269
+				    inet_ntoa(*(struct in_addr *)&tval));
270
+			} else
271
+				printf("%s/%u %s %u\n", tbuf, xent->masklen - (8 * ETHER_ADDR_LEN), ether_ntoa((struct ether_addr *)xent->k.mix.mac), tval);
272
+			break;
273
 		}
274
 
275
 		if (sz < xent->len)
276
diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h
277
index 14b08f5..7b64bf5 100644
278
--- a/sys/netinet/ip_fw.h
279
+++ b/sys/netinet/ip_fw.h
280
@@ -74,6 +74,8 @@ typedef struct _ip_fw3_opheader {
281
 #define	IP_FW_TABLE_XDEL	87	/* delete entry */
282
 #define	IP_FW_TABLE_XGETSIZE	88	/* get table size */
283
 #define	IP_FW_TABLE_XLIST	89	/* list table contents */
284
+#define	IP_FW_TABLE_XLISTENTRY	90	/* list one table entry contents */
285
+#define	IP_FW_TABLE_XZEROENTRY	91	/* zero one table entry stats */
286
 
287
 /*
288
  * The kernel representation of ipfw rules is made of a list of
289
@@ -600,7 +602,9 @@ struct _ipfw_dyn_rule {
290
 
291
 #define	IPFW_TABLE_CIDR		1	/* Table for holding IPv4/IPv6 prefixes */
292
 #define	IPFW_TABLE_INTERFACE	2	/* Table for holding interface names */
293
-#define	IPFW_TABLE_MAXTYPE	2	/* Maximum valid number */
294
+#define	IPFW_TABLE_MIX		3	/* Table for holding IPv4/mac entries */
295
+#define	IPFW_TABLE_MAC		4	/* Table for holding mac entries */
296
+#define	IPFW_TABLE_MAXTYPE	5	/* Maximum valid number */
297
 
298
 typedef struct	_ipfw_table_entry {
299
 	in_addr_t	addr;		/* network address		*/
300
@@ -617,9 +621,25 @@ typedef struct	_ipfw_table_xentry {
301
 	uint32_t	value;		/* value			*/
302
 	union {
303
 		/* Longest field needs to be aligned by 4-byte boundary	*/
304
+#ifndef ETHER_ADDR_LEN
305
+#define ETHER_ADDR_LEN 6
306
+#endif
307
+#if 0
308
+		struct {
309
+			struct ether_addr addr;
310
+			struct ether_addr mask;
311
+		} mac;
312
+#endif
313
+		struct {
314
+			struct in_addr addr;
315
+			u_char mac[ETHER_ADDR_LEN];
316
+		} mix;
317
 		struct in6_addr	addr6;	/* IPv6 address 		*/
318
 		char	iface[IF_NAMESIZE];	/* interface name	*/
319
 	} k;
320
+	uint64_t               bytes;
321
+	uint64_t               packets;
322
+	uint32_t               timestamp;
323
 } ipfw_table_xentry;
324
 
325
 typedef struct	_ipfw_table {
326
diff --git a/sys/netpfil/ipfw/ip_fw2.c b/sys/netpfil/ipfw/ip_fw2.c
327
index cd466bd..aa5a94d 100644
328
--- a/sys/netpfil/ipfw/ip_fw2.c
329
+++ b/sys/netpfil/ipfw/ip_fw2.c
330
@@ -358,8 +358,8 @@ iface_match(struct ifnet *ifp, ipfw_insn_if *cmd, struct ip_fw_chain *chain, uin
331
 	/* Check by name or by IP address */
332
 	if (cmd->name[0] != '\0') { /* match by name */
333
 		if (cmd->name[0] == '\1') /* use tablearg to match */
334
-			return ipfw_lookup_table_extended(chain, cmd->p.glob,
335
-				ifp->if_xname, tablearg, IPFW_TABLE_INTERFACE);
336
+			return (ipfw_lookup_table_extended(chain, cmd->p.glob,
337
+				ifp->if_xname, tablearg, IPFW_TABLE_INTERFACE) != NULL);
338
 		/* Check name */
339
 		if (cmd->p.glob) {
340
 			if (fnmatch(cmd->name, ifp->if_xname, 0) == 0)
341
@@ -955,6 +955,7 @@ ipfw_chk(struct ip_fw_args *args)
342
 	int dyn_dir = MATCH_UNKNOWN;
343
 	ipfw_dyn_rule *q = NULL;
344
 	struct ip_fw_chain *chain = &V_layer3_chain;
345
+	void *tblent = NULL;
346
 
347
 	/*
348
 	 * We store in ulp a pointer to the upper layer protocol header.
349
@@ -1288,6 +1289,7 @@ do {								\
350
 			continue;
351
 
352
 		skip_or = 0;
353
+		tblent = NULL;
354
 		for (l = f->cmd_len, cmd = f->cmd ; l > 0 ;
355
 		    l -= cmdlen, cmd += cmdlen) {
356
 			int match;
357
@@ -1402,7 +1404,7 @@ do {								\
358
 				break;
359
 
360
 			case O_IN:	/* "out" is "not in" */
361
-				match = (oif == NULL);
362
+				match = (args->dir == DIR_IN);
363
 				break;
364
 
365
 			case O_LAYER2:
366
@@ -1437,7 +1439,35 @@ do {								\
367
 
368
 			case O_IP_SRC_LOOKUP:
369
 			case O_IP_DST_LOOKUP:
370
-				if (is_ipv4) {
371
+				if (args->eh) {
372
+					struct {
373
+						struct in_addr addr;
374
+						char mac[ETHER_ADDR_LEN];
375
+					} mix;
376
+					void *pkey = &mix;
377
+			    		uint32_t v = 0;
378
+
379
+					if (is_ipv4) {
380
+						mix.addr.s_addr = (cmd->opcode == O_IP_DST_LOOKUP) ?
381
+							dst_ip.s_addr : src_ip.s_addr;
382
+						memcpy(mix.mac,(cmd->opcode == O_IP_DST_LOOKUP) ?
383
+							args->eh->ether_dhost :
384
+							args->eh->ether_shost, ETHER_ADDR_LEN);
385
+						tblent = ipfw_lookup_table_extended(chain,
386
+								cmd->arg1, pkey, &v,
387
+								IPFW_TABLE_MIX);
388
+						if (tblent == NULL) {
389
+							match = 0;
390
+							break;
391
+						} else
392
+							match = 1;
393
+						if (cmdlen == F_INSN_SIZE(ipfw_insn_u32))
394
+							match = ((ipfw_insn_u32 *)cmd)->d[0] == v;
395
+						if (match)
396
+							tablearg = v;
397
+
398
+					}
399
+				} else if (is_ipv4) {
400
 				    uint32_t key =
401
 					(cmd->opcode == O_IP_DST_LOOKUP) ?
402
 					    dst_ip.s_addr : src_ip.s_addr;
403
@@ -1497,9 +1527,9 @@ do {								\
404
 					uint32_t v = 0;
405
 					void *pkey = (cmd->opcode == O_IP_DST_LOOKUP) ?
406
 						&args->f_id.dst_ip6: &args->f_id.src_ip6;
407
-					match = ipfw_lookup_table_extended(chain,
408
+					match = (ipfw_lookup_table_extended(chain,
409
 							cmd->arg1, pkey, &v,
410
-							IPFW_TABLE_CIDR);
411
+							IPFW_TABLE_CIDR) != NULL);
412
 					if (cmdlen == F_INSN_SIZE(ipfw_insn_u32))
413
 						match = ((ipfw_insn_u32 *)cmd)->d[0] == v;
414
 					if (match)
415
@@ -2314,8 +2344,7 @@ do {								\
416
 				break;
417
 
418
 			case O_FORWARD_IP:
419
-				if (args->eh)	/* not valid on layer2 pkts */
420
-					break;
421
+				if (!args->eh)	{/* not valid on layer2 pkts */
422
 				if (q == NULL || q->rule != f ||
423
 				    dyn_dir == MATCH_FORWARD) {
424
 				    struct sockaddr_in *sa;
425
@@ -2330,6 +2359,48 @@ do {								\
426
 					args->next_hop = sa;
427
 				    }
428
 				}
429
+				} else if (args->eh) {
430
+					struct m_tag *fwd_tag;
431
+					struct sockaddr_in *sa;
432
+					u_short sum;
433
+
434
+					/*
435
+					* Checksum correct? (from ip_fastfwd.c)
436
+					*/
437
+					if (m->m_pkthdr.csum_flags & CSUM_IP_CHECKED)
438
+						sum = !(m->m_pkthdr.csum_flags & CSUM_IP_VALID);
439
+					else {
440
+						if (hlen == sizeof(struct ip))
441
+							sum = in_cksum_hdr(ip);
442
+						else
443
+							sum = in_cksum(m, hlen);
444
+					}
445
+					if (sum) {
446
+						IPSTAT_INC(ips_badsum);
447
+						retval = IP_FW_DENY;
448
+						break;
449
+					}
450
+
451
+					/*
452
+					* Remember that we have checked the IP header and found it valid.
453
+					*/
454
+					m->m_pkthdr.csum_flags |= (CSUM_IP_CHECKED | CSUM_IP_VALID);
455
+
456
+					sa = &(((ipfw_insn_sa *)cmd)->sa);
457
+					fwd_tag = m_tag_get(PACKET_TAG_IPFORWARD,
458
+						sizeof(struct sockaddr_in), M_NOWAIT);
459
+					if (fwd_tag == NULL)
460
+						retval = IP_FW_DENY;
461
+					else {
462
+						bcopy(sa, (fwd_tag+1), sizeof(struct sockaddr_in));
463
+						m_tag_prepend(m, fwd_tag);
464
+
465
+						if (in_localip(sa->sin_addr))
466
+							m->m_flags |= M_FASTFWD_OURS;
467
+						m->m_flags |= M_IP_NEXTHOP;
468
+					}
469
+				}
470
+
471
 				retval = IP_FW_PASS;
472
 				l = 0;          /* exit inner loop */
473
 				done = 1;       /* exit outer loop */
474
@@ -2337,8 +2408,7 @@ do {								\
475
 
476
 #ifdef INET6
477
 			case O_FORWARD_IP6:
478
-				if (args->eh)	/* not valid on layer2 pkts */
479
-					break;
480
+				if (args->eh) {	/* not valid on layer2 pkts */
481
 				if (q == NULL || q->rule != f ||
482
 				    dyn_dir == MATCH_FORWARD) {
483
 					struct sockaddr_in6 *sin6;
484
@@ -2346,6 +2416,24 @@ do {								\
485
 					sin6 = &(((ipfw_insn_sa6 *)cmd)->sa);
486
 					args->next_hop6 = sin6;
487
 				}
488
+				} else if (args->eh) {
489
+					struct m_tag *fwd_tag;
490
+					struct sockaddr_in6 *sin6;
491
+
492
+					sin6 = &(((ipfw_insn_sa6 *)cmd)->sa);
493
+					fwd_tag = m_tag_get(PACKET_TAG_IPFORWARD,
494
+						sizeof(struct sockaddr_in6), M_NOWAIT);
495
+					if (fwd_tag == NULL)
496
+						retval = IP_FW_DENY;
497
+					else {
498
+						bcopy(sin6, (fwd_tag+1), sizeof(struct sockaddr_in6));
499
+						m_tag_prepend(m, fwd_tag);
500
+
501
+						if (in6_localip(&sin6->sin6_addr))
502
+							m->m_flags |= M_FASTFWD_OURS;
503
+						m->m_flags |= M_IP6_NEXTHOP;
504
+					}
505
+				}
506
 				retval = IP_FW_PASS;
507
 				l = 0;		/* exit inner loop */
508
 				done = 1;	/* exit outer loop */
509
@@ -2505,6 +2593,8 @@ do {								\
510
 		struct ip_fw *rule = chain->map[f_pos];
511
 		/* Update statistics */
512
 		IPFW_INC_RULE_COUNTER(rule, pktlen);
513
+		if (tblent != NULL)
514
+			ipfw_count_table_xentry_stats(tblent, pktlen);
515
 	} else {
516
 		retval = IP_FW_DENY;
517
 		printf("ipfw: ouch!, skip past end of rules, denying packet\n");
518
diff --git a/sys/netpfil/ipfw/ip_fw_pfil.c b/sys/netpfil/ipfw/ip_fw_pfil.c
519
index d1202ff..6526991 100644
520
--- a/sys/netpfil/ipfw/ip_fw_pfil.c
521
+++ b/sys/netpfil/ipfw/ip_fw_pfil.c
522
@@ -143,8 +143,9 @@ again:
523
 	}
524
 
525
 	args.m = *m0;
526
-	args.oif = dir == DIR_OUT ? ifp : NULL;
527
+	args.oif = ifp;
528
 	args.inp = inp;
529
+	args.dir = dir;
530
 
531
 	ipfw = ipfw_chk(&args);
532
 	*m0 = args.m;
533
@@ -314,9 +315,8 @@ ipfw_check_frame(void *arg, struct mbuf **m0, struct ifnet *dst, int dir,
534
 		/* XXX can we free it after use ? */
535
 		mtag->m_tag_id = PACKET_TAG_NONE;
536
 		r = (struct ipfw_rule_ref *)(mtag + 1);
537
-		if (r->info & IPFW_ONEPASS)
538
-			return (0);
539
-		args.rule = *r;
540
+		m_tag_delete(*m0, mtag);
541
+		return (0);
542
 	}
543
 
544
 	/* I need some amt of data to be contiguous */
545
@@ -333,12 +333,15 @@ ipfw_check_frame(void *arg, struct mbuf **m0, struct ifnet *dst, int dir,
546
 	save_eh = *eh;			/* save copy for restore below */
547
 	m_adj(m, ETHER_HDR_LEN);	/* strip ethernet header */
548
 
549
+	dir = dir == PFIL_IN ? DIR_IN : DIR_OUT;
550
+
551
 	args.m = m;		/* the packet we are looking at		*/
552
-	args.oif = dir == PFIL_OUT ? dst: NULL;	/* destination, if any	*/
553
+	args.oif = dst;		/* destination, if any	*/
554
 	args.next_hop = NULL;	/* we do not support forward yet	*/
555
 	args.next_hop6 = NULL;	/* we do not support forward yet	*/
556
 	args.eh = &save_eh;	/* MAC header for bridged/MAC packets	*/
557
 	args.inp = NULL;	/* used by ipfw uid/gid/jail rules	*/
558
+	args.dir = dir;         /* pfSense addition                     */
559
 	i = ipfw_chk(&args);
560
 	m = args.m;
561
 	if (m != NULL) {
562
@@ -369,13 +372,12 @@ ipfw_check_frame(void *arg, struct mbuf **m0, struct ifnet *dst, int dir,
563
 
564
 	case IP_FW_DUMMYNET:
565
 		ret = EACCES;
566
-		int dir;
567
 
568
 		if (ip_dn_io_ptr == NULL)
569
 			break; /* i.e. drop */
570
 
571
 		*m0 = NULL;
572
-		dir = PROTO_LAYER2 | (dst ? DIR_OUT : DIR_IN);
573
+		dir = PROTO_LAYER2 | dir;
574
 		ip_dn_io_ptr(&m, dir, &args);
575
 		return 0;
576
 
577
diff --git a/sys/netpfil/ipfw/ip_fw_private.h b/sys/netpfil/ipfw/ip_fw_private.h
578
index a8d7eea..1d8a4aa 100644
579
--- a/sys/netpfil/ipfw/ip_fw_private.h
580
+++ b/sys/netpfil/ipfw/ip_fw_private.h
581
@@ -101,6 +101,7 @@ struct ip_fw_args {
582
 
583
 	struct ipfw_flow_id f_id;	/* grabbed from IP header	*/
584
 	//uint32_t	cookie;		/* a cookie depending on rule action */
585
+	uint32_t        dir;            /* direction */
586
 	struct inpcb	*inp;
587
 
588
 	struct _ip6dn_args	dummypar; /* dummynet->ip6_output */
589
@@ -304,8 +305,11 @@ void ipfw_reap_rules(struct ip_fw *head);
590
 struct radix_node;
591
 int ipfw_lookup_table(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr,
592
     uint32_t *val);
593
-int ipfw_lookup_table_extended(struct ip_fw_chain *ch, uint16_t tbl, void *paddr,
594
+void *ipfw_lookup_table_extended(struct ip_fw_chain *ch, uint16_t tbl, void *paddr,
595
     uint32_t *val, int type);
596
+void ipfw_count_table_xentry_stats(void *, int);
597
+int ipfw_zero_table_xentry_stats(struct ip_fw_chain *, ipfw_table_xentry *);
598
+int ipfw_lookup_table_xentry(struct ip_fw_chain *, ipfw_table_xentry *);
599
 int ipfw_init_tables(struct ip_fw_chain *ch);
600
 void ipfw_destroy_tables(struct ip_fw_chain *ch);
601
 int ipfw_flush_table(struct ip_fw_chain *ch, uint16_t tbl);
602
diff --git a/sys/netpfil/ipfw/ip_fw_sockopt.c b/sys/netpfil/ipfw/ip_fw_sockopt.c
603
index cb9c89c..491116e 100644
604
--- a/sys/netpfil/ipfw/ip_fw_sockopt.c
605
+++ b/sys/netpfil/ipfw/ip_fw_sockopt.c
606
@@ -1245,6 +1245,47 @@ ipfw_ctl(struct sockopt *sopt)
607
 		}
608
 		break;
609
 
610
+	case IP_FW_TABLE_XZEROENTRY: /* IP_FW3 */
611
+		{
612
+			ipfw_table_xentry *xent = (ipfw_table_xentry *)(op3 + 1);
613
+
614
+			/* Check minimum header size */
615
+			if (IP_FW3_OPLENGTH(sopt) < offsetof(ipfw_table_xentry, k)) {
616
+				error = EINVAL;
617
+				break;
618
+			}
619
+
620
+			/* Check if len field is valid */
621
+			if (xent->len > sizeof(ipfw_table_xentry)) {
622
+				error = EINVAL;
623
+				break;
624
+			}
625
+			
626
+			error = ipfw_zero_table_xentry_stats(chain, xent);
627
+		}
628
+		break;
629
+
630
+	case IP_FW_TABLE_XLISTENTRY: /* IP_FW3 */
631
+		{
632
+			ipfw_table_xentry *xent = (ipfw_table_xentry *)(op3 + 1);
633
+
634
+			/* Check minimum header size */
635
+			if (IP_FW3_OPLENGTH(sopt) < offsetof(ipfw_table_xentry, k)) {
636
+				error = EINVAL;
637
+				break;
638
+			}
639
+
640
+			/* Check if len field is valid */
641
+			if (xent->len > sizeof(ipfw_table_xentry)) {
642
+				error = EINVAL;
643
+				break;
644
+			}
645
+			
646
+			error = ipfw_lookup_table_xentry(chain, xent);
647
+			xent->timestamp += boottime.tv_sec;
648
+		}
649
+		break;
650
+
651
 	case IP_FW_TABLE_XLIST: /* IP_FW3 */
652
 		{
653
 			ipfw_xtable *tbl;
654
diff --git a/sys/netpfil/ipfw/ip_fw_table.c b/sys/netpfil/ipfw/ip_fw_table.c
655
index 95cff5c..a6d0f79 100644
656
--- a/sys/netpfil/ipfw/ip_fw_table.c
657
+++ b/sys/netpfil/ipfw/ip_fw_table.c
658
@@ -75,6 +75,9 @@ struct table_entry {
659
 	struct radix_node	rn[2];
660
 	struct sockaddr_in	addr, mask;
661
 	u_int32_t		value;
662
+	u_int32_t               timestamp;
663
+	u_int64_t               bytes;
664
+	u_int64_t               packets;
665
 };
666
 
667
 struct xaddr_iface {
668
@@ -83,6 +86,22 @@ struct xaddr_iface {
669
 	char 		ifname[IF_NAMESIZE];	/* Interface name */
670
 };
671
 
672
+#if 0
673
+struct xaddr_mac {
674
+	uint8_t		mac_len;		/* length of this struct */
675
+	uint8_t		pad[7];		/* Align name */
676
+	struct ether_addr mac;
677
+};
678
+#endif
679
+
680
+struct xaddr_mix {
681
+	uint8_t		mix_len;		/* length of this struct */
682
+	sa_family_t     sin_family;
683
+        uint8_t		pad[6];
684
+        struct  in_addr sin_addr;
685
+	u_char	mac[ETHER_ADDR_LEN];
686
+};
687
+
688
 struct table_xentry {
689
 	struct radix_node	rn[2];
690
 	union {
691
@@ -90,14 +109,25 @@ struct table_xentry {
692
 		struct sockaddr_in6	addr6;
693
 #endif
694
 		struct xaddr_iface	iface;
695
+#if 0
696
+		struct xaddr_mac	mac;
697
+#endif
698
+		struct xaddr_mix	mix;
699
 	} a;
700
 	union {
701
 #ifdef INET6
702
 		struct sockaddr_in6	mask6;
703
 #endif
704
 		struct xaddr_iface	ifmask;
705
+#if 0
706
+		struct xaddr_mac	macmask;
707
+#endif
708
+		struct xaddr_mix	mixmask;
709
 	} m;
710
 	u_int32_t		value;
711
+	u_int32_t               timestamp;
712
+	u_int64_t               bytes;
713
+	u_int64_t               packets;
714
 };
715
 
716
 /*
717
@@ -117,10 +147,17 @@ struct table_xentry {
718
 #define KEY_LEN_INET	(offsetof(struct sockaddr_in, sin_addr) + sizeof(in_addr_t))
719
 #define KEY_LEN_INET6	(offsetof(struct sockaddr_in6, sin6_addr) + sizeof(struct in6_addr))
720
 #define KEY_LEN_IFACE	(offsetof(struct xaddr_iface, ifname))
721
+#define KEY_LEN_MIX	(offsetof(struct xaddr_mix, sin_addr) + sizeof(in_addr_t) + ETHER_ADDR_LEN)
722
+#if 0
723
+#define KEY_LEN_MAC	(offsetof(struct xaddr_mac, mac) + ETHER_ADDR_LEN)
724
+#endif
725
 
726
 #define OFF_LEN_INET	(8 * offsetof(struct sockaddr_in, sin_addr))
727
 #define OFF_LEN_INET6	(8 * offsetof(struct sockaddr_in6, sin6_addr))
728
 #define OFF_LEN_IFACE	(8 * offsetof(struct xaddr_iface, ifname))
729
+#if 0
730
+#define OFF_LEN_MAC	(8 * offsetof(struct xaddr_mac, mac))
731
+#endif
732
 
733
 
734
 #ifdef INET6
735
@@ -233,6 +270,52 @@ ipfw_add_table_entry(struct ip_fw_chain *ch, uint16_t tbl, void *paddr,
736
 		mask_ptr = NULL;
737
 		break;
738
 
739
+#if 0
740
+	case IPFW_TABLE_MAC:
741
+		int i;
742
+
743
+		xent = malloc(sizeof(*xent), M_IPFW_TBL, M_WAITOK | M_ZERO);
744
+		xent->value = value;
745
+		/* Set 'total' structure length */
746
+		KEY_LEN(xent->a.mac) = KEY_LEN_MAC;
747
+		KEY_LEN(xent->m.macmask) = KEY_LEN_MAC;
748
+		/* Set offset of address in bits */
749
+		offset = OFF_LEN_MAC;
750
+		xent->a.mac = (struct ether_addr)(*paddr);
751
+		xent->m.mac = (struct ether_addr)(*(((struct ether_addr *)paddr) + 1));
752
+		for (i = 0; i < ETHER_ADDR_LEN; i++)
753
+			xent->a.mac.octet[i] &= xent->m.mac.octet[i];
754
+		/* Set pointers */
755
+		rnh_ptr = &ch->xtables[tbl];
756
+		ent_ptr = xent;
757
+		addr_ptr = (struct sockaddr *)&xent->a.mac;
758
+		mask_ptr = (struct sockaddr *)&xent->m.macmask;
759
+		break;
760
+#endif
761
+
762
+	case IPFW_TABLE_MIX:
763
+		if ((plen - ETHER_ADDR_LEN) != sizeof(in_addr_t))
764
+			return (EINVAL);
765
+
766
+		xent = malloc(sizeof(*xent), M_IPFW_TBL, M_WAITOK | M_ZERO);
767
+		xent->value = value;
768
+		/* Set 'total' structure length */
769
+		KEY_LEN(xent->a.mix) = KEY_LEN_MIX;
770
+		KEY_LEN(xent->m.mixmask) = KEY_LEN_MIX;
771
+		/* Set offset of IPv4 address in bits */
772
+		offset = OFF_LEN_INET;
773
+		/* XXX: Needs to be fixed */
774
+		memcpy(&xent->a.mix.sin_addr, paddr, ETHER_ADDR_LEN + sizeof(struct in_addr));
775
+		/* Only full ips /32 and full masks supported for mac */
776
+		memset(&xent->m.mixmask.sin_addr, 0xFF, sizeof(struct in_addr));
777
+		memset(xent->m.mixmask.mac, 0xFF, ETHER_ADDR_LEN);
778
+		/* Set pointers */
779
+		rnh_ptr = &ch->xtables[tbl];
780
+		ent_ptr = xent;
781
+		addr_ptr = (struct sockaddr *)&xent->a.mix;
782
+		mask_ptr = NULL;
783
+		break;
784
+
785
 	default:
786
 		return (EINVAL);
787
 	}
788
@@ -367,6 +450,41 @@ ipfw_del_table_entry(struct ip_fw_chain *ch, uint16_t tbl, void *paddr,
789
 
790
 		break;
791
 
792
+#if 0
793
+	case IPFW_TABLE_MAC:
794
+		struct xaddr_mac mac, macmask;
795
+		memset(&mac, 0, sizeof(mac));
796
+		memset(&macmask, 0, sizeof(macmask));
797
+
798
+		/* Set 'total' structure length */
799
+                KEY_LEN(mac) = KEY_LEN_MAC;
800
+		mac.mac.mac = (struct ether_addr)(*paddr);
801
+                KEY_LEN(macmask) = KEY_LEN_MAC;
802
+		macmask.mac.macmask = (struct ether_addr)(*(((struct ether_addr *)paddr) + 1));
803
+		for (i = 0; i < ETHER_ADDR_LEN; i++)
804
+			mac.mac.octet[i] &= macmask.mac.octet[i];
805
+		rnh_ptr = &ch->xtables[tbl];
806
+		sa_ptr = (struct sockaddr *)&mac;
807
+		mask_ptr = (struct sockaddr *)&macmask;
808
+
809
+		break;
810
+#endif
811
+
812
+	case IPFW_TABLE_MIX:
813
+		if (mlen > (32 + ETHER_ADDR_LEN))
814
+			return (EINVAL);
815
+		struct xaddr_mix mix;
816
+		memset(&mix, 0, sizeof(mix));
817
+
818
+		/* Set 'total' structure length */
819
+		KEY_LEN(mix) = KEY_LEN_MIX;
820
+		memcpy(&mix.sin_addr, paddr, sizeof(struct in_addr) + ETHER_ADDR_LEN);
821
+		rnh_ptr = &ch->xtables[tbl];
822
+		sa_ptr = (struct sockaddr *)&mix;
823
+		mask_ptr = NULL;
824
+
825
+		break;
826
+
827
 	default:
828
 		return (EINVAL);
829
 	}
830
@@ -552,7 +670,150 @@ ipfw_lookup_table(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr,
831
 	return (0);
832
 }
833
 
834
+void
835
+ipfw_count_table_xentry_stats(void *arg, int pktlen)
836
+{
837
+	ipfw_table_xentry *xent= arg;
838
+
839
+	xent->packets++;
840
+	xent->bytes += pktlen;
841
+	xent->timestamp = time_uptime;
842
+}
843
+
844
 int
845
+ipfw_zero_table_xentry_stats(struct ip_fw_chain *ch, ipfw_table_xentry *arg)
846
+{
847
+	struct radix_node_head *rnh;
848
+	struct table_xentry *xent;
849
+	struct sockaddr_in6 sa6;
850
+	struct xaddr_iface iface;
851
+	struct xaddr_mix xm;
852
+
853
+	if (arg->tbl >= V_fw_tables_max)
854
+		return (0);
855
+	if ((rnh = ch->xtables[arg->tbl]) == NULL)
856
+		return (0);
857
+
858
+	switch (arg->type) {
859
+	case IPFW_TABLE_CIDR:
860
+		KEY_LEN(sa6) = KEY_LEN_INET6;
861
+		memcpy(&sa6.sin6_addr, &arg->k.addr6, sizeof(struct in6_addr));
862
+		xent = (struct table_xentry *)(rnh->rnh_lookup(&sa6, NULL, rnh));
863
+		break;
864
+
865
+	case IPFW_TABLE_INTERFACE:
866
+		KEY_LEN(iface) = KEY_LEN_IFACE +
867
+		    strlcpy(iface.ifname, arg->k.iface, IF_NAMESIZE) + 1;
868
+		/* Assume direct match */
869
+		/* FIXME: Add interface pattern matching */
870
+		xent = (struct table_xentry *)(rnh->rnh_lookup(&iface, NULL, rnh));
871
+		break;
872
+
873
+#if 0
874
+	case IPFW_TABLE_MAC:
875
+	{
876
+		struct xaddr_mac mac;
877
+
878
+		KEY_LEN(mac) = KEY_LEN_MAC;
879
+		&mac.mac = arg->k.mac;
880
+		xent = (struct table_xentry *)(rnh->rnh_lookup(&mac, NULL, rnh));
881
+	}
882
+		break;
883
+#endif
884
+
885
+	case IPFW_TABLE_MIX:
886
+		KEY_LEN(xm) = KEY_LEN_MIX;
887
+		memcpy(&xm.sin_addr, &arg->k.mix.addr, sizeof(struct in_addr));
888
+		memcpy(&xm.mac, arg->k.mix.mac, ETHER_ADDR_LEN);
889
+		xent = (struct table_xentry *)(rnh->rnh_lookup(&xm, NULL, rnh));
890
+		break;
891
+
892
+	default:
893
+		return (0);
894
+	}
895
+
896
+	if (xent != NULL) {
897
+		xent->bytes = 0;
898
+		xent->packets = 0;
899
+		xent->timestamp = time_uptime;
900
+		
901
+		return (1);
902
+	}
903
+	return (0);
904
+}
905
+
906
+int
907
+ipfw_lookup_table_xentry(struct ip_fw_chain *ch, ipfw_table_xentry *arg)
908
+{
909
+	struct radix_node_head *rnh;
910
+	struct table_xentry *xent;
911
+
912
+	if (arg->tbl >= V_fw_tables_max)
913
+		return (0);
914
+	if ((rnh = ch->xtables[arg->tbl]) == NULL)
915
+		return (0);
916
+
917
+	switch (arg->type) {
918
+	case IPFW_TABLE_CIDR:
919
+	{
920
+		struct sockaddr_in6 sa6;
921
+		KEY_LEN(sa6) = KEY_LEN_INET6;
922
+		memcpy(&sa6.sin6_addr, &arg->k.addr6, sizeof(struct in6_addr));
923
+		xent = (struct table_xentry *)(rnh->rnh_lookup(&sa6, NULL, rnh));
924
+	}
925
+		break;
926
+
927
+	case IPFW_TABLE_INTERFACE:
928
+	{
929
+		struct xaddr_iface iface;
930
+
931
+		KEY_LEN(iface) = KEY_LEN_IFACE +
932
+		    strlcpy(iface.ifname, arg->k.iface, IF_NAMESIZE) + 1;
933
+		/* Assume direct match */
934
+		/* FIXME: Add interface pattern matching */
935
+		xent = (struct table_xentry *)(rnh->rnh_lookup(&iface, NULL, rnh));
936
+	}
937
+		break;
938
+
939
+#if 0
940
+	case IPFW_TABLE_MAC:
941
+	{
942
+		struct xaddr_mac mac;
943
+
944
+		KEY_LEN(mac) = KEY_LEN_MAC;
945
+		mac.mac = arg->k.mac.addr;
946
+		xent = (struct table_xentry *)(rnh->rnh_lookup(&mac, NULL, rnh));
947
+	}
948
+		break;
949
+#endif
950
+
951
+	case IPFW_TABLE_MIX:
952
+	{
953
+		struct xaddr_mix xm;
954
+
955
+		KEY_LEN(xm) = KEY_LEN_MIX;
956
+		memcpy(&xm.sin_addr, &arg->k.mix.addr, sizeof(struct in_addr));
957
+		memcpy(&xm.mac, arg->k.mix.mac, ETHER_ADDR_LEN);
958
+		xent = (struct table_xentry *)(rnh->rnh_lookup(&xm, NULL, rnh));
959
+	}
960
+		break;
961
+
962
+	default:
963
+		return (0);
964
+	}
965
+
966
+	if (xent != NULL) {
967
+		arg->bytes = xent->bytes;
968
+		arg->packets = xent->packets;
969
+		arg->value = xent->value;
970
+		arg->timestamp = xent->timestamp;
971
+		
972
+		return (1);
973
+	}
974
+	return (0);
975
+}
976
+
977
+void *
978
 ipfw_lookup_table_extended(struct ip_fw_chain *ch, uint16_t tbl, void *paddr,
979
     uint32_t *val, int type)
980
 {
981
@@ -562,9 +823,9 @@ ipfw_lookup_table_extended(struct ip_fw_chain *ch, uint16_t tbl, void *paddr,
982
 	struct xaddr_iface iface;
983
 
984
 	if (tbl >= V_fw_tables_max)
985
-		return (0);
986
+		return (NULL);
987
 	if ((rnh = ch->xtables[tbl]) == NULL)
988
-		return (0);
989
+		return (NULL);
990
 
991
 	switch (type) {
992
 	case IPFW_TABLE_CIDR:
993
@@ -581,15 +842,37 @@ ipfw_lookup_table_extended(struct ip_fw_chain *ch, uint16_t tbl, void *paddr,
994
 		xent = (struct table_xentry *)(rnh->rnh_lookup(&iface, NULL, rnh));
995
 		break;
996
 
997
+#if 0
998
+	case IPFW_TABLE_MAC:
999
+	{
1000
+		struct xaddr_mac mac;
1001
+
1002
+		KEY_LEN(mac) = KEY_LEN_MAC;
1003
+		mac.mac = (struct ether_addr)(*paddr);
1004
+		xent = (struct table_xentry *)(rnh->rnh_lookup(&mac, NULL, rnh));
1005
+	}
1006
+		break;
1007
+#endif
1008
+
1009
+	case IPFW_TABLE_MIX:
1010
+	{
1011
+		struct xaddr_mix xm;
1012
+
1013
+		KEY_LEN(xm) = KEY_LEN_MIX;
1014
+		memcpy(((char *)&xm.sin_addr), paddr, sizeof(struct in_addr) + ETHER_ADDR_LEN);
1015
+		xent = (struct table_xentry *)(rnh->rnh_lookup(&xm, NULL, rnh));
1016
+	}
1017
+		break;
1018
+
1019
 	default:
1020
-		return (0);
1021
+		return (NULL);
1022
 	}
1023
 
1024
 	if (xent != NULL) {
1025
 		*val = xent->value;
1026
-		return (1);
1027
+		return (xent);
1028
 	}
1029
-	return (0);
1030
+	return (NULL);
1031
 }
1032
 
1033
 static int
1034
@@ -698,6 +981,9 @@ dump_table_xentry_base(struct radix_node *rn, void *arg)
1035
 	/* Save IPv4 address as deprecated IPv6 compatible */
1036
 	xent->k.addr6.s6_addr32[3] = n->addr.sin_addr.s_addr;
1037
 	xent->value = n->value;
1038
+	xent->bytes = n->bytes;
1039
+	xent->packets = n->packets;
1040
+	xent->timestamp = n->timestamp;
1041
 	tbl->cnt++;
1042
 	return (0);
1043
 }
1044
@@ -735,12 +1021,31 @@ dump_table_xentry_extended(struct radix_node *rn, void *arg)
1045
 		memcpy(&xent->k, &n->a.iface.ifname, IF_NAMESIZE);
1046
 		break;
1047
 	
1048
+#if 0
1049
+	case IPFW_TABLE_MAC:
1050
+		/* Assume exact mask */
1051
+		xent->masklen = 8 * ETHER_ADDR_LEN;
1052
+		xent->k.mac.addr = n->a.mac.mac;
1053
+		xent->k.mac.mask = n->m.mac.mac;
1054
+		break;
1055
+#endif
1056
+	
1057
+	case IPFW_TABLE_MIX:
1058
+		/* Assume exact mask */
1059
+		xent->masklen = 8 * (ETHER_ADDR_LEN + sizeof(struct in_addr));
1060
+		memcpy(&xent->k.mix.addr, &n->a.mix.sin_addr, sizeof(struct in_addr));
1061
+		memcpy(xent->k.mix.mac, &n->a.mix.mac, ETHER_ADDR_LEN);
1062
+		break;
1063
+
1064
 	default:
1065
 		/* unknown, skip entry */
1066
 		return (0);
1067
 	}
1068
 
1069
 	xent->value = n->value;
1070
+	xent->bytes = n->bytes;
1071
+	xent->packets = n->packets;
1072
+	xent->timestamp = n->timestamp;
1073
 	tbl->cnt++;
1074
 	return (0);
1075
 }
(2-2/64)