Projet

Général

Profil

Télécharger (36,5 ko) Statistiques
| Branche: | Révision:

univnautes-tools / patches / stable / 10 / CP_speedup.diff @ dc10b283

1
diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c
2
index 577d644..48dbc2a 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,19 +4199,41 @@ 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
@@ -4245,7 +4248,20 @@ table_fill_xentry(char *arg, ipfw_table_xentry *xent)
93
 	 * 4) port, uid/gid or other u32 key (base 10 format)
94
 	 * 5) hostname
95
 	 */
96
-	paddr = &xent->k.addr6;
97
+	if (ac > 1 && av && _substrcmp(*av, "mac") == 0) {
98
+		uint8_t _mask[8];
99
+
100
+		type = IPFW_TABLE_MIX;
101
+		get_mac_addr_mask(av[1], (uint8_t *)xent->k.mix.mac, _mask);
102
+		ac-=2; av+=2;
103
+		if (ac <= 0)
104
+			errx(EX_DATAERR, "wrong argument passed.");
105
+
106
+		paddr = (struct in6_addr *)&xent->k.mix.addr;
107
+	} else
108
+		paddr = &xent->k.addr6;
109
+
110
+	arg = *av;
111
 	if (ishexnumber(*arg) != 0 || *arg == ':') {
112
 		/* Remove / if exists */
113
 		if ((p = strchr(arg, '/')) != NULL) {
114
@@ -4258,7 +4274,8 @@ table_fill_xentry(char *arg, ipfw_table_xentry *xent)
115
 				errx(EX_DATAERR, "bad IPv4 mask width: %s",
116
 				    p + 1);
117
 
118
-			type = IPFW_TABLE_CIDR;
119
+			if (type == 0)
120
+				type = IPFW_TABLE_CIDR;
121
 			masklen = p ? mask : 32;
122
 			addrlen = sizeof(struct in_addr);
123
 		} else if (inet_pton(AF_INET6, arg, paddr) == 1) {
124
@@ -4269,10 +4286,14 @@ table_fill_xentry(char *arg, ipfw_table_xentry *xent)
125
 				errx(EX_DATAERR, "bad IPv6 mask width: %s",
126
 				    p + 1);
127
 
128
-			type = IPFW_TABLE_CIDR;
129
+			if (type == 0)
130
+				type = IPFW_TABLE_CIDR;
131
 			masklen = p ? mask : 128;
132
 			addrlen = sizeof(struct in6_addr);
133
 		} else {
134
+			if (type != 0 && type != IPFW_TABLE_MIX)
135
+				errx(EX_DATAERR, "Wrong value passed as address");
136
+
137
 			/* Port or any other key */
138
 			key = strtol(arg, &p, 10);
139
 			/* Skip non-base 10 entries like 'fa1' */
140
@@ -4304,9 +4325,102 @@ table_fill_xentry(char *arg, ipfw_table_xentry *xent)
141
 		addrlen = sizeof(struct in_addr);
142
 	}
143
 
144
+	ac--; av++;
145
+	if (ac > 1 && av) {
146
+		if (_substrcmp(*av, "mac") == 0)  {
147
+			uint8_t _mask[8];
148
+
149
+			if (type == 0)
150
+				type = IPFW_TABLE_CIDR;
151
+			get_mac_addr_mask(av[1], (uint8_t *)&xent->mac_addr, _mask);
152
+			ac-=2; av+=2;
153
+		}
154
+	}
155
+
156
+	if (do_add && ac > 0) {
157
+		unsigned int tval;
158
+		/* isdigit is a bit of a hack here.. */
159
+		if (strchr(*av, (int)'.') == NULL && isdigit(**av))  {
160
+			xent->value = strtoul(*av, NULL, 0);
161
+		} else {
162
+			if (lookup_host(*av, (struct in_addr *)&tval) == 0) {
163
+				/* The value must be stored in host order	 *
164
+				 * so that the values < 65k can be distinguished */
165
+				xent->value = ntohl(tval);
166
+			} else {
167
+				errx(EX_NOHOST, "hostname ``%s'' unknown", *av);
168
+			}
169
+		}
170
+	} else
171
+		xent->value = 0;
172
+
173
 	xent->type = type;
174
 	xent->masklen = masklen;
175
-	xent->len = offsetof(ipfw_table_xentry, k) + addrlen;
176
+	if (type == IPFW_TABLE_MIX)
177
+		xent->len = offsetof(ipfw_table_xentry, k) + addrlen + ETHER_ADDR_LEN;
178
+	else
179
+		xent->len = offsetof(ipfw_table_xentry, k) + addrlen;
180
+}
181
+
182
+static void
183
+table_list_entry(ipfw_table_xentry *xent)
184
+{
185
+	struct in6_addr *addr6;
186
+	uint32_t tval;
187
+	char tbuf[128];
188
+
189
+	switch (xent->type) {
190
+	case IPFW_TABLE_CIDR:
191
+		/* IPv4 or IPv6 prefixes */
192
+		tval = xent->value;
193
+		addr6 = &xent->k.addr6;
194
+
195
+		if ((xent->flags & IPFW_TCF_INET) != 0) {
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 +4452,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
@@ -4352,8 +4467,7 @@ table_list(uint16_t num, int need_header)
253
 			tval = xent->value;
254
 			addr6 = &xent->k.addr6;
255
 
256
-
257
-			if (IN6_IS_ADDR_V4COMPAT(addr6)) {
258
+			if ((xent->flags & IPFW_TCF_INET) != 0) {
259
 				/* IPv4 address */
260
 				inet_ntop(AF_INET, &addr6->s6_addr32[3], tbuf, sizeof(tbuf));
261
 			} else {
262
@@ -4361,12 +4475,16 @@ table_list(uint16_t num, int need_header)
263
 				inet_ntop(AF_INET6, addr6, tbuf, sizeof(tbuf));
264
 			}
265
 
266
+			printf("%s/%u", tbuf, xent->masklen);
267
+			if (xent->mac_addr)
268
+				printf(" mac %s", ether_ntoa((struct ether_addr *)&xent->mac_addr));
269
+
270
 			if (co.do_value_as_ip) {
271
 				tval = htonl(tval);
272
-				printf("%s/%u %s\n", tbuf, xent->masklen,
273
+				printf(" %s\n",
274
 				    inet_ntoa(*(struct in_addr *)&tval));
275
 			} else
276
-				printf("%s/%u %u\n", tbuf, xent->masklen, tval);
277
+				printf(" %u\n", tval);
278
 			break;
279
 		case IPFW_TABLE_INTERFACE:
280
 			/* Interface names */
281
@@ -4377,6 +4495,23 @@ table_list(uint16_t num, int need_header)
282
 				    inet_ntoa(*(struct in_addr *)&tval));
283
 			} else
284
 				printf("%s %u\n", xent->k.iface, tval);
285
+
286
+			break;
287
+
288
+		case IPFW_TABLE_MIX:
289
+			/* mix of ip+mac */
290
+			tval = xent->value;
291
+
292
+			/* IPv4 address */
293
+			inet_ntop(AF_INET, &xent->k.mix.addr, tbuf, sizeof(tbuf));
294
+
295
+			if (co.do_value_as_ip) {
296
+				tval = htonl(tval);
297
+				printf("%s/%u %s %s\n", tbuf, xent->masklen - (8 * ETHER_ADDR_LEN), ether_ntoa((struct ether_addr *)xent->k.mix.mac),
298
+				    inet_ntoa(*(struct in_addr *)&tval));
299
+			} else
300
+				printf("%s/%u %s %u\n", tbuf, xent->masklen - (8 * ETHER_ADDR_LEN), ether_ntoa((struct ether_addr *)xent->k.mix.mac), tval);
301
+			break;
302
 		}
303
 
304
 		if (sz < xent->len)
305
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
306
index 1a6ac08..49f678f 100644
307
--- a/sys/net/if_ethersubr.c
308
+++ b/sys/net/if_ethersubr.c
309
@@ -742,7 +742,11 @@ ether_demux(struct ifnet *ifp, struct mbuf *m)
310
 
311
 		if (i != 0 || m == NULL)
312
 			return;
313
-	}
314
+
315
+		/* M_PROTO2 is for M_IP[6]_NEXTHOP */
316
+		i = m->m_flags & (M_FASTFWD_OURS|M_PROTO2);
317
+	} else
318
+		i = 0;
319
 
