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  *
62393Syz155240  * $Id: printfr.c,v 1.43.2.12 2005/06/12 07:18:42 darrenr Exp $
70Sstevel@tonic-gate  *
8*5868Sdr146992  * Copyright 2008 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 
162393Syz155240 static void printaddr(int, int, char *, u_32_t *, u_32_t *);
172393Syz155240 
182393Syz155240 static void printaddr(v, type, ifname, addr, mask)
192393Syz155240 int v, type;
202393Syz155240 char *ifname;
212393Syz155240 u_32_t *addr, *mask;
222393Syz155240 {
232393Syz155240 	char *suffix;
242393Syz155240 
252393Syz155240 	switch (type)
262393Syz155240 	{
272393Syz155240 	case FRI_BROADCAST :
282393Syz155240 		suffix = "/bcast";
292393Syz155240 		break;
302393Syz155240 
312393Syz155240 	case FRI_DYNAMIC :
322393Syz155240 		printf("%s", ifname);
332393Syz155240 		printmask(v, mask);
342393Syz155240 		suffix = NULL;
352393Syz155240 		break;
362393Syz155240 
372393Syz155240 	case FRI_NETWORK :
382393Syz155240 		suffix = "/net";
392393Syz155240 		break;
402393Syz155240 
412393Syz155240 	case FRI_NETMASKED :
422393Syz155240 		suffix = "/netmasked";
432393Syz155240 		break;
442393Syz155240 
452393Syz155240 	case FRI_PEERADDR :
462393Syz155240 		suffix = "/peer";
472393Syz155240 		break;
482393Syz155240 
492393Syz155240 	case FRI_LOOKUP :
502393Syz155240 		suffix = NULL;
512393Syz155240 		printlookup((i6addr_t *)addr, (i6addr_t *)mask);
522393Syz155240 		break;
532393Syz155240 
542393Syz155240 	case FRI_NORMAL :
552393Syz155240 		printhostmask(v, addr, mask);
562393Syz155240 		suffix = NULL;
572393Syz155240 		break;
582393Syz155240 	default :
592393Syz155240 		printf("<%d>", type);
602393Syz155240 		printmask(v, mask);
612393Syz155240 		suffix = NULL;
622393Syz155240 		break;
632393Syz155240 	}
642393Syz155240 
652393Syz155240 	if (suffix != NULL) {
662393Syz155240 		printf("%s/%s", ifname, suffix);
672393Syz155240 	}
682393Syz155240 }
692393Syz155240 
700Sstevel@tonic-gate 
710Sstevel@tonic-gate void printlookup(addr, mask)
720Sstevel@tonic-gate i6addr_t *addr, *mask;
730Sstevel@tonic-gate {
740Sstevel@tonic-gate 	switch (addr->iplookuptype)
750Sstevel@tonic-gate 	{
760Sstevel@tonic-gate 	case IPLT_POOL :
770Sstevel@tonic-gate 		printf("pool/");
780Sstevel@tonic-gate 		break;
790Sstevel@tonic-gate 	case IPLT_HASH :
800Sstevel@tonic-gate 		printf("hash/");
810Sstevel@tonic-gate 		break;
820Sstevel@tonic-gate 	default :
830Sstevel@tonic-gate 		printf("lookup(%x)=", addr->iplookuptype);
840Sstevel@tonic-gate 		break;
850Sstevel@tonic-gate 	}
860Sstevel@tonic-gate 
870Sstevel@tonic-gate 	printf("%u", addr->iplookupnum);
880Sstevel@tonic-gate 	if (opts & OPT_UNDEF) {
890Sstevel@tonic-gate 		if (mask->iplookupptr == NULL) {
900Sstevel@tonic-gate 			printf("(!)");
910Sstevel@tonic-gate 		}
920Sstevel@tonic-gate 	}
930Sstevel@tonic-gate }
940Sstevel@tonic-gate 
950Sstevel@tonic-gate 
960Sstevel@tonic-gate /*
970Sstevel@tonic-gate  * print the filter structure in a useful way
980Sstevel@tonic-gate  */
990Sstevel@tonic-gate void	printfr(fp, iocfunc)
1000Sstevel@tonic-gate struct	frentry	*fp;
1010Sstevel@tonic-gate ioctlfunc_t	iocfunc;
1020Sstevel@tonic-gate {
1030Sstevel@tonic-gate 	struct protoent	*p;
1040Sstevel@tonic-gate 	u_short	sec[2];
1050Sstevel@tonic-gate 	u_32_t type;
1060Sstevel@tonic-gate 	u_char *t;
1070Sstevel@tonic-gate 	char *s;
1080Sstevel@tonic-gate 	int pr;
1090Sstevel@tonic-gate 
1100Sstevel@tonic-gate 	pr = -2;
1110Sstevel@tonic-gate 	type = fp->fr_type & ~FR_T_BUILTIN;
1120Sstevel@tonic-gate 
1130Sstevel@tonic-gate 	if ((fp->fr_type & FR_T_BUILTIN) != 0)
1140Sstevel@tonic-gate 		printf("# Builtin: ");
1150Sstevel@tonic-gate 
1162393Syz155240 	if (fp->fr_collect != 0)
1172393Syz155240 		printf("%u ", fp->fr_collect);
1182393Syz155240 
1190Sstevel@tonic-gate 	if (fp->fr_type == FR_T_CALLFUNC) {
1200Sstevel@tonic-gate 		;
1210Sstevel@tonic-gate 	} else if (fp->fr_func != NULL) {
1220Sstevel@tonic-gate 		printf("call");
1230Sstevel@tonic-gate 		if ((fp->fr_flags & FR_CALLNOW) != 0)
1240Sstevel@tonic-gate 			printf(" now");
1250Sstevel@tonic-gate 		s = kvatoname(fp->fr_func, iocfunc);
1260Sstevel@tonic-gate 		printf(" %s/%u", s ? s : "?", fp->fr_arg);
1270Sstevel@tonic-gate 	} else if (FR_ISPASS(fp->fr_flags))
1280Sstevel@tonic-gate 		printf("pass");
1290Sstevel@tonic-gate 	else if (FR_ISBLOCK(fp->fr_flags)) {
1300Sstevel@tonic-gate 		printf("block");
1310Sstevel@tonic-gate 		if (fp->fr_flags & FR_RETICMP) {
1320Sstevel@tonic-gate 			if ((fp->fr_flags & FR_RETMASK) == FR_FAKEICMP)
1330Sstevel@tonic-gate 				printf(" return-icmp-as-dest");
1340Sstevel@tonic-gate 			else if ((fp->fr_flags & FR_RETMASK) == FR_RETICMP)
1350Sstevel@tonic-gate 				printf(" return-icmp");
1360Sstevel@tonic-gate 			if (fp->fr_icode) {
1370Sstevel@tonic-gate 				if (fp->fr_icode <= MAX_ICMPCODE)
1380Sstevel@tonic-gate 					printf("(%s)",
1390Sstevel@tonic-gate 						icmpcodes[(int)fp->fr_icode]);
1400Sstevel@tonic-gate 				else
1410Sstevel@tonic-gate 					printf("(%d)", fp->fr_icode);
1420Sstevel@tonic-gate 			}
1430Sstevel@tonic-gate 		} else if ((fp->fr_flags & FR_RETMASK) == FR_RETRST)
1440Sstevel@tonic-gate 			printf(" return-rst");
1450Sstevel@tonic-gate 	} else if ((fp->fr_flags & FR_LOGMASK) == FR_LOG) {
1460Sstevel@tonic-gate 		printlog(fp);
1470Sstevel@tonic-gate 	} else if (FR_ISACCOUNT(fp->fr_flags))
1480Sstevel@tonic-gate 		printf("count");
1490Sstevel@tonic-gate 	else if (FR_ISAUTH(fp->fr_flags))
1500Sstevel@tonic-gate 		printf("auth");
1510Sstevel@tonic-gate 	else if (FR_ISPREAUTH(fp->fr_flags))
1520Sstevel@tonic-gate 		printf("preauth");
1530Sstevel@tonic-gate 	else if (FR_ISNOMATCH(fp->fr_flags))
1540Sstevel@tonic-gate 		printf("nomatch");
1550Sstevel@tonic-gate 	else if (FR_ISSKIP(fp->fr_flags))
1560Sstevel@tonic-gate 		printf("skip %u", fp->fr_arg);
1570Sstevel@tonic-gate 	else {
1580Sstevel@tonic-gate 		printf("%x", fp->fr_flags);
1590Sstevel@tonic-gate 	}
1600Sstevel@tonic-gate 
1610Sstevel@tonic-gate 	if (fp->fr_flags & FR_OUTQUE)
1620Sstevel@tonic-gate 		printf(" out ");
1630Sstevel@tonic-gate 	else
1640Sstevel@tonic-gate 		printf(" in ");
1650Sstevel@tonic-gate 
1660Sstevel@tonic-gate 	if (((fp->fr_flags & FR_LOGB) == FR_LOGB) ||
1670Sstevel@tonic-gate 	    ((fp->fr_flags & FR_LOGP) == FR_LOGP)) {
1680Sstevel@tonic-gate 		printlog(fp);
1690Sstevel@tonic-gate 		putchar(' ');
1700Sstevel@tonic-gate 	}
1710Sstevel@tonic-gate 
1720Sstevel@tonic-gate 	if (fp->fr_flags & FR_QUICK)
1730Sstevel@tonic-gate 		printf("quick ");
1740Sstevel@tonic-gate 
1750Sstevel@tonic-gate 	if (*fp->fr_ifname) {
1760Sstevel@tonic-gate 		printifname("on ", fp->fr_ifname, fp->fr_ifa);
1770Sstevel@tonic-gate 		if (*fp->fr_ifnames[1] && strcmp(fp->fr_ifnames[1], "*"))
1780Sstevel@tonic-gate 			printifname(",", fp->fr_ifnames[1], fp->fr_ifas[1]);
1790Sstevel@tonic-gate 		putchar(' ');
1802393Syz155240 	}
1810Sstevel@tonic-gate 
1822393Syz155240 	if (*fp->fr_dif.fd_ifname || (fp->fr_flags & FR_DUP))
1832393Syz155240 		print_toif("dup-to", &fp->fr_dif);
1842393Syz155240 	if (*fp->fr_tif.fd_ifname)
1852393Syz155240 		print_toif("to", &fp->fr_tif);
1862393Syz155240 	if (*fp->fr_rif.fd_ifname)
1872393Syz155240 		print_toif("reply-to", &fp->fr_rif);
1882393Syz155240 	if (fp->fr_flags & FR_FASTROUTE)
1892393Syz155240 		printf("fastroute ");
1900Sstevel@tonic-gate 
1912393Syz155240 	if ((*fp->fr_ifnames[2] && strcmp(fp->fr_ifnames[2], "*")) ||
1922393Syz155240 	    (*fp->fr_ifnames[3] && strcmp(fp->fr_ifnames[3], "*"))) {
1932393Syz155240 		if (fp->fr_flags & FR_OUTQUE)
1942393Syz155240 			printf("in-via ");
1952393Syz155240 		else
1962393Syz155240 			printf("out-via ");
1970Sstevel@tonic-gate 
1982393Syz155240 		if (*fp->fr_ifnames[2]) {
1992393Syz155240 			printifname("", fp->fr_ifnames[2],
2002393Syz155240 				    fp->fr_ifas[2]);
2012393Syz155240 			putchar(' ');
2020Sstevel@tonic-gate 
2032393Syz155240 			if (*fp->fr_ifnames[3]) {
2042393Syz155240 				printifname(",", fp->fr_ifnames[3],
2052393Syz155240 					    fp->fr_ifas[3]);
2060Sstevel@tonic-gate 			}
2070Sstevel@tonic-gate 		}
2080Sstevel@tonic-gate 	}
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate 	if (type == FR_T_IPF) {
2110Sstevel@tonic-gate 		if (fp->fr_mip.fi_tos)
2120Sstevel@tonic-gate 			printf("tos %#x ", fp->fr_tos);
2130Sstevel@tonic-gate 		if (fp->fr_mip.fi_ttl)
2140Sstevel@tonic-gate 			printf("ttl %d ", fp->fr_ttl);
2150Sstevel@tonic-gate 		if (fp->fr_flx & FI_TCPUDP) {
2160Sstevel@tonic-gate 			printf("proto tcp/udp ");
2170Sstevel@tonic-gate 			pr = -1;
2180Sstevel@tonic-gate 		} else if (fp->fr_mip.fi_p) {
2190Sstevel@tonic-gate 			pr = fp->fr_ip.fi_p;
2202393Syz155240 			p = getprotobynumber(pr);
2212393Syz155240 			printf("proto ");
2222393Syz155240 			printproto(p, pr, NULL);
2232393Syz155240 			putchar(' ');
2240Sstevel@tonic-gate 		}
2250Sstevel@tonic-gate 	}
2260Sstevel@tonic-gate 
2270Sstevel@tonic-gate 	if (type == FR_T_NONE) {
2280Sstevel@tonic-gate 		printf("all");
2290Sstevel@tonic-gate 	} else if (type == FR_T_IPF) {
2300Sstevel@tonic-gate 		printf("from %s", fp->fr_flags & FR_NOTSRCIP ? "!" : "");
2312393Syz155240 		printaddr(fp->fr_v, fp->fr_satype, fp->fr_ifname,
2322393Syz155240 			  &fp->fr_src.s_addr, &fp->fr_smsk.s_addr);
2330Sstevel@tonic-gate 		if (fp->fr_scmp)
2340Sstevel@tonic-gate 			printportcmp(pr, &fp->fr_tuc.ftu_src);
2350Sstevel@tonic-gate 
2360Sstevel@tonic-gate 		printf(" to %s", fp->fr_flags & FR_NOTDSTIP ? "!" : "");
2372393Syz155240 		printaddr(fp->fr_v, fp->fr_datype, fp->fr_ifname,
2382393Syz155240 			  &fp->fr_dst.s_addr, &fp->fr_dmsk.s_addr);
2390Sstevel@tonic-gate 		if (fp->fr_dcmp)
2400Sstevel@tonic-gate 			printportcmp(pr, &fp->fr_tuc.ftu_dst);
2410Sstevel@tonic-gate 
242637Sml37995 		if ((fp->fr_proto == IPPROTO_ICMP
243637Sml37995 #ifdef	USE_INET6
244637Sml37995 		    || fp->fr_proto == IPPROTO_ICMPV6
245637Sml37995 #endif
246637Sml37995 		    ) && fp->fr_icmpm) {
2470Sstevel@tonic-gate 			int	type = fp->fr_icmp, code;
2480Sstevel@tonic-gate 
2490Sstevel@tonic-gate 			type = ntohs(fp->fr_icmp);
2500Sstevel@tonic-gate 			code = type & 0xff;
2510Sstevel@tonic-gate 			type /= 256;
2520Sstevel@tonic-gate 			if (type < (sizeof(icmptypes) / sizeof(char *) - 1) &&
253637Sml37995 			    icmptypes[type] && fp->fr_proto == IPPROTO_ICMP)
2540Sstevel@tonic-gate 				printf(" icmp-type %s", icmptypes[type]);
2550Sstevel@tonic-gate 			else
2560Sstevel@tonic-gate 				printf(" icmp-type %d", type);
2570Sstevel@tonic-gate 			if (ntohs(fp->fr_icmpm) & 0xff)
2580Sstevel@tonic-gate 				printf(" code %d", code);
2590Sstevel@tonic-gate 		}
2600Sstevel@tonic-gate 		if ((fp->fr_proto == IPPROTO_TCP) &&
2610Sstevel@tonic-gate 		    (fp->fr_tcpf || fp->fr_tcpfm)) {
2620Sstevel@tonic-gate 			printf(" flags ");
2630Sstevel@tonic-gate 			if (fp->fr_tcpf & ~TCPF_ALL)
2640Sstevel@tonic-gate 				printf("0x%x", fp->fr_tcpf);
2650Sstevel@tonic-gate 			else
2660Sstevel@tonic-gate 				for (s = flagset, t = flags; *s; s++, t++)
2670Sstevel@tonic-gate 					if (fp->fr_tcpf & *t)
2680Sstevel@tonic-gate 						(void)putchar(*s);
2690Sstevel@tonic-gate 			if (fp->fr_tcpfm) {
2700Sstevel@tonic-gate 				(void)putchar('/');
2710Sstevel@tonic-gate 				if (fp->fr_tcpfm & ~TCPF_ALL)
2720Sstevel@tonic-gate 					printf("0x%x", fp->fr_tcpfm);
2730Sstevel@tonic-gate 				else
2740Sstevel@tonic-gate 					for (s = flagset, t = flags; *s;
2750Sstevel@tonic-gate 					     s++, t++)
2760Sstevel@tonic-gate 						if (fp->fr_tcpfm & *t)
2770Sstevel@tonic-gate 							(void)putchar(*s);
2780Sstevel@tonic-gate 			}
2790Sstevel@tonic-gate 		}
2800Sstevel@tonic-gate 	} else if (type == FR_T_BPFOPC) {
2812393Syz155240 		fakebpf_t *fb;
2820Sstevel@tonic-gate 		int i;
2830Sstevel@tonic-gate 
2842393Syz155240 		printf("bpf-v%d { \"", fp->fr_v);
2852393Syz155240 		i = fp->fr_dsize / sizeof(*fb);
2860Sstevel@tonic-gate 
2872393Syz155240 		for (fb = fp->fr_data, s = ""; i; i--, fb++, s = " ")
2882393Syz155240 			printf("%s%#x %#x %#x %#x", s, fb->fb_c, fb->fb_t,
2892393Syz155240 			       fb->fb_f, fb->fb_k);
2900Sstevel@tonic-gate 
2912393Syz155240 		printf("\" }");
2920Sstevel@tonic-gate 	} else if (type == FR_T_COMPIPF) {
2930Sstevel@tonic-gate 		;
2940Sstevel@tonic-gate 	} else if (type == FR_T_CALLFUNC) {
2950Sstevel@tonic-gate 		printf("call function at %p", fp->fr_data);
2960Sstevel@tonic-gate 	} else {
2970Sstevel@tonic-gate 		printf("[unknown filter type %#x]", fp->fr_type);
2980Sstevel@tonic-gate 	}
2990Sstevel@tonic-gate 
3002393Syz155240 	if ((type == FR_T_IPF) &&
3012393Syz155240 	    ((fp->fr_flx & FI_WITH) || (fp->fr_mflx & FI_WITH) ||
3022393Syz155240 	     fp->fr_optbits || fp->fr_optmask ||
3032393Syz155240 	     fp->fr_secbits || fp->fr_secmask)) {
3042393Syz155240 		char *comma = " ";
3052393Syz155240 
3062393Syz155240 		printf(" with");
3072393Syz155240 		if (fp->fr_optbits || fp->fr_optmask ||
3082393Syz155240 		    fp->fr_secbits || fp->fr_secmask) {
3092393Syz155240 			sec[0] = fp->fr_secmask;
3102393Syz155240 			sec[1] = fp->fr_secbits;
3112393Syz155240 			if (fp->fr_v == 4)
3122393Syz155240 				optprint(sec, fp->fr_optmask, fp->fr_optbits);
3132393Syz155240 #ifdef	USE_INET6
3142393Syz155240 			else
3152393Syz155240 				optprintv6(sec, fp->fr_optmask,
3162393Syz155240 					   fp->fr_optbits);
3172393Syz155240 #endif
3182393Syz155240 		} else if (fp->fr_mflx & FI_OPTIONS) {
3192393Syz155240 			fputs(comma, stdout);
3202393Syz155240 			if (!(fp->fr_flx & FI_OPTIONS))
3212393Syz155240 				printf("not ");
3222393Syz155240 			printf("ipopts");
3232393Syz155240 			comma = ",";
3242393Syz155240 		}
3252393Syz155240 		if (fp->fr_mflx & FI_SHORT) {
3262393Syz155240 			fputs(comma, stdout);
3272393Syz155240 			if (!(fp->fr_flx & FI_SHORT))
3282393Syz155240 				printf("not ");
3292393Syz155240 			printf("short");
3302393Syz155240 			comma = ",";
3312393Syz155240 		}
3322393Syz155240 		if (fp->fr_mflx & FI_FRAG) {
3332393Syz155240 			fputs(comma, stdout);
3342393Syz155240 			if (!(fp->fr_flx & FI_FRAG))
3352393Syz155240 				printf("not ");
3362393Syz155240 			printf("frag");
3372393Syz155240 			comma = ",";
3382393Syz155240 		}
3392393Syz155240 		if (fp->fr_mflx & FI_FRAGBODY) {
3402393Syz155240 			fputs(comma, stdout);
3412393Syz155240 			if (!(fp->fr_flx & FI_FRAGBODY))
3422393Syz155240 				printf("not ");
3432393Syz155240 			printf("frag-body");
3442393Syz155240 			comma = ",";
3452393Syz155240 		}
3462393Syz155240 		if (fp->fr_mflx & FI_NATED) {
3472393Syz155240 			fputs(comma, stdout);
3482393Syz155240 			if (!(fp->fr_flx & FI_NATED))
3492393Syz155240 				printf("not ");
3502393Syz155240 			printf("nat");
3512393Syz155240 			comma = ",";
3522393Syz155240 		}
3532393Syz155240 		if (fp->fr_mflx & FI_LOWTTL) {
3542393Syz155240 			fputs(comma, stdout);
3552393Syz155240 			if (!(fp->fr_flx & FI_LOWTTL))
3562393Syz155240 				printf("not ");
3572393Syz155240 			printf("lowttl");
3582393Syz155240 			comma = ",";
3592393Syz155240 		}
3602393Syz155240 		if (fp->fr_mflx & FI_BAD) {
3612393Syz155240 			fputs(comma, stdout);
3622393Syz155240 			if (!(fp->fr_flx & FI_BAD))
3632393Syz155240 				printf("not ");
3642393Syz155240 			printf("bad");
3652393Syz155240 			comma = ",";
3662393Syz155240 		}
3672393Syz155240 		if (fp->fr_mflx & FI_BADSRC) {
3682393Syz155240 			fputs(comma, stdout);
3692393Syz155240 			if (!(fp->fr_flx & FI_BADSRC))
3702393Syz155240 				printf("not ");
3712393Syz155240 			printf("bad-src");
3722393Syz155240 			comma = ",";
3732393Syz155240 		}
3742393Syz155240 		if (fp->fr_mflx & FI_BADNAT) {
3752393Syz155240 			fputs(comma, stdout);
3762393Syz155240 			if (!(fp->fr_flx & FI_BADNAT))
3772393Syz155240 				printf("not ");
3782393Syz155240 			printf("bad-nat");
3792393Syz155240 			comma = ",";
3802393Syz155240 		}
3812393Syz155240 		if (fp->fr_mflx & FI_OOW) {
3822393Syz155240 			fputs(comma, stdout);
3832393Syz155240 			if (!(fp->fr_flx & FI_OOW))
3842393Syz155240 				printf("not ");
3852393Syz155240 			printf("oow");
3862393Syz155240 		}
3872393Syz155240 		if (fp->fr_mflx & FI_MULTICAST) {
3882393Syz155240 			fputs(comma, stdout);
3892393Syz155240 			if (!(fp->fr_flx & FI_MULTICAST))
3902393Syz155240 				printf("not ");
391*5868Sdr146992 			printf("mcast");
3922393Syz155240 			comma = ",";
3932393Syz155240 		}
3942393Syz155240 		if (fp->fr_mflx & FI_BROADCAST) {
3952393Syz155240 			fputs(comma, stdout);
3962393Syz155240 			if (!(fp->fr_flx & FI_BROADCAST))
3972393Syz155240 				printf("not ");
3982393Syz155240 			printf("bcast");
3992393Syz155240 			comma = ",";
4002393Syz155240 		}
4012393Syz155240 		if (fp->fr_mflx & FI_MBCAST) {
4022393Syz155240 			fputs(comma, stdout);
4032393Syz155240 			if (!(fp->fr_flx & FI_MBCAST))
4042393Syz155240 				printf("not ");
4052393Syz155240 			printf("mbcast");
4062393Syz155240 			comma = ",";
4072393Syz155240 		}
4082393Syz155240 		if (fp->fr_mflx & FI_STATE) {
4092393Syz155240 			fputs(comma, stdout);
4102393Syz155240 			if (!(fp->fr_flx & FI_STATE))
4112393Syz155240 				printf("not ");
4122393Syz155240 			printf("state");
4132393Syz155240 			comma = ",";
4142393Syz155240 		}
4152393Syz155240 	}
4162393Syz155240 
4170Sstevel@tonic-gate 	if (fp->fr_flags & FR_KEEPSTATE) {
4180Sstevel@tonic-gate 		printf(" keep state");
4192393Syz155240 		if ((fp->fr_flags & (FR_STSTRICT|FR_NEWISN|FR_NOICMPERR|FR_STATESYNC)) ||
4200Sstevel@tonic-gate 		    (fp->fr_statemax != 0) || (fp->fr_age[0] != 0)) {
4212393Syz155240 			char *comma = "";
4220Sstevel@tonic-gate 			printf(" (");
4232393Syz155240 			if (fp->fr_statemax != 0) {
4242393Syz155240 				printf("limit %u", fp->fr_statemax);
4252393Syz155240 				comma = ",";
4262393Syz155240 			}
4272393Syz155240 			if (fp->fr_flags & FR_STSTRICT) {
4282393Syz155240 				printf("%sstrict", comma);
4292393Syz155240 				comma = ",";
4302393Syz155240 			}
4312393Syz155240 			if (fp->fr_flags & FR_NEWISN) {
4322393Syz155240 				printf("%snewisn", comma);
4332393Syz155240 				comma = ",";
4342393Syz155240 			}
4352393Syz155240 			if (fp->fr_flags & FR_NOICMPERR) {
4362393Syz155240 				printf("%sno-icmp-err", comma);
4372393Syz155240 				comma = ",";
4382393Syz155240 			}
4392393Syz155240 			if (fp->fr_flags & FR_STATESYNC) {
4402393Syz155240 				printf("%ssync", comma);
4412393Syz155240 				comma = ",";
4422393Syz155240 			}
4430Sstevel@tonic-gate 			if (fp->fr_age[0] || fp->fr_age[1])
4442393Syz155240 				printf("%sage %d/%d", comma, fp->fr_age[0],
4450Sstevel@tonic-gate 				       fp->fr_age[1]);
4462393Syz155240 			printf(")");
4470Sstevel@tonic-gate 		}
4480Sstevel@tonic-gate 	}
4490Sstevel@tonic-gate 	if (fp->fr_flags & FR_KEEPFRAG) {
4500Sstevel@tonic-gate 		printf(" keep frags");
4510Sstevel@tonic-gate 		if (fp->fr_flags & (FR_FRSTRICT)) {
4520Sstevel@tonic-gate 			printf(" (");
4530Sstevel@tonic-gate 			if (fp->fr_flags & FR_FRSTRICT)
4540Sstevel@tonic-gate 				printf(" strict");
4550Sstevel@tonic-gate 			printf(" )");
4560Sstevel@tonic-gate 
4570Sstevel@tonic-gate 		}
4580Sstevel@tonic-gate 	}
4590Sstevel@tonic-gate 	if (fp->fr_isc != (struct ipscan *)-1) {
4600Sstevel@tonic-gate 		if (fp->fr_isctag[0])
4610Sstevel@tonic-gate 			printf(" scan %s", fp->fr_isctag);
4620Sstevel@tonic-gate 		else
4630Sstevel@tonic-gate 			printf(" scan *");
4640Sstevel@tonic-gate 	}
4650Sstevel@tonic-gate 	if (*fp->fr_grhead != '\0')
4660Sstevel@tonic-gate 		printf(" head %s", fp->fr_grhead);
4670Sstevel@tonic-gate 	if (*fp->fr_group != '\0')
4680Sstevel@tonic-gate 		printf(" group %s", fp->fr_group);
4692393Syz155240 	if (fp->fr_logtag != FR_NOLOGTAG || *fp->fr_nattag.ipt_tag) {
4702393Syz155240 		char *s = "";
4712393Syz155240 
4722393Syz155240 		printf(" set-tag(");
4732393Syz155240 		if (fp->fr_logtag != FR_NOLOGTAG) {
4742393Syz155240 			printf("log=%u", fp->fr_logtag);
4752393Syz155240 			s = ", ";
4762393Syz155240 		}
4772393Syz155240 		if (*fp->fr_nattag.ipt_tag) {
4782393Syz155240 			printf("%snat=%-.*s", s, IPFTAG_LEN,
4792393Syz155240 				fp->fr_nattag.ipt_tag);
4802393Syz155240 		}
4812393Syz155240 		printf(")");
4822393Syz155240 	}
4830Sstevel@tonic-gate 	if (fp->fr_pps)
4840Sstevel@tonic-gate 		printf(" pps %d", fp->fr_pps);
4850Sstevel@tonic-gate 	(void)putchar('\n');
4860Sstevel@tonic-gate }
487