xref: /illumos-gate/usr/src/cmd/ipf/tools/ipftest.c (revision 3d393ee6c37fa10ac512ed6d36109ad616dc7c1a)
1 /*
2  * Copyright (C) 1993-2001 by Darren Reed.
3  *
4  * See the IPFILTER.LICENCE file for details on licencing.
5  *
6  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
7  * Use is subject to license terms.
8  */
9 
10 #include "ipf.h"
11 #include "ipt.h"
12 #include <sys/ioctl.h>
13 #include <sys/file.h>
14 
15 #if !defined(lint)
16 static const char sccsid[] = "@(#)ipt.c	1.19 6/3/96 (C) 1993-2000 Darren Reed";
17 static const char rcsid[] = "@(#)$Id: ipftest.c,v 1.44.2.4 2005/07/16 06:05:28 darrenr Exp $";
18 #endif
19 
20 extern	char	*optarg;
21 extern	struct frentry	*ipfilter[2][2];
22 extern	struct ipread	snoop, etherf, tcpd, pcap, iptext, iphex;
23 extern	struct ifnet	*get_unit __P((char *, int, ipf_stack_t *));
24 extern	void	init_ifp __P((void));
25 
26 int	opts = OPT_DONOTHING;
27 int	use_inet6 = 0;
28 int	pfil_delayed_copy = 0;
29 int	main __P((int, char *[]));
30 int	loadrules __P((char *, int));
31 int	kmemcpy __P((char *, long, int));
32 int     kstrncpy __P((char *, long, int n));
33 void	dumpnat __P((ipf_stack_t *ifs));
34 void	dumpstate __P((ipf_stack_t *ifs));
35 void	dumplookups __P((ipf_stack_t *ifs));
36 void	dumpgroups __P((ipf_stack_t *ifs));
37 void	drain_log __P((char *, ipf_stack_t *ifs));
38 void	fixv4sums __P((mb_t *, ip_t *));
39 ipf_stack_t *get_ifs __P((void));
40 ipf_stack_t *create_ifs __P((void));
41 
42 
43 #if defined(__NetBSD__) || defined(__OpenBSD__) || SOLARIS || \
44 	(_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000) || \
45 	defined(__osf__) || defined(linux)
46 int ipftestioctl __P((int, ioctlcmd_t, ...));
47 int ipnattestioctl __P((int, ioctlcmd_t, ...));
48 int ipstatetestioctl __P((int, ioctlcmd_t, ...));
49 int ipauthtestioctl __P((int, ioctlcmd_t, ...));
50 int ipscantestioctl __P((int, ioctlcmd_t, ...));
51 int ipsynctestioctl __P((int, ioctlcmd_t, ...));
52 int ipooltestioctl __P((int, ioctlcmd_t, ...));
53 #else
54 int ipftestioctl __P((dev_t, ioctlcmd_t, void *));
55 int ipnattestioctl __P((dev_t, ioctlcmd_t, void *));
56 int ipstatetestioctl __P((dev_t, ioctlcmd_t, void *));
57 int ipauthtestioctl __P((dev_t, ioctlcmd_t, void *));
58 int ipsynctestioctl __P((dev_t, ioctlcmd_t, void *));
59 int ipscantestioctl __P((dev_t, ioctlcmd_t, void *));
60 int ipooltestioctl __P((dev_t, ioctlcmd_t, void *));
61 #endif
62 
63 static	ioctlfunc_t	iocfunctions[IPL_LOGSIZE] = { ipftestioctl,
64 						      ipnattestioctl,
65 						      ipstatetestioctl,
66 						      ipauthtestioctl,
67 						      ipsynctestioctl,
68 						      ipscantestioctl,
69 						      ipooltestioctl,
70 						      NULL };
71 
72 
73 int main(argc,argv)
74 int argc;
75 char *argv[];
76 {
77 	char	*datain, *iface, *ifname, *logout;
78 	int	fd, i, dir, c, loaded, dump, hlen;
79 	struct	ifnet	*ifp;
80 	struct	ipread	*r;
81 	mb_t	mb, *m;
82 	ip_t	*ip;
83 	ipf_stack_t *ifs;
84 
85 	m = &mb;
86 	dir = 0;
87 	dump = 0;
88 	hlen = 0;
89 	loaded = 0;
90 	r = &iptext;
91 	iface = NULL;
92 	logout = NULL;
93 	ifname = "anon0";
94 	datain = NULL;
95 
96 	initparse();
97 	ifs = create_ifs();
98 
99 #if defined(IPFILTER_DEFAULT_BLOCK)
100         ifs->ifs_fr_pass = FR_BLOCK|FR_NOMATCH;
101 #else
102         ifs->ifs_fr_pass = (IPF_DEFAULT_PASS)|FR_NOMATCH;
103 #endif
104 	ipftuneable_alloc(ifs);
105 
106 	MUTEX_INIT(&ifs->ifs_ipf_rw, "ipf rw mutex");
107 	MUTEX_INIT(&ifs->ifs_ipf_timeoutlock, "ipf timeout lock");
108 	RWLOCK_INIT(&ifs->ifs_ipf_global, "ipf filter load/unload mutex");
109 	RWLOCK_INIT(&ifs->ifs_ipf_mutex, "ipf filter rwlock");
110 	RWLOCK_INIT(&ifs->ifs_ipf_ipidfrag, "ipf IP NAT-Frag rwlock");
111 
112 	fr_loginit(ifs);
113 	fr_authinit(ifs);
114 	fr_fraginit(ifs);
115 	fr_stateinit(ifs);
116 	fr_natinit(ifs);
117 	appr_init(ifs);
118 	ip_lookup_init(ifs);
119 	ifs->ifs_fr_running = 1;
120 
121 	while ((c = getopt(argc, argv, "6bdDF:i:I:l:N:P:or:RT:vxX")) != -1)
122 		switch (c)
123 		{
124 		case '6' :
125 #ifdef	USE_INET6
126 			use_inet6 = 1;
127 #else
128 			fprintf(stderr, "IPv6 not supported\n");
129 			exit(1);
130 #endif
131 			break;
132 		case 'b' :
133 			opts |= OPT_BRIEF;
134 			break;
135 		case 'd' :
136 			opts |= OPT_DEBUG;
137 			break;
138 		case 'D' :
139 			dump = 1;
140 			break;
141 		case 'F' :
142 			if (strcasecmp(optarg, "pcap") == 0)
143 				r = &pcap;
144 			else if (strcasecmp(optarg, "etherfind") == 0)
145 				r = &etherf;
146 			else if (strcasecmp(optarg, "snoop") == 0)
147 				r = &snoop;
148 			else if (strcasecmp(optarg, "tcpdump") == 0)
149 				r = &tcpd;
150 			else if (strcasecmp(optarg, "hex") == 0)
151 				r = &iphex;
152 			else if (strcasecmp(optarg, "text") == 0)
153 				r = &iptext;
154 			break;
155 		case 'i' :
156 			datain = optarg;
157 			break;
158 		case 'I' :
159 			ifname = optarg;
160 			break;
161 		case 'l' :
162 			logout = optarg;
163 			break;
164 		case 'o' :
165 			opts |= OPT_SAVEOUT;
166 			break;
167 		case 'r' :
168 			if (ipf_parsefile(-1, ipf_addrule, iocfunctions,
169 					  optarg) == -1)
170 				return -1;
171 			loaded = 1;
172 			break;
173 		case 'R' :
174 			opts |= OPT_NORESOLVE;
175 			break;
176 		case 'v' :
177 			opts |= OPT_VERBOSE;
178 			break;
179 		case 'N' :
180 			if (ipnat_parsefile(-1, ipnat_addrule, ipnattestioctl,
181 					    optarg) == -1)
182 				return -1;
183 			loaded = 1;
184 			opts |= OPT_NAT;
185 			break;
186 		case 'P' :
187 			if (ippool_parsefile(-1, optarg, ipooltestioctl) == -1)
188 				return -1;
189 			loaded = 1;
190 			break;
191 		case 'T' :
192 			ipf_dotuning(-1, optarg, ipftestioctl);
193 			break;
194 		case 'x' :
195 			opts |= OPT_HEX;
196 			break;
197 		}
198 
199 	if (loaded == 0) {
200 		(void)fprintf(stderr,"no rules loaded\n");
201 		exit(-1);
202 	}
203 
204 	if (opts & OPT_SAVEOUT)
205 		init_ifp();
206 
207 	if (datain)
208 		fd = (*r->r_open)(datain);
209 	else
210 		fd = (*r->r_open)("-");
211 
212 	if (fd < 0)
213 		exit(-1);
214 
215 	ip = MTOD(m, ip_t *);
216 	while ((i = (*r->r_readip)(MTOD(m, char *), sizeof(m->mb_buf),
217 				    &iface, &dir)) > 0) {
218 		if (iface == NULL || *iface == '\0')
219 			iface = ifname;
220 		ifp = get_unit(iface, IP_V(ip), ifs);
221 		if (ifp == NULL) {
222 			fprintf(stderr, "out of memory\n");
223 			exit(1);
224 		}
225 		if (!use_inet6) {
226 			ip->ip_off = ntohs(ip->ip_off);
227 			ip->ip_len = ntohs(ip->ip_len);
228 			if (r->r_flags & R_DO_CKSUM)
229 				fixv4sums(m, ip);
230 			hlen = IP_HL(ip) << 2;
231 		}
232 #ifdef	USE_INET6
233 		else
234 			hlen = sizeof(ip6_t);
235 #endif
236 		/* ipfr_slowtimer(); */
237 		m = &mb;
238 		m->mb_len = i;
239 		i = fr_check(ip, hlen, ifp, dir, &m, ifs);
240 		if ((opts & OPT_NAT) == 0)
241 			switch (i)
242 			{
243 			case -4 :
244 				(void)printf("preauth");
245 				break;
246 			case -3 :
247 				(void)printf("account");
248 				break;
249 			case -2 :
250 				(void)printf("auth");
251 				break;
252 			case -1 :
253 				(void)printf("block");
254 				break;
255 			case 0 :
256 				(void)printf("pass");
257 				break;
258 			case 1 :
259 				(void)printf("nomatch");
260 				break;
261 			case 3 :
262 				(void)printf("block return-rst");
263 				break;
264 			case 4 :
265 				(void)printf("block return-icmp");
266 				break;
267 			case 5 :
268 				(void)printf("block return-icmp-as-dest");
269 				break;
270 			default :
271 				(void)printf("recognised return %#x\n", i);
272 				break;
273 			}
274 		if (!use_inet6) {
275 			ip->ip_off = htons(ip->ip_off);
276 			ip->ip_len = htons(ip->ip_len);
277 		}
278 
279 		if (!(opts & OPT_BRIEF)) {
280 			putchar(' ');
281 			printpacket(ip);
282 			printf("--------------");
283 		} else if ((opts & (OPT_BRIEF|OPT_NAT)) == (OPT_NAT|OPT_BRIEF))
284 			printpacket(ip);
285 		if (dir && (ifp != NULL) && IP_V(ip) && (m != NULL))
286 #if  defined(__sgi) && (IRIX < 60500)
287 			(*ifp->if_output)(ifp, (void *)m, NULL);
288 #else
289 # if TRU64 >= 1885
290 			(*ifp->if_output)(ifp, (void *)m, NULL, 0, 0);
291 # else
292 			(*ifp->if_output)(ifp, (void *)m, NULL, 0);
293 # endif
294 #endif
295 		if ((opts & (OPT_BRIEF|OPT_NAT)) != (OPT_NAT|OPT_BRIEF))
296 			putchar('\n');
297 		dir = 0;
298 		if (iface != ifname) {
299 			free(iface);
300 			iface = ifname;
301 		}
302 		m = &mb;
303 	}
304 	(*r->r_close)();
305 
306 	if (logout != NULL) {
307 		drain_log(logout, ifs);
308 	}
309 
310 	if (dump == 1)  {
311 		dumpnat(ifs);
312 		dumpstate(ifs);
313 		dumplookups(ifs);
314 		dumpgroups(ifs);
315 	}
316 
317 	fr_deinitialise(ifs);
318 
319 	return 0;
320 }
321 
322 
323 #if defined(__NetBSD__) || defined(__OpenBSD__) || SOLARIS || \
324 	(_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000) || \
325 	defined(__osf__) || defined(linux)
326 int ipftestioctl(int dev, ioctlcmd_t cmd, ...)
327 {
328 	caddr_t data;
329 	va_list ap;
330 	int i;
331 
332 	va_start(ap, cmd);
333 	data = va_arg(ap, caddr_t);
334 	va_end(ap);
335 
336 	i = iplioctl(IPL_LOGIPF, cmd, data, FWRITE|FREAD);
337 	if (opts & OPT_DEBUG)
338 		fprintf(stderr, "iplioctl(IPF,%#x,%p) = %d\n",
339 			(u_int)cmd, data, i);
340 	if (i != 0) {
341 		errno = i;
342 		return -1;
343 	}
344 	return 0;
345 }
346 
347 
348 int ipnattestioctl(int dev, ioctlcmd_t cmd, ...)
349 {
350 	caddr_t data;
351 	va_list ap;
352 	int i;
353 
354 	va_start(ap, cmd);
355 	data = va_arg(ap, caddr_t);
356 	va_end(ap);
357 
358 	i = iplioctl(IPL_LOGNAT, cmd, data, FWRITE|FREAD);
359 	if (opts & OPT_DEBUG)
360 		fprintf(stderr, "iplioctl(NAT,%#x,%p) = %d\n",
361 			(u_int)cmd, data, i);
362 	if (i != 0) {
363 		errno = i;
364 		return -1;
365 	}
366 	return 0;
367 }
368 
369 
370 int ipstatetestioctl(int dev, ioctlcmd_t cmd, ...)
371 {
372 	caddr_t data;
373 	va_list ap;
374 	int i;
375 
376 	va_start(ap, cmd);
377 	data = va_arg(ap, caddr_t);
378 	va_end(ap);
379 
380 	i = iplioctl(IPL_LOGSTATE, cmd, data, FWRITE|FREAD);
381 	if ((opts & OPT_DEBUG) || (i != 0))
382 		fprintf(stderr, "iplioctl(STATE,%#x,%p) = %d\n",
383 			(u_int)cmd, data, i);
384 	if (i != 0) {
385 		errno = i;
386 		return -1;
387 	}
388 	return 0;
389 }
390 
391 
392 int ipauthtestioctl(int dev, ioctlcmd_t cmd, ...)
393 {
394 	caddr_t data;
395 	va_list ap;
396 	int i;
397 
398 	va_start(ap, cmd);
399 	data = va_arg(ap, caddr_t);
400 	va_end(ap);
401 
402 	i = iplioctl(IPL_LOGAUTH, cmd, data, FWRITE|FREAD);
403 	if ((opts & OPT_DEBUG) || (i != 0))
404 		fprintf(stderr, "iplioctl(AUTH,%#x,%p) = %d\n",
405 			(u_int)cmd, data, i);
406 	if (i != 0) {
407 		errno = i;
408 		return -1;
409 	}
410 	return 0;
411 }
412 
413 
414 int ipscantestioctl(int dev, ioctlcmd_t cmd, ...)
415 {
416 	caddr_t data;
417 	va_list ap;
418 	int i;
419 
420 	va_start(ap, cmd);
421 	data = va_arg(ap, caddr_t);
422 	va_end(ap);
423 
424 	i = iplioctl(IPL_LOGSCAN, cmd, data, FWRITE|FREAD);
425 	if ((opts & OPT_DEBUG) || (i != 0))
426 		fprintf(stderr, "iplioctl(SCAN,%#x,%p) = %d\n",
427 			(u_int)cmd, data, i);
428 	if (i != 0) {
429 		errno = i;
430 		return -1;
431 	}
432 	return 0;
433 }
434 
435 
436 int ipsynctestioctl(int dev, ioctlcmd_t cmd, ...)
437 {
438 	caddr_t data;
439 	va_list ap;
440 	int i;
441 
442 	va_start(ap, cmd);
443 	data = va_arg(ap, caddr_t);
444 	va_end(ap);
445 
446 	i = iplioctl(IPL_LOGSYNC, cmd, data, FWRITE|FREAD);
447 	if ((opts & OPT_DEBUG) || (i != 0))
448 		fprintf(stderr, "iplioctl(SYNC,%#x,%p) = %d\n",
449 			(u_int)cmd, data, i);
450 	if (i != 0) {
451 		errno = i;
452 		return -1;
453 	}
454 	return 0;
455 }
456 
457 
458 int ipooltestioctl(int dev, ioctlcmd_t cmd, ...)
459 {
460 	caddr_t data;
461 	va_list ap;
462 	int i;
463 
464 	va_start(ap, cmd);
465 	data = va_arg(ap, caddr_t);
466 	va_end(ap);
467 
468 	i = iplioctl(IPL_LOGLOOKUP, cmd, data, FWRITE|FREAD);
469 	if ((opts & OPT_DEBUG) || (i != 0))
470 		fprintf(stderr, "iplioctl(POOL,%#x,%p) = %d\n",
471 			(u_int)cmd, data, i);
472 	if (i != 0) {
473 		errno = i;
474 		return -1;
475 	}
476 	return 0;
477 }
478 #else
479 int ipftestioctl(dev, cmd, data)
480 dev_t dev;
481 ioctlcmd_t cmd;
482 void *data;
483 {
484 	int i;
485 
486 	i = iplioctl(IPL_LOGIPF, cmd, data, FWRITE|FREAD);
487 	if ((opts & OPT_DEBUG) || (i != 0))
488 		fprintf(stderr, "iplioctl(IPF,%#x,%p) = %d\n", cmd, data, i);
489 	if (i != 0) {
490 		errno = i;
491 		return -1;
492 	}
493 	return 0;
494 }
495 
496 
497 int ipnattestioctl(dev, cmd, data)
498 dev_t dev;
499 ioctlcmd_t cmd;
500 void *data;
501 {
502 	int i;
503 
504 	i = iplioctl(IPL_LOGNAT, cmd, data, FWRITE|FREAD);
505 	if ((opts & OPT_DEBUG) || (i != 0))
506 		fprintf(stderr, "iplioctl(NAT,%#x,%p) = %d\n", cmd, data, i);
507 	if (i != 0) {
508 		errno = i;
509 		return -1;
510 	}
511 	return 0;
512 }
513 
514 
515 int ipstatetestioctl(dev, cmd, data)
516 dev_t dev;
517 ioctlcmd_t cmd;
518 void *data;
519 {
520 	int i;
521 
522 	i = iplioctl(IPL_LOGSTATE, cmd, data, FWRITE|FREAD);
523 	if ((opts & OPT_DEBUG) || (i != 0))
524 		fprintf(stderr, "iplioctl(STATE,%#x,%p) = %d\n", cmd, data, i);
525 	if (i != 0) {
526 		errno = i;
527 		return -1;
528 	}
529 	return 0;
530 }
531 
532 
533 int ipauthtestioctl(dev, cmd, data)
534 dev_t dev;
535 ioctlcmd_t cmd;
536 void *data;
537 {
538 	int i;
539 
540 	i = iplioctl(IPL_LOGAUTH, cmd, data, FWRITE|FREAD);
541 	if ((opts & OPT_DEBUG) || (i != 0))
542 		fprintf(stderr, "iplioctl(AUTH,%#x,%p) = %d\n", cmd, data, i);
543 	if (i != 0) {
544 		errno = i;
545 		return -1;
546 	}
547 	return 0;
548 }
549 
550 
551 int ipsynctestioctl(dev, cmd, data)
552 dev_t dev;
553 ioctlcmd_t cmd;
554 void *data;
555 {
556 	int i;
557 
558 	i = iplioctl(IPL_LOGSYNC, cmd, data, FWRITE|FREAD);
559 	if ((opts & OPT_DEBUG) || (i != 0))
560 		fprintf(stderr, "iplioctl(SYNC,%#x,%p) = %d\n", cmd, data, i);
561 	if (i != 0) {
562 		errno = i;
563 		return -1;
564 	}
565 	return 0;
566 }
567 
568 
569 int ipscantestioctl(dev, cmd, data)
570 dev_t dev;
571 ioctlcmd_t cmd;
572 void *data;
573 {
574 	int i;
575 
576 	i = iplioctl(IPL_LOGSCAN, cmd, data, FWRITE|FREAD);
577 	if ((opts & OPT_DEBUG) || (i != 0))
578 		fprintf(stderr, "iplioctl(SCAN,%#x,%p) = %d\n", cmd, data, i);
579 	if (i != 0) {
580 		errno = i;
581 		return -1;
582 	}
583 	return 0;
584 }
585 
586 
587 int ipooltestioctl(dev, cmd, data)
588 dev_t dev;
589 ioctlcmd_t cmd;
590 void *data;
591 {
592 	int i;
593 
594 	i = iplioctl(IPL_LOGLOOKUP, cmd, data, FWRITE|FREAD);
595 	if (opts & OPT_DEBUG)
596 		fprintf(stderr, "iplioctl(POOL,%#x,%p) = %d\n", cmd, data, i);
597 	if (i != 0) {
598 		errno = i;
599 		return -1;
600 	}
601 	return 0;
602 }
603 #endif
604 
605 
606 int kmemcpy(addr, offset, size)
607 char *addr;
608 long offset;
609 int size;
610 {
611 	bcopy((char *)offset, addr, size);
612 	return 0;
613 }
614 
615 
616 int kstrncpy(buf, pos, n)
617 char *buf;
618 long pos;
619 int n;
620 {
621 	char *ptr;
622 
623 	ptr = (char *)pos;
624 
625 	while ((n-- > 0) && (*buf++ = *ptr++))
626 		;
627 	return 0;
628 }
629 
630 
631 /*
632  * Display the built up NAT table rules and mapping entries.
633  */
634 void dumpnat(ifs)
635 	ipf_stack_t *ifs;
636 {
637 	ipnat_t	*ipn;
638 	nat_t	*nat;
639 
640 	printf("List of active MAP/Redirect filters:\n");
641 	for (ipn = ifs->ifs_nat_list; ipn != NULL; ipn = ipn->in_next)
642 		printnat(ipn, opts & (OPT_DEBUG|OPT_VERBOSE));
643 	printf("\nList of active sessions:\n");
644 	for (nat = ifs->ifs_nat_instances; nat; nat = nat->nat_next) {
645 		printactivenat(nat, opts, 0);
646 		if (nat->nat_aps)
647 			printaps(nat->nat_aps, opts);
648 	}
649 }
650 
651 
652 /*
653  * Display the built up state table rules and mapping entries.
654  */
655 void dumpstate(ifs)
656 	ipf_stack_t *ifs;
657 {
658 	ipstate_t *ips;
659 
660 	printf("List of active state sessions:\n");
661 	for (ips = ifs->ifs_ips_list; ips != NULL; )
662 		ips = printstate(ips, opts & (OPT_DEBUG|OPT_VERBOSE),
663 				 ifs->ifs_fr_ticks);
664 }
665 
666 
667 void dumplookups(ifs)
668 	ipf_stack_t *ifs;
669 {
670 	iphtable_t *iph;
671 	ip_pool_t *ipl;
672 	int i;
673 
674 	printf("List of configured pools\n");
675 	for (i = 0; i < IPL_LOGSIZE; i++)
676 		for (ipl = ifs->ifs_ip_pool_list[i]; ipl != NULL;
677 		    ipl = ipl->ipo_next)
678 			printpool(ipl, bcopywrap, NULL, opts);
679 
680 	printf("List of configured hash tables\n");
681 	for (i = 0; i < IPL_LOGSIZE; i++)
682 		for (iph = ifs->ifs_ipf_htables[i]; iph != NULL;
683 		     iph = iph->iph_next)
684 			printhash(iph, bcopywrap, NULL, opts);
685 }
686 
687 
688 void dumpgroups(ifs)
689 	ipf_stack_t *ifs;
690 {
691 	frgroup_t *fg;
692 	frentry_t *fr;
693 	int i;
694 
695 	printf("List of groups configured (set 0)\n");
696 	for (i = 0; i < IPL_LOGSIZE; i++)
697 		for (fg =  ifs->ifs_ipfgroups[i][0]; fg != NULL;
698 		    fg = fg->fg_next) {
699 			printf("Dev.%d. Group %s Ref %d Flags %#x\n",
700 				i, fg->fg_name, fg->fg_ref, fg->fg_flags);
701 			for (fr = fg->fg_start; fr != NULL; fr = fr->fr_next) {
702 #ifdef	USE_QUAD_T
703 				printf("%qu ",(unsigned long long)fr->fr_hits);
704 #else
705 				printf("%ld ", fr->fr_hits);
706 #endif
707 				printfr(fr, ipftestioctl);
708 			}
709 		}
710 
711 	printf("List of groups configured (set 1)\n");
712 	for (i = 0; i < IPL_LOGSIZE; i++)
713 		for (fg =  ifs->ifs_ipfgroups[i][1]; fg != NULL;
714 		    fg = fg->fg_next) {
715 			printf("Dev.%d. Group %s Ref %d Flags %#x\n",
716 				i, fg->fg_name, fg->fg_ref, fg->fg_flags);
717 			for (fr = fg->fg_start; fr != NULL; fr = fr->fr_next) {
718 #ifdef	USE_QUAD_T
719 				printf("%qu ",(unsigned long long)fr->fr_hits);
720 #else
721 				printf("%ld ", fr->fr_hits);
722 #endif
723 				printfr(fr, ipftestioctl);
724 			}
725 		}
726 }
727 
728 
729 void drain_log(filename, ifs)
730 char *filename;
731 ipf_stack_t *ifs;
732 {
733 	char buffer[DEFAULT_IPFLOGSIZE];
734 	struct iovec iov;
735 	struct uio uio;
736 	size_t resid;
737 	int fd, i;
738 
739 	fd = open(filename, O_CREAT|O_TRUNC|O_WRONLY, 0644);
740 	if (fd == -1) {
741 		perror("drain_log:open");
742 		return;
743 	}
744 
745 	for (i = 0; i <= IPL_LOGMAX; i++)
746 		while (1) {
747 			bzero((char *)&iov, sizeof(iov));
748 			iov.iov_base = buffer;
749 			iov.iov_len = sizeof(buffer);
750 
751 			bzero((char *)&uio, sizeof(uio));
752 			uio.uio_iov = &iov;
753 			uio.uio_iovcnt = 1;
754 			uio.uio_resid = iov.iov_len;
755 			resid = uio.uio_resid;
756 
757 			if (ipflog_read(i, &uio, ifs) == 0) {
758 				/*
759 				 * If nothing was read then break out.
760 				 */
761 				if (uio.uio_resid == resid)
762 					break;
763 				write(fd, buffer, resid - uio.uio_resid);
764 			} else
765 				break;
766 	}
767 
768 	close(fd);
769 }
770 
771 
772 void fixv4sums(m, ip)
773 mb_t *m;
774 ip_t *ip;
775 {
776 	u_char *csump, *hdr;
777 
778 	ip->ip_sum = 0;
779 	ip->ip_sum = ipf_cksum((u_short *)ip, IP_HL(ip) << 2);
780 
781 	csump = (u_char *)ip;
782 	csump += IP_HL(ip) << 2;
783 
784 	switch (ip->ip_p)
785 	{
786 	case IPPROTO_TCP :
787 		hdr = csump;
788 		csump += offsetof(tcphdr_t, th_sum);
789 		break;
790 	case IPPROTO_UDP :
791 		hdr = csump;
792 		csump += offsetof(udphdr_t, uh_sum);
793 		break;
794 	default :
795 		csump = NULL;
796 		hdr = NULL;
797 		break;
798 	}
799 	if (hdr != NULL) {
800 		*csump = 0;
801 		*(u_short *)csump = fr_cksum(m, ip, ip->ip_p, hdr);
802 	}
803 }
804 
805 ipf_stack_t *gifs;
806 
807 /*
808  * Allocate and keep pointer for get_ifs()
809  */
810 ipf_stack_t *
811 create_ifs()
812 {
813 	ipf_stack_t *ifs;
814 
815 	KMALLOCS(ifs, ipf_stack_t *, sizeof (*ifs));
816 	bzero(ifs, sizeof (*ifs));
817 	gifs = ifs;
818 	return (ifs);
819 }
820 
821 ipf_stack_t *
822 get_ifs()
823 {
824 	return (gifs);
825 }
826