320
 	eh = mtod(m, struct ether_header *);
321
 	ether_type = ntohs(eh->ether_type);
322
@@ -781,6 +785,8 @@ ether_demux(struct ifnet *ifp, struct mbuf *m)
323
 	 */
324
 	m->m_flags &= ~M_VLANTAG;
325
 	m_clrprotoflags(m);
326
+	if (i)
327
+		m->m_flags |= M_FASTFWD_OURS|M_PROTO2;
328
 	m_adj(m, ETHER_HDR_LEN);
329
 
330
 	/*
331
diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h
332
index 14b08f5..b514ee3 100644
333
--- a/sys/netinet/ip_fw.h
334
+++ b/sys/netinet/ip_fw.h
335
@@ -74,6 +74,8 @@ typedef struct _ip_fw3_opheader {
336
 #define	IP_FW_TABLE_XDEL	87	/* delete entry */
337
 #define	IP_FW_TABLE_XGETSIZE	88	/* get table size */
338
 #define	IP_FW_TABLE_XLIST	89	/* list table contents */
339
+#define	IP_FW_TABLE_XLISTENTRY	90	/* list one table entry contents */
340
+#define	IP_FW_TABLE_XZEROENTRY	91	/* zero one table entry stats */
341
 
342
 /*
343
  * The kernel representation of ipfw rules is made of a list of
344
@@ -600,13 +602,16 @@ struct _ipfw_dyn_rule {
345
 
346
 #define	IPFW_TABLE_CIDR		1	/* Table for holding IPv4/IPv6 prefixes */
347
 #define	IPFW_TABLE_INTERFACE	2	/* Table for holding interface names */
348
-#define	IPFW_TABLE_MAXTYPE	2	/* Maximum valid number */
349
+#define	IPFW_TABLE_MIX		3	/* Table for holding IPv4/mac entries */
350
+#define	IPFW_TABLE_MAC		4	/* Table for holding mac entries */
351
+#define	IPFW_TABLE_MAXTYPE	5	/* Maximum valid number */
352
 
353
 typedef struct	_ipfw_table_entry {
354
 	in_addr_t	addr;		/* network address		*/
355
 	u_int32_t	value;		/* value			*/
356
 	u_int16_t	tbl;		/* table number			*/
357
 	u_int8_t	masklen;	/* mask length			*/
358
+	uint64_t	mac_addr;
359
 } ipfw_table_entry;
360
 
