Projet

Général

Profil

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

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

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