10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * Copyright (C) 1993-2001 by Darren Reed.
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * See the IPFILTER.LICENCE file for details on licencing.
50Sstevel@tonic-gate  *
60Sstevel@tonic-gate  * $Id: printfr.c,v 1.37 2003/06/03 16:01:12 darrenr Exp $
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
90Sstevel@tonic-gate  * Use is subject to license terms.
100Sstevel@tonic-gate  */
110Sstevel@tonic-gate 
120Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
130Sstevel@tonic-gate 
140Sstevel@tonic-gate #include "ipf.h"
150Sstevel@tonic-gate 
160Sstevel@tonic-gate 
170Sstevel@tonic-gate void printlookup(addr, mask)
180Sstevel@tonic-gate i6addr_t *addr, *mask;
190Sstevel@tonic-gate {
200Sstevel@tonic-gate 	switch (addr->iplookuptype)
210Sstevel@tonic-gate 	{
220Sstevel@tonic-gate 	case IPLT_POOL :
230Sstevel@tonic-gate 		printf("pool/");
240Sstevel@tonic-gate 		break;
250Sstevel@tonic-gate 	case IPLT_HASH :
260Sstevel@tonic-gate 		printf("hash/");
270Sstevel@tonic-gate 		break;
280Sstevel@tonic-gate 	default :
290Sstevel@tonic-gate 		printf("lookup(%x)=", addr->iplookuptype);
300Sstevel@tonic-gate 		break;
310Sstevel@tonic-gate 	}
320Sstevel@tonic-gate 
330Sstevel@tonic-gate 	printf("%u", addr->iplookupnum);
340Sstevel@tonic-gate 	if (opts & OPT_UNDEF) {
350Sstevel@tonic-gate 		if (mask->iplookupptr == NULL) {
360Sstevel@tonic-gate 			printf("(!)");
370Sstevel@tonic-gate 		}
380Sstevel@tonic-gate 	}
390Sstevel@tonic-gate }
400Sstevel@tonic-gate 
410Sstevel@tonic-gate 
420Sstevel@tonic-gate /*
430Sstevel@tonic-gate  * print the filter structure in a useful way
440Sstevel@tonic-gate  */
450Sstevel@tonic-gate void	printfr(fp, iocfunc)
460Sstevel@tonic-gate struct	frentry	*fp;
470Sstevel@tonic-gate ioctlfunc_t	iocfunc;
480Sstevel@tonic-gate {
490Sstevel@tonic-gate 	struct protoent	*p;
500Sstevel@tonic-gate 	u_short	sec[2];
510Sstevel@tonic-gate 	u_32_t type;
520Sstevel@tonic-gate 	u_char *t;
530Sstevel@tonic-gate 	char *s;
540Sstevel@tonic-gate 	int pr;
550Sstevel@tonic-gate 
560Sstevel@tonic-gate 	pr = -2;
570Sstevel@tonic-gate 	type = fp->fr_type & ~FR_T_BUILTIN;
580Sstevel@tonic-gate 
590Sstevel@tonic-gate 	if ((fp->fr_type & FR_T_BUILTIN) != 0)
600Sstevel@tonic-gate 		printf("# Builtin: ");
610Sstevel@tonic-gate 
620Sstevel@tonic-gate 	if (fp->fr_type == FR_T_CALLFUNC) {
630Sstevel@tonic-gate 		;
640Sstevel@tonic-gate 	} else if (fp->fr_func != NULL) {
650Sstevel@tonic-gate 		printf("call");
660Sstevel@tonic-gate 		if ((fp->fr_flags & FR_CALLNOW) != 0)
670Sstevel@tonic-gate 			printf(" now");
680Sstevel@tonic-gate 		s = kvatoname(fp->fr_func, iocfunc);
690Sstevel@tonic-gate 		printf(" %s/%u", s ? s : "?", fp->fr_arg);
700Sstevel@tonic-gate 	} else if (FR_ISPASS(fp->fr_flags))
710Sstevel@tonic-gate 		printf("pass");
720Sstevel@tonic-gate 	else if (FR_ISBLOCK(fp->fr_flags)) {
730Sstevel@tonic-gate 		printf("block");
740Sstevel@tonic-gate 		if (fp->fr_flags & FR_RETICMP) {
750Sstevel@tonic-gate 			if ((fp->fr_flags & FR_RETMASK) == FR_FAKEICMP)
760Sstevel@tonic-gate 				printf(" return-icmp-as-dest");
770Sstevel@tonic-gate 			else if ((fp->fr_flags & FR_RETMASK) == FR_RETICMP)
780Sstevel@tonic-gate 				printf(" return-icmp");
790Sstevel@tonic-gate 			if (fp->fr_icode) {
800Sstevel@tonic-gate 				if (fp->fr_icode <= MAX_ICMPCODE)
810Sstevel@tonic-gate 					printf("(%s)",
820Sstevel@tonic-gate 						icmpcodes[(int)fp->fr_icode]);
830Sstevel@tonic-gate 				else
840Sstevel@tonic-gate 					printf("(%d)", fp->fr_icode);
850Sstevel@tonic-gate 			}
860Sstevel@tonic-gate 		} else if ((fp->fr_flags & FR_RETMASK) == FR_RETRST)
870Sstevel@tonic-gate 			printf(" return-rst");
880Sstevel@tonic-gate 	} else if ((fp->fr_flags & FR_LOGMASK) == FR_LOG) {
890Sstevel@tonic-gate 		printlog(fp);
900Sstevel@tonic-gate 	} else if (FR_ISACCOUNT(fp->fr_flags))
910Sstevel@tonic-gate 		printf("count");
920Sstevel@tonic-gate 	else if (FR_ISAUTH(fp->fr_flags))
930Sstevel@tonic-gate 		printf("auth");
940Sstevel@tonic-gate 	else if (FR_ISPREAUTH(fp->fr_flags))
950Sstevel@tonic-gate 		printf("preauth");
960Sstevel@tonic-gate 	else if (FR_ISNOMATCH(fp->fr_flags))
970Sstevel@tonic-gate 		printf("nomatch");
980Sstevel@tonic-gate 	else if (FR_ISSKIP(fp->fr_flags))
990Sstevel@tonic-gate 		printf("skip %u", fp->fr_arg);
1000Sstevel@tonic-gate 	else {
1010Sstevel@tonic-gate 		printf("%x", fp->fr_flags);
1020Sstevel@tonic-gate 	}
1030Sstevel@tonic-gate 
1040Sstevel@tonic-gate 	if (fp->fr_flags & FR_OUTQUE)
1050Sstevel@tonic-gate 		printf(" out ");
1060Sstevel@tonic-gate 	else
1070Sstevel@tonic-gate 		printf(" in ");
1080Sstevel@tonic-gate 
1090Sstevel@tonic-gate 	if (((fp->fr_flags & FR_LOGB) == FR_LOGB) ||
1100Sstevel@tonic-gate 	    ((fp->fr_flags & FR_LOGP) == FR_LOGP)) {
1110Sstevel@tonic-gate 		printlog(fp);
1120Sstevel@tonic-gate 		putchar(' ');
1130Sstevel@tonic-gate 	}
1140Sstevel@tonic-gate 
1150Sstevel@tonic-gate 	if (fp->fr_flags & FR_QUICK)
1160Sstevel@tonic-gate 		printf("quick ");
1170Sstevel@tonic-gate 
1180Sstevel@tonic-gate 	if (*fp->fr_ifname) {
1190Sstevel@tonic-gate 		printifname("on ", fp->fr_ifname, fp->fr_ifa);
1200Sstevel@tonic-gate 		if (*fp->fr_ifnames[1] && strcmp(fp->fr_ifnames[1], "*"))
1210Sstevel@tonic-gate 			printifname(",", fp->fr_ifnames[1], fp->fr_ifas[1]);
1220Sstevel@tonic-gate 		putchar(' ');
1230Sstevel@tonic-gate 
1240Sstevel@tonic-gate 		if (*fp->fr_dif.fd_ifname)
1250Sstevel@tonic-gate 			print_toif("dup-to", &fp->fr_dif);
1260Sstevel@tonic-gate 		if (*fp->fr_tif.fd_ifname)
1270Sstevel@tonic-gate 			print_toif("to", &fp->fr_tif);
1280Sstevel@tonic-gate 		if (fp->fr_flags & FR_FASTROUTE)
1290Sstevel@tonic-gate 			printf("fastroute ");
1300Sstevel@tonic-gate 
1310Sstevel@tonic-gate 		if ((*fp->fr_ifnames[2] && strcmp(fp->fr_ifnames[2], "*")) ||
1320Sstevel@tonic-gate 		    (*fp->fr_ifnames[3] && strcmp(fp->fr_ifnames[3], "*"))) {
1330Sstevel@tonic-gate 			if (fp->fr_flags & FR_OUTQUE)
1340Sstevel@tonic-gate 				printf("in-via ");
1350Sstevel@tonic-gate 			else
1360Sstevel@tonic-gate 				printf("out-via ");
1370Sstevel@tonic-gate 
1380Sstevel@tonic-gate 			if (*fp->fr_ifnames[2]) {
1390Sstevel@tonic-gate 				printifname("", fp->fr_ifnames[2],
1400Sstevel@tonic-gate 					    fp->fr_ifas[2]);
1410Sstevel@tonic-gate 				putchar(' ');
1420Sstevel@tonic-gate 
1430Sstevel@tonic-gate 				if (*fp->fr_ifnames[3]) {
1440Sstevel@tonic-gate 					printifname(",", fp->fr_ifnames[3],
1450Sstevel@tonic-gate 						    fp->fr_ifas[3]);
1460Sstevel@tonic-gate 				}
1470Sstevel@tonic-gate 			}
1480Sstevel@tonic-gate 		}
1490Sstevel@tonic-gate 	}
1500Sstevel@tonic-gate 
1510Sstevel@tonic-gate 	if (type == FR_T_IPF) {
1520Sstevel@tonic-gate 		if (fp->fr_mip.fi_tos)
1530Sstevel@tonic-gate 			printf("tos %#x ", fp->fr_tos);
1540Sstevel@tonic-gate 		if (fp->fr_mip.fi_ttl)
1550Sstevel@tonic-gate 			printf("ttl %d ", fp->fr_ttl);
1560Sstevel@tonic-gate 		if (fp->fr_flx & FI_TCPUDP) {
1570Sstevel@tonic-gate 			printf("proto tcp/udp ");
1580Sstevel@tonic-gate 			pr = -1;
1590Sstevel@tonic-gate 		} else if (fp->fr_mip.fi_p) {
1600Sstevel@tonic-gate 			pr = fp->fr_ip.fi_p;
1610Sstevel@tonic-gate 			if ((p = getprotobynumber(fp->fr_proto)))
1620Sstevel@tonic-gate 				printf("proto %s ", p->p_name);
1630Sstevel@tonic-gate 			else
1640Sstevel@tonic-gate 				printf("proto %d ", fp->fr_proto);
1650Sstevel@tonic-gate 		}
1660Sstevel@tonic-gate 	}
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate 	if (type == FR_T_NONE) {
1690Sstevel@tonic-gate 		printf("all");
1700Sstevel@tonic-gate 	} else if (type == FR_T_IPF) {
1710Sstevel@tonic-gate 		printf("from %s", fp->fr_flags & FR_NOTSRCIP ? "!" : "");
1720Sstevel@tonic-gate 		if (fp->fr_satype != FRI_NORMAL) {
1730Sstevel@tonic-gate 			printf("%s", fp->fr_ifname);
1740Sstevel@tonic-gate 			if (fp->fr_satype == FRI_BROADCAST)
1750Sstevel@tonic-gate 				printf("/bcast");
1760Sstevel@tonic-gate 			else if (fp->fr_satype == FRI_NETWORK)
1770Sstevel@tonic-gate 				printf("/net");
1780Sstevel@tonic-gate 			else if (fp->fr_satype == FRI_NETMASKED)
1790Sstevel@tonic-gate 				printf("/netmasked");
1800Sstevel@tonic-gate 			else if (fp->fr_satype == FRI_PEERADDR)
1810Sstevel@tonic-gate 				printf("/peer");
1820Sstevel@tonic-gate 			else if (fp->fr_satype == FRI_LOOKUP)
1830Sstevel@tonic-gate 				printlookup(&fp->fr_ip.fi_src,
1840Sstevel@tonic-gate 					    &fp->fr_mip.fi_src);
1850Sstevel@tonic-gate 			else
186*637Sml37995 				printmask(fp->fr_v,
187*637Sml37995 					  (u_32_t *)&fp->fr_smsk.s_addr);
1880Sstevel@tonic-gate 		} else
1890Sstevel@tonic-gate 			printhostmask(fp->fr_v, (u_32_t *)&fp->fr_src.s_addr,
1900Sstevel@tonic-gate 				      (u_32_t *)&fp->fr_smsk.s_addr);
1910Sstevel@tonic-gate 		if (fp->fr_scmp)
1920Sstevel@tonic-gate 			printportcmp(pr, &fp->fr_tuc.ftu_src);
1930Sstevel@tonic-gate 
1940Sstevel@tonic-gate 		printf(" to %s", fp->fr_flags & FR_NOTDSTIP ? "!" : "");
1950Sstevel@tonic-gate 		if (fp->fr_datype != FRI_NORMAL) {
1960Sstevel@tonic-gate 			printf("%s", fp->fr_ifname);
1970Sstevel@tonic-gate 			if (fp->fr_datype == FRI_BROADCAST)
1980Sstevel@tonic-gate 				printf("/bcast");
1990Sstevel@tonic-gate 			else if (fp->fr_datype == FRI_NETWORK)
2000Sstevel@tonic-gate 				printf("/net");
2010Sstevel@tonic-gate 			else if (fp->fr_datype == FRI_NETMASKED)
2020Sstevel@tonic-gate 				printf("/netmasked");
2030Sstevel@tonic-gate 			else if (fp->fr_datype == FRI_PEERADDR)
2040Sstevel@tonic-gate 				printf("/peer");
2050Sstevel@tonic-gate 			else if (fp->fr_datype == FRI_LOOKUP)
2060Sstevel@tonic-gate 				printlookup(&fp->fr_ip.fi_dst,
2070Sstevel@tonic-gate 					    &fp->fr_mip.fi_dst);
2080Sstevel@tonic-gate 			else
209*637Sml37995 				printmask(fp->fr_v,
210*637Sml37995 					  (u_32_t *)&fp->fr_dmsk.s_addr);
2110Sstevel@tonic-gate 		} else
2120Sstevel@tonic-gate 			printhostmask(fp->fr_v, (u_32_t *)&fp->fr_dst.s_addr,
2130Sstevel@tonic-gate 				      (u_32_t *)&fp->fr_dmsk.s_addr);
2140Sstevel@tonic-gate 		if (fp->fr_dcmp)
2150Sstevel@tonic-gate 			printportcmp(pr, &fp->fr_tuc.ftu_dst);
2160Sstevel@tonic-gate 
2170Sstevel@tonic-gate 		if ((fp->fr_flx & FI_WITH) || (fp->fr_mflx & FI_WITH) ||
2180Sstevel@tonic-gate 		    fp->fr_optbits || fp->fr_optmask ||
2190Sstevel@tonic-gate 		    fp->fr_secbits || fp->fr_secmask) {
2200Sstevel@tonic-gate 			printf(" with");
2210Sstevel@tonic-gate 			if (fp->fr_optbits || fp->fr_optmask ||
2220Sstevel@tonic-gate 			    fp->fr_secbits || fp->fr_secmask) {
2230Sstevel@tonic-gate 				sec[0] = fp->fr_secmask;
2240Sstevel@tonic-gate 				sec[1] = fp->fr_secbits;
2250Sstevel@tonic-gate 				if (fp->fr_v == 4)
2260Sstevel@tonic-gate 					optprint(sec, fp->fr_optmask,
2270Sstevel@tonic-gate 						 fp->fr_optbits);
2280Sstevel@tonic-gate #ifdef	USE_INET6
2290Sstevel@tonic-gate 				else
2300Sstevel@tonic-gate 					optprintv6(sec, fp->fr_optmask,
2310Sstevel@tonic-gate 						   fp->fr_optbits);
2320Sstevel@tonic-gate #endif
2330Sstevel@tonic-gate 			} else if (fp->fr_mflx & FI_OPTIONS) {
2340Sstevel@tonic-gate 				if (!(fp->fr_flx & FI_OPTIONS))
2350Sstevel@tonic-gate 					printf(" not");
2360Sstevel@tonic-gate 				printf(" ipopts");
2370Sstevel@tonic-gate 			}
2380Sstevel@tonic-gate 			if (fp->fr_mflx & FI_SHORT) {
2390Sstevel@tonic-gate 				if (!(fp->fr_flx & FI_SHORT))
2400Sstevel@tonic-gate 					printf(" not");
2410Sstevel@tonic-gate 				printf(" short");
2420Sstevel@tonic-gate 			}
2430Sstevel@tonic-gate 			if (fp->fr_mflx & FI_FRAG) {
2440Sstevel@tonic-gate 				if (!(fp->fr_flx & FI_FRAG))
2450Sstevel@tonic-gate 					printf(" not");
2460Sstevel@tonic-gate 				printf(" frag");
2470Sstevel@tonic-gate 			}
2480Sstevel@tonic-gate 			if (fp->fr_mflx & FI_NATED) {
2490Sstevel@tonic-gate 				if (!(fp->fr_flx & FI_NATED))
2500Sstevel@tonic-gate 					printf(" not");
2510Sstevel@tonic-gate 				printf(" nat");
2520Sstevel@tonic-gate 			}
253492Syx160601 			if (fp->fr_mflx & FI_MULTICAST) {
254492Syx160601 				if (!(fp->fr_flx & FI_MULTICAST))
255492Syx160601 					printf(" not");
256492Syx160601 				printf(" multicast");
257492Syx160601 			}
258492Syx160601 			if (fp->fr_mflx & FI_BROADCAST) {
259492Syx160601 				if (!(fp->fr_flx & FI_BROADCAST))
260492Syx160601 					printf(" not");
261492Syx160601 				printf(" bcast");
262492Syx160601 			}
263492Syx160601 			if (fp->fr_mflx & FI_MBCAST) {
264492Syx160601 				if (!(fp->fr_flx & FI_MBCAST))
265492Syx160601 					printf(" not");
266492Syx160601 				printf(" mbcast");
267492Syx160601 			}
268492Syx160601 			if (fp->fr_mflx & FI_STATE) {
269492Syx160601 				if (!(fp->fr_flx & FI_STATE))
270492Syx160601 					printf(" not");
271492Syx160601 				printf(" state");
272492Syx160601 			}
273492Syx160601 			if (fp->fr_mflx & FI_BADNAT) {
274492Syx160601 				if (!(fp->fr_flx & FI_BADNAT))
275492Syx160601 					printf(" not");
276492Syx160601 				printf(" bad-nat");
277492Syx160601 			}
278492Syx160601 			if (fp->fr_mflx & FI_BAD) {
279492Syx160601 				if (!(fp->fr_flx & FI_BAD))
280492Syx160601 					printf(" not");
281492Syx160601 				printf(" bad");
282492Syx160601 			}
283492Syx160601 			if (fp->fr_mflx & FI_OOW) {
284492Syx160601 				if (!(fp->fr_flx & FI_OOW))
285492Syx160601 					printf(" not");
286492Syx160601 				printf(" oow");
287492Syx160601 			}
2880Sstevel@tonic-gate 			if (fp->fr_mflx & FI_LOWTTL) {
2890Sstevel@tonic-gate 				if (!(fp->fr_flx & FI_LOWTTL))
2900Sstevel@tonic-gate 					printf(" not");
2910Sstevel@tonic-gate 				printf(" lowttl");
2920Sstevel@tonic-gate 			}
2930Sstevel@tonic-gate 			if (fp->fr_mflx & FI_BADSRC) {
2940Sstevel@tonic-gate 				if (!(fp->fr_flx & FI_BADSRC))
2950Sstevel@tonic-gate 					printf(" not");
2960Sstevel@tonic-gate 				printf(" bad-src");
2970Sstevel@tonic-gate 			}
2980Sstevel@tonic-gate 		}
299*637Sml37995 		if ((fp->fr_proto == IPPROTO_ICMP
300*637Sml37995 #ifdef	USE_INET6
301*637Sml37995 		    || fp->fr_proto == IPPROTO_ICMPV6
302*637Sml37995 #endif
303*637Sml37995 		    ) && fp->fr_icmpm) {
3040Sstevel@tonic-gate 			int	type = fp->fr_icmp, code;
3050Sstevel@tonic-gate 
3060Sstevel@tonic-gate 			type = ntohs(fp->fr_icmp);
3070Sstevel@tonic-gate 			code = type & 0xff;
3080Sstevel@tonic-gate 			type /= 256;
3090Sstevel@tonic-gate 			if (type < (sizeof(icmptypes) / sizeof(char *) - 1) &&
310*637Sml37995 			    icmptypes[type] && fp->fr_proto == IPPROTO_ICMP)
3110Sstevel@tonic-gate 				printf(" icmp-type %s", icmptypes[type]);
3120Sstevel@tonic-gate 			else
3130Sstevel@tonic-gate 				printf(" icmp-type %d", type);
3140Sstevel@tonic-gate 			if (ntohs(fp->fr_icmpm) & 0xff)
3150Sstevel@tonic-gate 				printf(" code %d", code);
3160Sstevel@tonic-gate 		}
3170Sstevel@tonic-gate 		if ((fp->fr_proto == IPPROTO_TCP) &&
3180Sstevel@tonic-gate 		    (fp->fr_tcpf || fp->fr_tcpfm)) {
3190Sstevel@tonic-gate 			printf(" flags ");
3200Sstevel@tonic-gate 			if (fp->fr_tcpf & ~TCPF_ALL)
3210Sstevel@tonic-gate 				printf("0x%x", fp->fr_tcpf);
3220Sstevel@tonic-gate 			else
3230Sstevel@tonic-gate 				for (s = flagset, t = flags; *s; s++, t++)
3240Sstevel@tonic-gate 					if (fp->fr_tcpf & *t)
3250Sstevel@tonic-gate 						(void)putchar(*s);
3260Sstevel@tonic-gate 			if (fp->fr_tcpfm) {
3270Sstevel@tonic-gate 				(void)putchar('/');
3280Sstevel@tonic-gate 				if (fp->fr_tcpfm & ~TCPF_ALL)
3290Sstevel@tonic-gate 					printf("0x%x", fp->fr_tcpfm);
3300Sstevel@tonic-gate 				else
3310Sstevel@tonic-gate 					for (s = flagset, t = flags; *s;
3320Sstevel@tonic-gate 					     s++, t++)
3330Sstevel@tonic-gate 						if (fp->fr_tcpfm & *t)
3340Sstevel@tonic-gate 							(void)putchar(*s);
3350Sstevel@tonic-gate 			}
3360Sstevel@tonic-gate 		}
3370Sstevel@tonic-gate #ifdef IPFILTER_BPF
3380Sstevel@tonic-gate 	} else if (type == FR_T_BPFOPC) {
3390Sstevel@tonic-gate 		u_32_t *bp;
3400Sstevel@tonic-gate 		int i;
3410Sstevel@tonic-gate 
3420Sstevel@tonic-gate 		printf("{");
3430Sstevel@tonic-gate 		i = fp->fr_dsize / sizeof(*bp);
3440Sstevel@tonic-gate 
3450Sstevel@tonic-gate 		for (bp = fp->fr_data; i; i--, bp++)
3460Sstevel@tonic-gate 			printf(" 0x%08x", *bp);
3470Sstevel@tonic-gate 
3480Sstevel@tonic-gate 		printf(" }");
3490Sstevel@tonic-gate #endif
3500Sstevel@tonic-gate 	} else if (type == FR_T_COMPIPF) {
3510Sstevel@tonic-gate 		;
3520Sstevel@tonic-gate 	} else if (type == FR_T_CALLFUNC) {
3530Sstevel@tonic-gate 		printf("call function at %p", fp->fr_data);
3540Sstevel@tonic-gate 	} else {
3550Sstevel@tonic-gate 		printf("[unknown filter type %#x]", fp->fr_type);
3560Sstevel@tonic-gate 	}
3570Sstevel@tonic-gate 
3580Sstevel@tonic-gate 	if (fp->fr_flags & FR_KEEPSTATE) {
3590Sstevel@tonic-gate 		printf(" keep state");
3600Sstevel@tonic-gate 		if ((fp->fr_flags & (FR_STSTRICT|FR_NEWISN)) ||
3610Sstevel@tonic-gate 		    (fp->fr_statemax != 0) || (fp->fr_age[0] != 0)) {
3620Sstevel@tonic-gate 			printf(" (");
3630Sstevel@tonic-gate 			if (fp->fr_statemax != 0)
3640Sstevel@tonic-gate 				printf(" limit %u", fp->fr_statemax);
3650Sstevel@tonic-gate 			if (fp->fr_flags & FR_FRSTRICT)
3660Sstevel@tonic-gate 				printf(" strict");
3670Sstevel@tonic-gate 			if (fp->fr_flags & FR_NEWISN)
3680Sstevel@tonic-gate 				printf(" newisn");
3690Sstevel@tonic-gate 			if (fp->fr_age[0] || fp->fr_age[1])
3700Sstevel@tonic-gate 				printf(" age %d/%d", fp->fr_age[0],
3710Sstevel@tonic-gate 				       fp->fr_age[1]);
3720Sstevel@tonic-gate 			printf(" )");
3730Sstevel@tonic-gate 		}
3740Sstevel@tonic-gate 	}
3750Sstevel@tonic-gate 	if (fp->fr_flags & FR_KEEPFRAG) {
3760Sstevel@tonic-gate 		printf(" keep frags");
3770Sstevel@tonic-gate 		if (fp->fr_flags & (FR_FRSTRICT)) {
3780Sstevel@tonic-gate 			printf(" (");
3790Sstevel@tonic-gate 			if (fp->fr_flags & FR_FRSTRICT)
3800Sstevel@tonic-gate 				printf(" strict");
3810Sstevel@tonic-gate 			printf(" )");
3820Sstevel@tonic-gate 
3830Sstevel@tonic-gate 		}
3840Sstevel@tonic-gate 	}
3850Sstevel@tonic-gate 	if (fp->fr_isc != (struct ipscan *)-1) {
3860Sstevel@tonic-gate 		if (fp->fr_isctag[0])
3870Sstevel@tonic-gate 			printf(" scan %s", fp->fr_isctag);
3880Sstevel@tonic-gate 		else
3890Sstevel@tonic-gate 			printf(" scan *");
3900Sstevel@tonic-gate 	}
3910Sstevel@tonic-gate 	if (*fp->fr_grhead != '\0')
3920Sstevel@tonic-gate 		printf(" head %s", fp->fr_grhead);
3930Sstevel@tonic-gate 	if (*fp->fr_group != '\0')
3940Sstevel@tonic-gate 		printf(" group %s", fp->fr_group);
3950Sstevel@tonic-gate 	if (fp->fr_logtag != FR_NOLOGTAG)
3960Sstevel@tonic-gate 		printf(" log-tag %u", fp->fr_logtag);
3970Sstevel@tonic-gate 	if (fp->fr_pps)
3980Sstevel@tonic-gate 		printf(" pps %d", fp->fr_pps);
3990Sstevel@tonic-gate 	(void)putchar('\n');
4000Sstevel@tonic-gate }
401