361
 typedef struct	_ipfw_table_xentry {
362
@@ -614,13 +619,32 @@ typedef struct	_ipfw_table_xentry {
363
 	uint8_t		type;		/* entry type			*/
364
 	uint8_t		masklen;	/* mask length			*/
365
 	uint16_t	tbl;		/* table number			*/
366
+	uint16_t	flags;		/* record flags			*/
367
 	uint32_t	value;		/* value			*/
368
+	uint32_t	timestamp;
369
+	uint64_t	mac_addr;
370
+	uint64_t	bytes;
371
+	uint64_t	packets;
372
 	union {
373
 		/* Longest field needs to be aligned by 4-byte boundary	*/
374
+#ifndef ETHER_ADDR_LEN
375
+#define ETHER_ADDR_LEN 6
376
+#endif
377
+#if 0
378
+		struct {
379
+			struct ether_addr addr;
380
+			struct ether_addr mask;
381
+		} mac;
382
+#endif
383
+		struct {
384
+			struct in_addr addr;
385
+			u_char mac[ETHER_ADDR_LEN];
386
+		} mix;
387
 		struct in6_addr	addr6;	/* IPv6 address 		*/
388
 		char	iface[IF_NAMESIZE];	/* interface name	*/
389
 	} k;
390
 } ipfw_table_xentry;
391
+#define	IPFW_TCF_INET	0x01	 /* CIDR flags: IPv4 record	*/
392
 
393
 typedef struct	_ipfw_table {
394
 	u_int32_t	size;		/* size of entries in bytes	*/
395
diff --git a/sys/netpfil/ipfw/ip_fw2.c b/sys/netpfil/ipfw/ip_fw2.c
396
index cd466bd..f2f117e 100644
397
--- a/sys/netpfil/ipfw/ip_fw2.c
398
+++ b/sys/netpfil/ipfw/ip_fw2.c
399
@@ -358,8 +358,8 @@ iface_match(struct ifnet *ifp, ipfw_insn_if *cmd, struct ip_fw_chain *chain, uin
400
 	/* Check by name or by IP address */
401
 	if (cmd->name[0] != '\0') { /* match by name */
402
 		if (cmd->name[0] == '\1') /* use tablearg to match */
403
-			return ipfw_lookup_table_extended(chain, cmd->p.glob,
404
-				ifp->if_xname, tablearg, IPFW_TABLE_INTERFACE);
405
+			return (ipfw_lookup_table_extended(chain, cmd->p.glob,
406
+				ifp->if_xname, tablearg, IPFW_TABLE_INTERFACE, NULL) != NULL);
407
 		/* Check name */
408
 		if (cmd->p.glob) {
409
 			if (fnmatch(cmd->name, ifp->if_xname, 0) == 0)
410
@@ -955,6 +955,7 @@ ipfw_chk(struct ip_fw_args *args)
411
 	int dyn_dir = MATCH_UNKNOWN;
412
 	ipfw_dyn_rule *q = NULL;
413
 	struct ip_fw_chain *chain = &V_layer3_chain;
414
+	void *tblent = NULL;
415
 
416
 	/*
417
 	 * We store in ulp a pointer to the upper layer protocol header.
418
@@ -1288,6 +1289,7 @@ do {								\
419
 			continue;
420
 
421
 		skip_or = 0;
422
+		tblent = NULL;
423
 		for (l = f->cmd_len, cmd = f->cmd ; l > 0 ;
424
 		    l -= cmdlen, cmd += cmdlen) {
425
 			int match;
426
@@ -1402,7 +1404,7 @@ do {								\
427
 				break;
428
 
429
 			case O_IN:	/* "out" is "not in" */
430
-				match = (oif == NULL);
431
+				match = (args->dir == DIR_IN);
432
 				break;
433
 
434
 			case O_LAYER2:
435
@@ -1438,11 +1440,18 @@ do {								\
436
 			case O_IP_SRC_LOOKUP:
437
 			case O_IP_DST_LOOKUP:
438
 				if (is_ipv4) {
439
+					struct ether_addr *ea = NULL;
440
+
441
 				    uint32_t key =
442
 					(cmd->opcode == O_IP_DST_LOOKUP) ?
443
 					    dst_ip.s_addr : src_ip.s_addr;
444
 				    uint32_t v = 0;
445
 
446
+					if (args->eh) {
447
+						ea = (struct ether_addr*)((cmd->opcode == O_IP_DST_LOOKUP) ?
448
+							args->eh->ether_dhost :
449
+							args->eh->ether_shost);
450
+					}
451
 				    if (cmdlen > F_INSN_SIZE(ipfw_insn_u32)) {
452
 					/* generic lookup. The key must be
453
 					 * in 32bit big-endian format.
454
@@ -1484,22 +1493,37 @@ do {								\
455
 					} else
456
 					    break;
457
 				    }
458
-				    match = ipfw_lookup_table(chain,
459
-					cmd->arg1, key, &v);
460
-				    if (!match)
461
+				    tblent = ipfw_lookup_table_extended(chain,
462
+					cmd->arg1, &key, &v, IPFW_TABLE_CIDR, ea);
463
+				    if (tblent == NULL) {
464
+					match = 0;
465
 					break;
466
+				    } else
467
+					match = 1;
468
 				    if (cmdlen == F_INSN_SIZE(ipfw_insn_u32))
469
 					match =
470
 					    ((ipfw_insn_u32 *)cmd)->d[0] == v;
471
-				    else
472
+				    if (match)
473
 					tablearg = v;
474
 				} else if (is_ipv6) {
475
+					struct ether_addr *ea = NULL;
476
 					uint32_t v = 0;
477
+
478
+					if (args->eh) {
479
+						ea = (struct ether_addr*)((cmd->opcode == O_IP_DST_LOOKUP) ?
480
+							args->eh->ether_dhost :
481
+							args->eh->ether_shost);
482
+					}
483
 					void *pkey = (cmd->opcode == O_IP_DST_LOOKUP) ?
484
 						&args->f_id.dst_ip6: &args->f_id.src_ip6;
485
-					match = ipfw_lookup_table_extended(chain,
486
+					tblent = ipfw_lookup_table_extended(chain,
487
 							cmd->arg1, pkey, &v,
488
-							IPFW_TABLE_CIDR);
489
+							IPFW_TABLE_CIDR, ea);
490
+				    if (tblent == NULL) {
491
+					match = 0;
492
+					break;
493
+				    } else
494
+					match = 1;
495
 					if (cmdlen == F_INSN_SIZE(ipfw_insn_u32))
496
 						match = ((ipfw_insn_u32 *)cmd)->d[0] == v;
497
 					if (match)
498
@@ -2314,8 +2338,7 @@ do {								\
499
 				break;
500
 
501
 			case O_FORWARD_IP:
502
-				if (args->eh)	/* not valid on layer2 pkts */
503
-					break;
504
+				if (!args->eh)	{/* not valid on layer2 pkts */
505
 				if (q == NULL || q->rule != f ||
506
 				    dyn_dir == MATCH_FORWARD) {
507
 				    struct sockaddr_in *sa;
508
@@ -2330,6 +2353,48 @@ do {								\
509
 					args->next_hop = sa;
510
 				    }
511
 				}
512
+				} else if (args->eh) {
513
+					struct m_tag *fwd_tag;
514
+					struct sockaddr_in *sa;
515
+					u_short sum;
516
+
517
+					/*
518
+					* Checksum correct? (from ip_fastfwd.c)
519
+					*/
520
+					if (m->m_pkthdr.csum_flags & CSUM_IP_CHECKED)
521
+						sum = !(m->m_pkthdr.csum_flags & CSUM_IP_VALID);
522
+					else {
523
+						if (hlen == sizeof(struct ip))
524
+							sum = in_cksum_hdr(ip);
525
+						else
526
+							sum = in_cksum(m, hlen);
527
+					}
528
+					if (sum) {
529
+						IPSTAT_INC(ips_badsum);
530
+						retval = IP_FW_DENY;
531
+						break;
532
+					}
533
+
534
+					/*
535
+					* Remember that we have checked the IP header and found it valid.
536
+					*/
537
+					m->m_pkthdr.csum_flags |= (CSUM_IP_CHECKED | CSUM_IP_VALID);
538
+
539
+					sa = &(((ipfw_insn_sa *)cmd)->sa);
540
+					fwd_tag = m_tag_get(PACKET_TAG_IPFORWARD,
541
+						sizeof(struct sockaddr_in), M_NOWAIT);
542
+					if (fwd_tag == NULL)
543
+						retval = IP_FW_DENY;
544
+					else {
545
+						bcopy(sa, (fwd_tag+1), sizeof(struct sockaddr_in));
546
+						m_tag_prepend(m, fwd_tag);
547
+
548
+						if (in_localip(sa->sin_addr))
549
+							m->m_flags |= M_FASTFWD_OURS;
550
+						m->m_flags |= M_IP_NEXTHOP;
551
+					}
552
+				}
553
+
554
 				retval = IP_FW_PASS;
555
 				l = 0;          /* exit inner loop */
556
 				done = 1;       /* exit outer loop */
557
@@ -2337,8 +2402,7 @@ do {								\
558
 
559
 #ifdef INET6
560
 			case O_FORWARD_IP6:
561
-				if (args->eh)	/* not valid on layer2 pkts */
562
-					break;
563
+				if (!args->eh) {/* not valid on layer2 pkts */
564
 				if (q == NULL || q->rule != f ||
565
 				    dyn_dir == MATCH_FORWARD) {
566
 					struct sockaddr_in6 *sin6;
567
@@ -2346,6 +2410,24 @@ do {								\
568
 					sin6 = &(((ipfw_insn_sa6 *)cmd)->sa);
569
 					args->next_hop6 = sin6;
570
 				}
571
+				} else if (args->eh) {
572
+					struct m_tag *fwd_tag;
573
+					struct sockaddr_in6 *sin6;
574
+
575
+					sin6 = &(((ipfw_insn_sa6 *)cmd)->sa);
576
+					fwd_tag = m_tag_get(PACKET_TAG_IPFORWARD,
577
+						sizeof(struct sockaddr_in6), M_NOWAIT);
578
+					if (fwd_tag == NULL)
579
+						retval = IP_FW_DENY;
580
+					else {
581
+						bcopy(sin6, (fwd_tag+1), sizeof(struct sockaddr_in6));
582
+						m_tag_prepend(m, fwd_tag);
583
+
584
+						if (in6_localip(&sin6->sin6_addr))
585
+							m->m_flags |= M_FASTFWD_OURS;
586
+						m->m_flags |= M_IP6_NEXTHOP;
587
+					}
588
+				}
589
 				retval = IP_FW_PASS;
590
 				l = 0;		/* exit inner loop */
591
 				done = 1;	/* exit outer loop */
592
@@ -2505,6 +2587,8 @@ do {								\
593
 		struct ip_fw *rule = chain->map[f_pos];
594
 		/* Update statistics */
595
 		IPFW_INC_RULE_COUNTER(rule, pktlen);
596
+		if (tblent != NULL)
597
+			ipfw_count_table_xentry_stats(tblent, pktlen);
598
 	} else {
599
 		retval = IP_FW_DENY;
600
 		printf("ipfw: ouch!, skip past end of rules, denying packet\n");
601
diff --git a/sys/netpfil/ipfw/ip_fw_pfil.c b/sys/netpfil/ipfw/ip_fw_pfil.c
602
index d1202ff..bf225b8 100644
603
--- a/sys/netpfil/ipfw/ip_fw_pfil.c
604
+++ b/sys/netpfil/ipfw/ip_fw_pfil.c
605
@@ -143,8 +143,9 @@ again:
606
 	}
607
 
608
 	args.m = *m0;
609
-	args.oif = dir == DIR_OUT ? ifp : NULL;
610
+	args.oif = ifp;
611
 	args.inp = inp;
612
+	args.dir = dir;
613
 
614
 	ipfw = ipfw_chk(&args);
615
 	*m0 = args.m;
616
@@ -314,9 +315,8 @@ ipfw_check_frame(void *arg, struct mbuf **m0, struct ifnet *dst, int dir,
617
 		/* XXX can we free it after use ? */
618
 		mtag->m_tag_id = PACKET_TAG_NONE;
619
 		r = (struct ipfw_rule_ref *)(mtag + 1);
620
-		if (r->info & IPFW_ONEPASS)
621
-			return (0);
622
-		args.rule = *r;
623
+		m_tag_delete(*m0, mtag);
624
+		return (0);
625
 	}
626
 
627
 	/* I need some amt of data to be contiguous */
628
@@ -333,12 +333,15 @@ ipfw_check_frame(void *arg, struct mbuf **m0, struct ifnet *dst, int dir,
629
 	save_eh = *eh;			/* save copy for restore below */
630
 	m_adj(m, ETHER_HDR_LEN);	/* strip ethernet header */
631
 
632
+	dir = dir == PFIL_IN ? DIR_IN : DIR_OUT;
633
+
634
 	args.m = m;		/* the packet we are looking at		*/
635
-	args.oif = dir == PFIL_OUT ? dst: NULL;	/* destination, if any	*/
636
+	args.oif = dst;		/* destination, if any	*/
637
 	args.next_hop = NULL;	/* we do not support forward yet	*/
638
 	args.next_hop6 = NULL;	/* we do not support forward yet	*/
639
 	args.eh = &save_eh;	/* MAC header for bridged/MAC packets	*/
640
 	args.inp = NULL;	/* used by ipfw uid/gid/jail rules	*/
641
+	args.dir = dir;         /* pfSense addition                     */
642
 	i = ipfw_chk(&args);
643
 	m = args.m;
644
 	if (m != NULL) {
645
@@ -369,13 +372,12 @@ ipfw_check_frame(void *arg, struct mbuf **m0, struct ifnet *dst, int dir,
646
 
647
 	case IP_FW_DUMMYNET:
648
 		ret = EACCES;
649
-		int dir;
650
 
651
 		if (ip_dn_io_ptr == NULL)
652
 			break; /* i.e. drop */
653
 
654
 		*m0 = NULL;
655
-		dir = PROTO_LAYER2 | (dst ? DIR_OUT : DIR_IN);
656
+		dir = PROTO_LAYER2 | dir;
657
 		ip_dn_io_ptr(&m, dir, &args);
658
 		return 0;
659
 
660
diff --git a/sys/netpfil/ipfw/ip_fw_private.h b/sys/netpfil/ipfw/ip_fw_private.h
661
index a8d7eea..4830124 100644
662
--- a/sys/netpfil/ipfw/ip_fw_private.h
663
+++ b/sys/netpfil/ipfw/ip_fw_private.h
664
@@ -101,6 +101,7 @@ struct ip_fw_args {
665
 
666
 	struct ipfw_flow_id f_id;	/* grabbed from IP header	*/
667
 	//uint32_t	cookie;		/* a cookie depending on rule action */
668
+	uint32_t        dir;            /* direction */
669
 	struct inpcb	*inp;
670
 
671
 	struct _ip6dn_args	dummypar; /* dummynet->ip6_output */
672
@@ -304,13 +305,17 @@ void ipfw_reap_rules(struct ip_fw *head);
673
 struct radix_node;
674
 int ipfw_lookup_table(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr,
675
     uint32_t *val);
676
-int ipfw_lookup_table_extended(struct ip_fw_chain *ch, uint16_t tbl, void *paddr,
677
-    uint32_t *val, int type);
678
+struct ether_addr;
679
+void *ipfw_lookup_table_extended(struct ip_fw_chain *ch, uint16_t tbl, void *paddr,
680
+    uint32_t *val, int type, struct ether_addr *);
681
+void ipfw_count_table_xentry_stats(void *, int);
682
+int ipfw_zero_table_xentry_stats(struct ip_fw_chain *, ipfw_table_xentry *);
683
+int ipfw_lookup_table_xentry(struct ip_fw_chain *, ipfw_table_xentry *);
684
 int ipfw_init_tables(struct ip_fw_chain *ch);
685
 void ipfw_destroy_tables(struct ip_fw_chain *ch);
686
 int ipfw_flush_table(struct ip_fw_chain *ch, uint16_t tbl);
687
 int ipfw_add_table_entry(struct ip_fw_chain *ch, uint16_t tbl, void *paddr,
688
-    uint8_t plen, uint8_t mlen, uint8_t type, uint32_t value);
689
+    uint8_t plen, uint8_t mlen, uint8_t type, u_int64_t mac_addr, uint32_t value);
690
 int ipfw_del_table_entry(struct ip_fw_chain *ch, uint16_t tbl, void *paddr,
691
     uint8_t plen, uint8_t mlen, uint8_t type);
692
 int ipfw_count_table(struct ip_fw_chain *ch, uint32_t tbl, uint32_t *cnt);
693
diff --git a/sys/netpfil/ipfw/ip_fw_sockopt.c b/sys/netpfil/ipfw/ip_fw_sockopt.c
694
index cb9c89c..d98cac6 100644
695
--- a/sys/netpfil/ipfw/ip_fw_sockopt.c
696
+++ b/sys/netpfil/ipfw/ip_fw_sockopt.c
697
@@ -1124,7 +1124,7 @@ ipfw_ctl(struct sockopt *sopt)
698
 				break;
699
 			error = ipfw_add_table_entry(chain, ent.tbl,
700
 			    &ent.addr, sizeof(ent.addr), ent.masklen, 
701
-			    IPFW_TABLE_CIDR, ent.value);
702
+			    IPFW_TABLE_CIDR, ent.mac_addr, ent.value);
703
 		}
704
 		break;
705
 
706
@@ -1162,7 +1162,7 @@ ipfw_ctl(struct sockopt *sopt)
707
 
708
 			error = (opt == IP_FW_TABLE_XADD) ?
709
 				ipfw_add_table_entry(chain, xent->tbl, &xent->k, 
710
-					len, xent->masklen, xent->type, xent->value) :
711
+					len, xent->masklen, xent->type, xent->mac_addr, xent->value) :
712
 				ipfw_del_table_entry(chain, xent->tbl, &xent->k,
713
 					len, xent->masklen, xent->type);
714
 		}
715
@@ -1245,6 +1245,47 @@ ipfw_ctl(struct sockopt *sopt)
716
 		}
717
 		break;
718
 
719
+	case IP_FW_TABLE_XZEROENTRY: /* IP_FW3 */
720
+		{
721
+			ipfw_table_xentry *xent = (ipfw_table_xentry *)(op3 + 1);
722
+
723
+			/* Check minimum header size */
724
+			if (IP_FW3_OPLENGTH(sopt) < offsetof(ipfw_table_xentry, k)) {
725
+				error = EINVAL;
726
+				break;
727
+			}
728
+
729
+			/* Check if len field is valid */
730
+			if (xent->len > sizeof(ipfw_table_xentry)) {
731
+				error = EINVAL;
732
+				break;
733
+			}
734
+			
735
+			error = ipfw_zero_table_xentry_stats(chain, xent);
736
+		}
737
+		break;
738
+
739
+	case IP_FW_TABLE_XLISTENTRY: /* IP_FW3 */
740
+		{
741
+			ipfw_table_xentry *xent = (ipfw_table_xentry *)(op3 + 1);
742
+
743
+			/* Check minimum header size */
744
+			if (IP_FW3_OPLENGTH(sopt) < offsetof(ipfw_table_xentry, k)) {
745
+				error = EINVAL;
746
+				break;
747
+			}
748
+
749
+			/* Check if len field is valid */
750
+			if (xent->len > sizeof(ipfw_table_xentry)) {
751
+				error = EINVAL;
752
+				break;
753
+			}
754
+			
755
+			error = ipfw_lookup_table_xentry(chain, xent);
756
+			xent->timestamp += boottime.tv_sec;
757
+		}
758
+		break;
759
+
760
 	case IP_FW_TABLE_XLIST: /* IP_FW3 */
761
 		{
762
 			ipfw_xtable *tbl;
763
diff --git a/sys/netpfil/ipfw/ip_fw_table.c b/sys/netpfil/ipfw/ip_fw_table.c
764
index 95cff5c..c7b6718 100644
765
--- a/sys/netpfil/ipfw/ip_fw_table.c
766
+++ b/sys/netpfil/ipfw/ip_fw_table.c
767
@@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$");
768
 #include <net/route.h>
769
 #include <net/vnet.h>
770
 
771
+#include <net/ethernet.h>
772
 #include <netinet/in.h>
773
 #include <netinet/ip_var.h>	/* struct ipfw_rule_ref */
774
 #include <netinet/ip_fw.h>
775
@@ -74,7 +75,11 @@ static MALLOC_DEFINE(M_IPFW_TBL, "ipfw_tbl", "IpFw tables");
776
 struct table_entry {
777
 	struct radix_node	rn[2];
778
 	struct sockaddr_in	addr, mask;
779
+	u_int64_t               mac_addr;
780
 	u_int32_t		value;
781
+	u_int32_t               timestamp;
782
+	u_int64_t               bytes;
783
+	u_int64_t               packets;
784
 };
785
 
786
 struct xaddr_iface {
787
@@ -83,6 +88,22 @@ struct xaddr_iface {
788
 	char 		ifname[IF_NAMESIZE];	/* Interface name */
789
 };
790
 
791
+#if 0
792
+struct xaddr_mac {
793
+	uint8_t		mac_len;		/* length of this struct */
794
+	uint8_t		pad[7];		/* Align name */
795
+	struct ether_addr mac;
796
+};
797
+#endif
798
+
799
+struct xaddr_mix {
800
+	uint8_t		mix_len;		/* length of this struct */
801
+	sa_family_t     sin_family;
802
+        uint8_t		pad[6];
803
+        struct  in_addr sin_addr;
804
+	u_char	mac[ETHER_ADDR_LEN];
805
+};
806
+
807
 struct table_xentry {
808
 	struct radix_node	rn[2];
809
 	union {
810
@@ -90,14 +111,26 @@ struct table_xentry {
811
 		struct sockaddr_in6	addr6;
812
 #endif
813
 		struct xaddr_iface	iface;
814
+#if 0
815
+		struct xaddr_mac	mac;
816
+#endif
817
+		struct xaddr_mix	mix;
818
 	} a;
819
 	union {
820
 #ifdef INET6
821
 		struct sockaddr_in6	mask6;
822
 #endif
823
 		struct xaddr_iface	ifmask;
824
+#if 0
825
+		struct xaddr_mac	macmask;
826
+#endif
827
+		struct xaddr_mix	mixmask;
828
 	} m;
829
+	u_int64_t               mac_addr;
830
 	u_int32_t		value;
831
+	u_int32_t               timestamp;
832
+	u_int64_t               bytes;
833
+	u_int64_t               packets;
834
 };
835
 
836
 /*
837
@@ -117,10 +150,17 @@ struct table_xentry {
838
 #define KEY_LEN_INET	(offsetof(struct sockaddr_in, sin_addr) + sizeof(in_addr_t))
839
 #define KEY_LEN_INET6	(offsetof(struct sockaddr_in6, sin6_addr) + sizeof(struct in6_addr))
840
 #define KEY_LEN_IFACE	(offsetof(struct xaddr_iface, ifname))
841
+#define KEY_LEN_MIX	(offsetof(struct xaddr_mix, sin_addr) + sizeof(in_addr_t) + ETHER_ADDR_LEN)
842
+#if 0
843
+#define KEY_LEN_MAC	(offsetof(struct xaddr_mac, mac) + ETHER_ADDR_LEN)
844
+#endif
845
 
846
 #define OFF_LEN_INET	(8 * offsetof(struct sockaddr_in, sin_addr))
847
 #define OFF_LEN_INET6	(8 * offsetof(struct sockaddr_in6, sin6_addr))
848
 #define OFF_LEN_IFACE	(8 * offsetof(struct xaddr_iface, ifname))
849
+#if 0
850
+#define OFF_LEN_MAC	(8 * offsetof(struct xaddr_mac, mac))
851
+#endif
852
 
853
 
854
 #ifdef INET6
855
@@ -137,7 +177,7 @@ ipv6_writemask(struct in6_addr *addr6, uint8_t mask)
856
 
857
 int
858
 ipfw_add_table_entry(struct ip_fw_chain *ch, uint16_t tbl, void *paddr,
859
-    uint8_t plen, uint8_t mlen, uint8_t type, uint32_t value)
860
+    uint8_t plen, uint8_t mlen, uint8_t type, u_int64_t mac_addr, uint32_t value)
861
 {
862
 	struct radix_node_head *rnh, **rnh_ptr;
863
 	struct table_entry *ent;
864
@@ -161,6 +201,7 @@ ipfw_add_table_entry(struct ip_fw_chain *ch, uint16_t tbl, void *paddr,
865
 				return (EINVAL);
866
 			ent = malloc(sizeof(*ent), M_IPFW_TBL, M_WAITOK | M_ZERO);
867
 			ent->value = value;
868
+			ent->mac_addr = mac_addr;
869
 			/* Set 'total' structure length */
870
 			KEY_LEN(ent->addr) = KEY_LEN_INET;
871
 			KEY_LEN(ent->mask) = KEY_LEN_INET;
872
@@ -182,6 +223,7 @@ ipfw_add_table_entry(struct ip_fw_chain *ch, uint16_t tbl, void *paddr,
873
 				return (EINVAL);
874
 			xent = malloc(sizeof(*xent), M_IPFW_TBL, M_WAITOK | M_ZERO);
875
 			xent->value = value;
876
+			xent->mac_addr = mac_addr;
877
 			/* Set 'total' structure length */
878
 			KEY_LEN(xent->a.addr6) = KEY_LEN_INET6;
879
 			KEY_LEN(xent->m.mask6) = KEY_LEN_INET6;
880
@@ -233,6 +275,52 @@ ipfw_add_table_entry(struct ip_fw_chain *ch, uint16_t tbl, void *paddr,
881
 		mask_ptr = NULL;
882
 		break;
883
 
884
+#if 0
885
+	case IPFW_TABLE_MAC:
886
+		int i;
887
+
888
+		xent = malloc(sizeof(*xent), M_IPFW_TBL, M_WAITOK | M_ZERO);
889
+		xent->value = value;
890
+		/* Set 'total' structure length */
891
+		KEY_LEN(xent->a.mac) = KEY_LEN_MAC;
892
+		KEY_LEN(xent->m.macmask) = KEY_LEN_MAC;
893
+		/* Set offset of address in bits */
894
+		offset = OFF_LEN_MAC;
895
+		xent->a.mac = (struct ether_addr)(*paddr);
896
+		xent->m.mac = (struct ether_addr)(*(((struct ether_addr *)paddr) + 1));
897
+		for (i = 0; i < ETHER_ADDR_LEN; i++)
898
+			xent->a.mac.octet[i] &= xent->m.mac.octet[i];
899
+		/* Set pointers */
900
+		rnh_ptr = &ch->xtables[tbl];
901
+		ent_ptr = xent;
902
+		addr_ptr = (struct sockaddr *)&xent->a.mac;
903
+		mask_ptr = (struct sockaddr *)&xent->m.macmask;
904
+		break;
905
+#endif
906
+
907
+	case IPFW_TABLE_MIX:
908
+		if ((plen - ETHER_ADDR_LEN) != sizeof(in_addr_t))
909
+			return (EINVAL);
910
+
911
+		xent = malloc(sizeof(*xent), M_IPFW_TBL, M_WAITOK | M_ZERO);
912
+		xent->value = value;
913
+		/* Set 'total' structure length */
914
+		KEY_LEN(xent->a.mix) = KEY_LEN_MIX;
915
+		KEY_LEN(xent->m.mixmask) = KEY_LEN_MIX;
916
+		/* Set offset of IPv4 address in bits */
917
+		offset = OFF_LEN_INET;
918
+		/* XXX: Needs to be fixed */
919
+		memcpy(&xent->a.mix.sin_addr, paddr, ETHER_ADDR_LEN + sizeof(struct in_addr));
920
+		/* Only full ips /32 and full masks supported for mac */
921
+		memset(&xent->m.mixmask.sin_addr, 0xFF, sizeof(struct in_addr));
922
+		memset(xent->m.mixmask.mac, 0xFF, ETHER_ADDR_LEN);
923
+		/* Set pointers */
924
+		rnh_ptr = &ch->xtables[tbl];
925
+		ent_ptr = xent;
926
+		addr_ptr = (struct sockaddr *)&xent->a.mix;
927
+		mask_ptr = NULL;
928
+		break;
929
+
930
 	default:
931
 		return (EINVAL);
932
 	}
933
@@ -281,6 +369,19 @@ ipfw_add_table_entry(struct ip_fw_chain *ch, uint16_t tbl, void *paddr,
934
 	IPFW_WUNLOCK(ch);
935
 
936
 	if (rn == NULL) {
937
+		if (type == IPFW_TABLE_CIDR) {
938
+			/* Just update if any new value needed */
939
+			struct table_entry *ent2;
940
+
941
+			ent2 = (struct table_entry *)(rnh->rnh_lookup(&ent->addr, NULL, rnh));
942
+			if (ent2 != NULL) {
943
+				if (ent2->mac_addr) {
944
+					if (!bcmp(&mac_addr, &ent2->mac_addr, ETHER_ADDR_LEN))
945
+						ent2->value = value;
946
+				} else
947
+					ent2->value = value;
948
+			}
949
+		}
950
 		free(ent_ptr, M_IPFW_TBL);
951
 		return (EEXIST);
952
 	}
953
@@ -367,6 +468,41 @@ ipfw_del_table_entry(struct ip_fw_chain *ch, uint16_t tbl, void *paddr,
954
 
955
 		break;
956
 
957
+#if 0
958
+	case IPFW_TABLE_MAC:
959
+		struct xaddr_mac mac, macmask;
960
+		memset(&mac, 0, sizeof(mac));
961
+		memset(&macmask, 0, sizeof(macmask));
962
+
963
+		/* Set 'total' structure length */
964
+                KEY_LEN(mac) = KEY_LEN_MAC;
965
+		mac.mac.mac = (struct ether_addr)(*paddr);
966
+                KEY_LEN(macmask) = KEY_LEN_MAC;
967
+		macmask.mac.macmask = (struct ether_addr)(*(((struct ether_addr *)paddr) + 1));
968
+		for (i = 0; i < ETHER_ADDR_LEN; i++)
969
+			mac.mac.octet[i] &= macmask.mac.octet[i];
970
+		rnh_ptr = &ch->xtables[tbl];
971
+		sa_ptr = (struct sockaddr *)&mac;
972
+		mask_ptr = (struct sockaddr *)&macmask;
973
+
974
+		break;
975
+#endif
976
+
977
+	case IPFW_TABLE_MIX:
978
+		if (mlen > (32 + ETHER_ADDR_LEN))
979
+			return (EINVAL);
980
+		struct xaddr_mix mix;
981
+		memset(&mix, 0, sizeof(mix));
982
+
983
+		/* Set 'total' structure length */
984
+		KEY_LEN(mix) = KEY_LEN_MIX;
985
+		memcpy(&mix.sin_addr, paddr, sizeof(struct in_addr) + ETHER_ADDR_LEN);
986
+		rnh_ptr = &ch->xtables[tbl];
987
+		sa_ptr = (struct sockaddr *)&mix;
988
+		mask_ptr = NULL;
989
+
990
+		break;
991
+
992
 	default:
993
 		return (EINVAL);
994
 	}
995
@@ -552,9 +688,153 @@ ipfw_lookup_table(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr,
996
 	return (0);
997
 }
998
 
999
+void
1000
+ipfw_count_table_xentry_stats(void *arg, int pktlen)
1001
+{
1002
+	ipfw_table_xentry *xent= arg;
1003
+
1004
+	xent->packets++;
1005
+	xent->bytes += pktlen;
1006
+	xent->timestamp = time_uptime;
1007
+}
1008
+
1009
 int
1010
+ipfw_zero_table_xentry_stats(struct ip_fw_chain *ch, ipfw_table_xentry *arg)
1011
+{
1012
+	struct radix_node_head *rnh;
1013
+	struct table_xentry *xent;
1014
+	struct sockaddr_in6 sa6;
1015
+	struct xaddr_iface iface;
1016
+	struct xaddr_mix xm;
1017
+
1018
+	if (arg->tbl >= V_fw_tables_max)
1019
+		return (0);
1020
+	if ((rnh = ch->xtables[arg->tbl]) == NULL)
1021
+		return (0);
1022
+
1023
+	switch (arg->type) {
1024
+	case IPFW_TABLE_CIDR:
1025
+		KEY_LEN(sa6) = KEY_LEN_INET6;
1026
+		memcpy(&sa6.sin6_addr, &arg->k.addr6, sizeof(struct in6_addr));
1027
+		xent = (struct table_xentry *)(rnh->rnh_lookup(&sa6, NULL, rnh));
1028
+		break;
1029
+
1030
+	case IPFW_TABLE_INTERFACE:
1031
+		KEY_LEN(iface) = KEY_LEN_IFACE +
1032
+		    strlcpy(iface.ifname, arg->k.iface, IF_NAMESIZE) + 1;
1033
+		/* Assume direct match */
1034
+		/* FIXME: Add interface pattern matching */
1035
+		xent = (struct table_xentry *)(rnh->rnh_lookup(&iface, NULL, rnh));
1036
+		break;
1037
+
1038
+#if 0
1039
+	case IPFW_TABLE_MAC:
1040
+	{
1041
+		struct xaddr_mac mac;
1042
+
1043
+		KEY_LEN(mac) = KEY_LEN_MAC;
1044
+		&mac.mac = arg->k.mac;
1045
+		xent = (struct table_xentry *)(rnh->rnh_lookup(&mac, NULL, rnh));
1046
+	}
1047
+		break;
1048
+#endif
1049
+
1050
+	case IPFW_TABLE_MIX:
1051
+		KEY_LEN(xm) = KEY_LEN_MIX;
1052
+		memcpy(&xm.sin_addr, &arg->k.mix.addr, sizeof(struct in_addr));
1053
+		memcpy(&xm.mac, arg->k.mix.mac, ETHER_ADDR_LEN);
1054
+		xent = (struct table_xentry *)(rnh->rnh_lookup(&xm, NULL, rnh));
1055
+		break;
1056
+
1057
+	default:
1058
+		return (0);
1059
+	}
1060
+
1061
+	if (xent != NULL) {
1062
+		xent->bytes = 0;
1063
+		xent->packets = 0;
1064
+		xent->timestamp = time_uptime;
1065
+		
1066
+		return (1);
1067
+	}
1068
+	return (0);
1069
+}
1070
+
1071
+int
1072
+ipfw_lookup_table_xentry(struct ip_fw_chain *ch, ipfw_table_xentry *arg)
1073
+{
1074
+	struct radix_node_head *rnh;
1075
+	struct table_xentry *xent;
1076
+
1077
+	if (arg->tbl >= V_fw_tables_max)
1078
+		return (0);
1079
+	if ((rnh = ch->xtables[arg->tbl]) == NULL)
1080
+		return (0);
1081
+
1082
+	switch (arg->type) {
1083
+	case IPFW_TABLE_CIDR:
1084
+	{
1085
+		struct sockaddr_in6 sa6;
1086
+		KEY_LEN(sa6) = KEY_LEN_INET6;
1087
+		memcpy(&sa6.sin6_addr, &arg->k.addr6, sizeof(struct in6_addr));
1088
+		xent = (struct table_xentry *)(rnh->rnh_lookup(&sa6, NULL, rnh));
1089
+	}
1090
+		break;
1091
+
1092
+	case IPFW_TABLE_INTERFACE:
1093
+	{
1094
+		struct xaddr_iface iface;
1095
+
1096
+		KEY_LEN(iface) = KEY_LEN_IFACE +
1097
+		    strlcpy(iface.ifname, arg->k.iface, IF_NAMESIZE) + 1;
1098
+		/* Assume direct match */
1099
+		/* FIXME: Add interface pattern matching */
1100
+		xent = (struct table_xentry *)(rnh->rnh_lookup(&iface, NULL, rnh));
1101
+	}
1102
+		break;
1103
+
1104
+#if 0
1105
+	case IPFW_TABLE_MAC:
1106
+	{
1107
+		struct xaddr_mac mac;
1108
+
1109
+		KEY_LEN(mac) = KEY_LEN_MAC;
1110
+		mac.mac = arg->k.mac.addr;
1111
+		xent = (struct table_xentry *)(rnh->rnh_lookup(&mac, NULL, rnh));
1112
+	}
1113
+		break;
1114
+#endif
1115
+
1116
+	case IPFW_TABLE_MIX:
1117
+	{
1118
+		struct xaddr_mix xm;
1119
+
1120
+		KEY_LEN(xm) = KEY_LEN_MIX;
1121
+		memcpy(&xm.sin_addr, &arg->k.mix.addr, sizeof(struct in_addr));
1122
+		memcpy(&xm.mac, arg->k.mix.mac, ETHER_ADDR_LEN);
1123
+		xent = (struct table_xentry *)(rnh->rnh_lookup(&xm, NULL, rnh));
1124
+	}
1125
+		break;
1126
+
1127
+	default:
1128
+		return (0);
1129
+	}
1130
+
1131
+	if (xent != NULL) {
1132
+		arg->bytes = xent->bytes;
1133
+		arg->packets = xent->packets;
1134
+		arg->value = xent->value;
1135
+		arg->timestamp = xent->timestamp;
1136
+		arg->mac_addr = xent->mac_addr;
1137
+		
1138
+		return (1);
1139
+	}
1140
+	return (0);
1141
+}
1142
+
1143
+void *
1144
 ipfw_lookup_table_extended(struct ip_fw_chain *ch, uint16_t tbl, void *paddr,
1145
-    uint32_t *val, int type)
1146
+    uint32_t *val, int type, struct ether_addr *ea)
1147
 {
1148
 	struct radix_node_head *rnh;
1149
 	struct table_xentry *xent;
1150
@@ -562,15 +842,21 @@ ipfw_lookup_table_extended(struct ip_fw_chain *ch, uint16_t tbl, void *paddr,
1151
 	struct xaddr_iface iface;
1152
 
1153
 	if (tbl >= V_fw_tables_max)
1154
-		return (0);
1155
+		return (NULL);
1156
 	if ((rnh = ch->xtables[tbl]) == NULL)
1157
-		return (0);
1158
+		return (NULL);
1159
 
1160
 	switch (type) {
1161
 	case IPFW_TABLE_CIDR:
1162
 		KEY_LEN(sa6) = KEY_LEN_INET6;
1163
 		memcpy(&sa6.sin6_addr, paddr, sizeof(struct in6_addr));
1164
 		xent = (struct table_xentry *)(rnh->rnh_lookup(&sa6, NULL, rnh));
1165
+		if (xent != NULL) {
1166
+			if (ea && xent->mac_addr) {
1167
+				if (bcmp((u_char *)&xent->mac_addr, ea->octet, ETHER_ADDR_LEN) != 0)
1168
+					xent = NULL;
1169
+			}
1170
+		}
1171
 		break;
1172
 
1173
 	case IPFW_TABLE_INTERFACE:
1174
@@ -581,15 +867,37 @@ ipfw_lookup_table_extended(struct ip_fw_chain *ch, uint16_t tbl, void *paddr,
1175
 		xent = (struct table_xentry *)(rnh->rnh_lookup(&iface, NULL, rnh));
1176
 		break;
1177
 
1178
+#if 0
1179
+	case IPFW_TABLE_MAC:
1180
+	{
1181
+		struct xaddr_mac mac;
1182
+
1183
+		KEY_LEN(mac) = KEY_LEN_MAC;
1184
+		mac.mac = (struct ether_addr)(*paddr);
1185
+		xent = (struct table_xentry *)(rnh->rnh_lookup(&mac, NULL, rnh));
1186
+	}
1187
+		break;
1188
+#endif
1189
+
1190
+	case IPFW_TABLE_MIX:
1191
+	{
1192
+		struct xaddr_mix xm;
1193
+
1194
+		KEY_LEN(xm) = KEY_LEN_MIX;
1195
+		memcpy(((char *)&xm.sin_addr), paddr, sizeof(struct in_addr) + ETHER_ADDR_LEN);
1196
+		xent = (struct table_xentry *)(rnh->rnh_lookup(&xm, NULL, rnh));
1197
+	}
1198
+		break;
1199
+
1200
 	default:
1201
-		return (0);
1202
+		return (NULL);
1203
 	}
1204
 
1205
 	if (xent != NULL) {
1206
 		*val = xent->value;
1207
-		return (1);
1208
+		return (xent);
1209
 	}
1210
-	return (0);
1211
+	return (NULL);
1212
 }
1213
 
1214
 static int
1215
@@ -697,7 +1005,12 @@ dump_table_xentry_base(struct radix_node *rn, void *arg)
1216
 		xent->masklen = 33 - ffs(ntohl(n->mask.sin_addr.s_addr));
1217
 	/* Save IPv4 address as deprecated IPv6 compatible */
1218
 	xent->k.addr6.s6_addr32[3] = n->addr.sin_addr.s_addr;
1219
+	xent->flags = IPFW_TCF_INET;
1220
 	xent->value = n->value;
1221
+	xent->bytes = n->bytes;
1222
+	xent->packets = n->packets;
1223
+	xent->timestamp = n->timestamp;
1224
+	xent->mac_addr = n->mac_addr;
1225
 	tbl->cnt++;
1226
 	return (0);
1227
 }
1228
@@ -735,12 +1048,31 @@ dump_table_xentry_extended(struct radix_node *rn, void *arg)
1229
 		memcpy(&xent->k, &n->a.iface.ifname, IF_NAMESIZE);
1230
 		break;
1231
 	
1232
+#if 0
1233
+	case IPFW_TABLE_MAC:
1234
+		/* Assume exact mask */
1235
+		xent->masklen = 8 * ETHER_ADDR_LEN;
1236
+		xent->k.mac.addr = n->a.mac.mac;
1237
+		xent->k.mac.mask = n->m.mac.mac;
1238
+		break;
1239
+#endif
1240
+	
1241
+	case IPFW_TABLE_MIX:
1242
+		/* Assume exact mask */
1243
+		xent->masklen = 8 * (ETHER_ADDR_LEN + sizeof(struct in_addr));
1244
+		memcpy(&xent->k.mix.addr, &n->a.mix.sin_addr, sizeof(struct in_addr));
1245
+		memcpy(xent->k.mix.mac, &n->a.mix.mac, ETHER_ADDR_LEN);
1246
+		break;
1247
+
1248
 	default:
1249
 		/* unknown, skip entry */
1250
 		return (0);
1251
 	}
1252
 
1253
 	xent->value = n->value;
1254
+	xent->bytes = n->bytes;
1255
+	xent->packets = n->packets;
1256
+	xent->timestamp = n->timestamp;
1257
 	tbl->cnt++;
1258
 	return (0);
1259
 }
(2-2/65)