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  *
6*2393Syz155240  * $Id: printfr.c,v 1.43.2.12 2005/06/12 07:18:42 darrenr Exp $
70Sstevel@tonic-gate  *
8*2393Syz155240  * Copyright 2006 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 
16*2393Syz155240 static void printaddr(int, int, char *, u_32_t *, u_32_t *);
17*2393Syz155240 
18*2393Syz155240 static void printaddr(v, type, ifname, addr, mask)
19*2393Syz155240 int v, type;
20*2393Syz155240 char *ifname;
21*2393Syz155240 u_32_t *addr, *mask;
22*2393Syz155240 {
23*2393Syz155240 	char *suffix;
24*2393Syz155240 
25*2393Syz155240 	switch (type)
26*2393Syz155240 	{
27*2393Syz155240 	case FRI_BROADCAST :
28*2393Syz155240 		suffix = "/bcast";
29*2393Syz155240 		break;
30*2393Syz155240 
31*2393Syz155240 	case FRI_DYNAMIC :
32*2393Syz155240 		printf("%s", ifname);
33*2393Syz155240 		printmask(v, mask);
34*2393Syz155240 		suffix = NULL;
35*2393Syz155240 		break;
36*2393Syz155240 
37*2393Syz155240 	case FRI_NETWORK :
38*2393Syz155240 		suffix = "/net";
39*2393Syz155240 		break;
40*2393Syz155240 
41*2393Syz155240 	case FRI_NETMASKED :
42*2393Syz155240 		suffix = "/netmasked";
43*2393Syz155240 		break;
44*2393Syz155240 
45*2393Syz155240 	case FRI_PEERADDR :
46*2393Syz155240 		suffix = "/peer";
47*2393Syz155240 		break;
48*2393Syz155240 
49*2393Syz155240 	case FRI_LOOKUP :
50*2393Syz155240 		suffix = NULL;
51*2393Syz155240 		printlookup((i6addr_t *)addr, (i6addr_t *)mask);
52*2393Syz155240 		break;
53*2393Syz155240 
54*2393Syz155240 	case FRI_NORMAL :
55*2393Syz155240 		printhostmask(v, addr, mask);
56*2393Syz155240 		suffix = NULL;
57*2393Syz155240 		break;
58*2393Syz155240 	default :
59*2393Syz155240 		printf("<%d>", type);
60*2393Syz155240 		printmask(v, mask);
61*2393Syz155240 		suffix = NULL;
62*2393Syz155240 		break;
63*2393Syz155240 	}
64*2393Syz155240 
65*2393Syz155240 	if (suffix != NULL) {
66*2393Syz155240 		printf("%s/%s", ifname, suffix);
67*2393Syz155240 	}
68*2393Syz155240 }
69*2393Syz155240 
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 
116*2393Syz155240 	if (fp->fr_collect != 0)
117*2393Syz155240 		printf("%u ", fp->fr_collect);
118*2393Syz155240 
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(' ');
180*2393Syz155240 	}
1810Sstevel@tonic-gate 
182*2393Syz155240 	if (*fp->fr_dif.fd_ifname || (fp->fr_flags & FR_DUP))
183*2393Syz155240 		print_toif("dup-to", &fp->fr_dif);
184*2393Syz155240 	if (*fp->fr_tif.fd_ifname)
185*2393Syz155240 		print_toif("to", &fp->fr_tif);
186*2393Syz155240 	if (*fp->fr_rif.fd_ifname)
187*2393Syz155240 		print_toif("reply-to", &fp->fr_rif);
188*2393Syz155240 	if (fp->fr_flags & FR_FASTROUTE)
189*2393Syz155240 		printf("fastroute ");
1900Sstevel@tonic-gate 
191*2393Syz155240 	if ((*fp->fr_ifnames[2] && strcmp(fp->fr_ifnames[2], "*")) ||
192*2393Syz155240 	    (*fp->fr_ifnames[3] && strcmp(fp->fr_ifnames[3], "*"))) {
193*2393Syz155240 		if (fp->fr_flags & FR_OUTQUE)
194*2393Syz155240 			printf("in-via ");
195*2393Syz155240 		else
196*2393Syz155240 			printf("out-via ");
1970Sstevel@tonic-gate 
198*2393Syz155240 		if (*fp->fr_ifnames[2]) {
199*2393Syz155240 			printifname("", fp->fr_ifnames[2],
200*2393Syz155240 				    fp->fr_ifas[2]);
201*2393Syz155240 			putchar(' ');
2020Sstevel@tonic-gate 
203*2393Syz155240 			if (*fp->fr_ifnames[3]) {
204*2393Syz155240 				printifname(",", fp->fr_ifnames[3],
205*2393Syz155240 					    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;
220*2393Syz155240 			p = getprotobynumber(pr);
221*2393Syz155240 			printf("proto ");
222*2393Syz155240 			printproto(p, pr, NULL);
223*2393Syz155240 			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 ? "!" : "");
231*2393Syz155240 		printaddr(fp->fr_v, fp->fr_satype, fp->fr_ifname,
232*2393Syz155240 			  &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 ? "!" : "");
237*2393Syz155240 		printaddr(fp->fr_v, fp->fr_datype, fp->fr_ifname,
238*2393Syz155240 			  &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) {
281*2393Syz155240 		fakebpf_t *fb;
2820Sstevel@tonic-gate 		int i;
2830Sstevel@tonic-gate 
284*2393Syz155240 		printf("bpf-v%d { \"", fp->fr_v);
285*2393Syz155240 		i = fp->fr_dsize / sizeof(*fb);
2860Sstevel@tonic-gate 
287*2393Syz155240 		for (fb = fp->fr_data, s = ""; i; i--, fb++, s = " ")
288*2393Syz155240 			printf("%s%#x %#x %#x %#x", s, fb->fb_c, fb->fb_t,
289*2393Syz155240 			       fb->fb_f, fb->fb_k);
2900Sstevel@tonic-gate 
291*2393Syz155240 		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 
300*2393Syz155240 	if ((type == FR_T_IPF) &&
301*2393Syz155240 	    ((fp->fr_flx & FI_WITH) || (fp->fr_mflx & FI_WITH) ||
302*2393Syz155240 	     fp->fr_optbits || fp->fr_optmask ||
303*2393Syz155240 	     fp->fr_secbits || fp->fr_secmask)) {
304*2393Syz155240 		char *comma = " ";
305*2393Syz155240 
306*2393Syz155240 		printf(" with");
307*2393Syz155240 		if (fp->fr_optbits || fp->fr_optmask ||
308*2393Syz155240 		    fp->fr_secbits || fp->fr_secmask) {
309*2393Syz155240 			sec[0] = fp->fr_secmask;
310*2393Syz155240 			sec[1] = fp->fr_secbits;
311*2393Syz155240 			if (fp->fr_v == 4)
312*2393Syz155240 				optprint(sec, fp->fr_optmask, fp->fr_optbits);
313*2393Syz155240 #ifdef	USE_INET6
314*2393Syz155240 			else
315*2393Syz155240 				optprintv6(sec, fp->fr_optmask,
316*2393Syz155240 					   fp->fr_optbits);
317*2393Syz155240 #endif
318*2393Syz155240 		} else if (fp->fr_mflx & FI_OPTIONS) {
319*2393Syz155240 			fputs(comma, stdout);
320*2393Syz155240 			if (!(fp->fr_flx & FI_OPTIONS))
321*2393Syz155240 				printf("not ");
322*2393Syz155240 			printf("ipopts");
323*2393Syz155240 			comma = ",";
324*2393Syz155240 		}
325*2393Syz155240 		if (fp->fr_mflx & FI_SHORT) {
326*2393Syz155240 			fputs(comma, stdout);
327*2393Syz155240 			if (!(fp->fr_flx & FI_SHORT))
328*2393Syz155240 				printf("not ");
329*2393Syz155240 			printf("short");
330*2393Syz155240 			comma = ",";
331*2393Syz155240 		}
332*2393Syz155240 		if (fp->fr_mflx & FI_FRAG) {
333*2393Syz155240 			fputs(comma, stdout);
334*2393Syz155240 			if (!(fp->fr_flx & FI_FRAG))
335*2393Syz155240 				printf("not ");
336*2393Syz155240 			printf("frag");
337*2393Syz155240 			comma = ",";
338*2393Syz155240 		}
339*2393Syz155240 		if (fp->fr_mflx & FI_FRAGBODY) {
340*2393Syz155240 			fputs(comma, stdout);
341*2393Syz155240 			if (!(fp->fr_flx & FI_FRAGBODY))
342*2393Syz155240 				printf("not ");
343*2393Syz155240 			printf("frag-body");
344*2393Syz155240 			comma = ",";
345*2393Syz155240 		}
346*2393Syz155240 		if (fp->fr_mflx & FI_NATED) {
347*2393Syz155240 			fputs(comma, stdout);
348*2393Syz155240 			if (!(fp->fr_flx & FI_NATED))
349*2393Syz155240 				printf("not ");
350*2393Syz155240 			printf("nat");
351*2393Syz155240 			comma = ",";
352*2393Syz155240 		}
353*2393Syz155240 		if (fp->fr_mflx & FI_LOWTTL) {
354*2393Syz155240 			fputs(comma, stdout);
355*2393Syz155240 			if (!(fp->fr_flx & FI_LOWTTL))
356*2393Syz155240 				printf("not ");
357*2393Syz155240 			printf("lowttl");
358*2393Syz155240 			comma = ",";
359*2393Syz155240 		}
360*2393Syz155240 		if (fp->fr_mflx & FI_BAD) {
361*2393Syz155240 			fputs(comma, stdout);
362*2393Syz155240 			if (!(fp->fr_flx & FI_BAD))
363*2393Syz155240 				printf("not ");
364*2393Syz155240 			printf("bad");
365*2393Syz155240 			comma = ",";
366*2393Syz155240 		}
367*2393Syz155240 		if (fp->fr_mflx & FI_BADSRC) {
368*2393Syz155240 			fputs(comma, stdout);
369*2393Syz155240 			if (!(fp->fr_flx & FI_BADSRC))
370*2393Syz155240 				printf("not ");
371*2393Syz155240 			printf("bad-src");
372*2393Syz155240 			comma = ",";
373*2393Syz155240 		}
374*2393Syz155240 		if (fp->fr_mflx & FI_BADNAT) {
375*2393Syz155240 			fputs(comma, stdout);
376*2393Syz155240 			if (!(fp->fr_flx & FI_BADNAT))
377*2393Syz155240 				printf("not ");
378*2393Syz155240 			printf("bad-nat");
379*2393Syz155240 			comma = ",";
380*2393Syz155240 		}
381*2393Syz155240 		if (fp->fr_mflx & FI_OOW) {
382*2393Syz155240 			fputs(comma, stdout);
383*2393Syz155240 			if (!(fp->fr_flx & FI_OOW))
384*2393Syz155240 				printf("not ");
385*2393Syz155240 			printf("oow");
386*2393Syz155240 		}
387*2393Syz155240 		if (fp->fr_mflx & FI_MULTICAST) {
388*2393Syz155240 			fputs(comma, stdout);
389*2393Syz155240 			if (!(fp->fr_flx & FI_MULTICAST))
390*2393Syz155240 				printf("not ");
391*2393Syz155240 			printf("multicast");
392*2393Syz155240 			comma = ",";
393*2393Syz155240 		}
394*2393Syz155240 		if (fp->fr_mflx & FI_BROADCAST) {
395*2393Syz155240 			fputs(comma, stdout);
396*2393Syz155240 			if (!(fp->fr_flx & FI_BROADCAST))
397*2393Syz155240 				printf("not ");
398*2393Syz155240 			printf("bcast");
399*2393Syz155240 			comma = ",";
400*2393Syz155240 		}
401*2393Syz155240 		if (fp->fr_mflx & FI_MBCAST) {
402*2393Syz155240 			fputs(comma, stdout);
403*2393Syz155240 			if (!(fp->fr_flx & FI_MBCAST))
404*2393Syz155240 				printf("not ");
405*2393Syz155240 			printf("mbcast");
406*2393Syz155240 			comma = ",";
407*2393Syz155240 		}
408*2393Syz155240 		if (fp->fr_mflx & FI_STATE) {
409*2393Syz155240 			fputs(comma, stdout);
410*2393Syz155240 			if (!(fp->fr_flx & FI_STATE))
411*2393Syz155240 				printf("not ");
412*2393Syz155240 			printf("state");
413*2393Syz155240 			comma = ",";
414*2393Syz155240 		}
415*2393Syz155240 	}
416*2393Syz155240 
4170Sstevel@tonic-gate 	if (fp->fr_flags & FR_KEEPSTATE) {
4180Sstevel@tonic-gate 		printf(" keep state");
419*2393Syz155240 		if ((fp->fr_flags & (FR_STSTRICT|FR_NEWISN|FR_NOICMPERR|FR_STATESYNC)) ||
4200Sstevel@tonic-gate 		    (fp->fr_statemax != 0) || (fp->fr_age[0] != 0)) {
421*2393Syz155240 			char *comma = "";
4220Sstevel@tonic-gate 			printf(" (");
423*2393Syz155240 			if (fp->fr_statemax != 0) {
424*2393Syz155240 				printf("limit %u", fp->fr_statemax);
425*2393Syz155240 				comma = ",";
426*2393Syz155240 			}
427*2393Syz155240 			if (fp->fr_flags & FR_STSTRICT) {
428*2393Syz155240 				printf("%sstrict", comma);
429*2393Syz155240 				comma = ",";
430*2393Syz155240 			}
431*2393Syz155240 			if (fp->fr_flags & FR_NEWISN) {
432*2393Syz155240 				printf("%snewisn", comma);
433*2393Syz155240 				comma = ",";
434*2393Syz155240 			}
435*2393Syz155240 			if (fp->fr_flags & FR_NOICMPERR) {
436*2393Syz155240 				printf("%sno-icmp-err", comma);
437*2393Syz155240 				comma = ",";
438*2393Syz155240 			}
439*2393Syz155240 			if (fp->fr_flags & FR_STATESYNC) {
440*2393Syz155240 				printf("%ssync", comma);
441*2393Syz155240 				comma = ",";
442*2393Syz155240 			}
4430Sstevel@tonic-gate 			if (fp->fr_age[0] || fp->fr_age[1])
444*2393Syz155240 				printf("%sage %d/%d", comma, fp->fr_age[0],
4450Sstevel@tonic-gate 				       fp->fr_age[1]);
446*2393Syz155240 			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);
469*2393Syz155240 	if (fp->fr_logtag != FR_NOLOGTAG || *fp->fr_nattag.ipt_tag) {
470*2393Syz155240 		char *s = "";
471*2393Syz155240 
472*2393Syz155240 		printf(" set-tag(");
473*2393Syz155240 		if (fp->fr_logtag != FR_NOLOGTAG) {
474*2393Syz155240 			printf("log=%u", fp->fr_logtag);
475*2393Syz155240 			s = ", ";
476*2393Syz155240 		}
477*2393Syz155240 		if (*fp->fr_nattag.ipt_tag) {
478*2393Syz155240 			printf("%snat=%-.*s", s, IPFTAG_LEN,
479*2393Syz155240 				fp->fr_nattag.ipt_tag);
480*2393Syz155240 		}
481*2393Syz155240 		printf(")");
482*2393Syz155240 	}
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