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