Projet

Général

Profil

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

univnautes-tools / patches / stable / 10 / CP_speedup.diff @ 54a3971d

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