Projet

Général

Profil

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

univnautes-tools / patches / stable / 10 / CP_speedup.diff @ 1814ce0d

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