1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * Copyright (C) 1993-2001 by Darren Reed.
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * See the IPFILTER.LICENCE file for details on licencing.
5*0Sstevel@tonic-gate  *
6*0Sstevel@tonic-gate  * $Id: printfr.c,v 1.37 2003/06/03 16:01:12 darrenr Exp $
7*0Sstevel@tonic-gate  *
8*0Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
9*0Sstevel@tonic-gate  * Use is subject to license terms.
10*0Sstevel@tonic-gate  */
11*0Sstevel@tonic-gate 
12*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
13*0Sstevel@tonic-gate 
14*0Sstevel@tonic-gate #include "ipf.h"
15*0Sstevel@tonic-gate 
16*0Sstevel@tonic-gate 
17*0Sstevel@tonic-gate void printlookup(addr, mask)
18*0Sstevel@tonic-gate i6addr_t *addr, *mask;
19*0Sstevel@tonic-gate {
20*0Sstevel@tonic-gate 	switch (addr->iplookuptype)
21*0Sstevel@tonic-gate 	{
22*0Sstevel@tonic-gate 	case IPLT_POOL :
23*0Sstevel@tonic-gate 		printf("pool/");
24*0Sstevel@tonic-gate 		break;
25*0Sstevel@tonic-gate 	case IPLT_HASH :
26*0Sstevel@tonic-gate 		printf("hash/");
27*0Sstevel@tonic-gate 		break;
28*0Sstevel@tonic-gate 	default :
29*0Sstevel@tonic-gate 		printf("lookup(%x)=", addr->iplookuptype);
30*0Sstevel@tonic-gate 		break;
31*0Sstevel@tonic-gate 	}
32*0Sstevel@tonic-gate 
33*0Sstevel@tonic-gate 	printf("%u", addr->iplookupnum);
34*0Sstevel@tonic-gate 	if (opts & OPT_UNDEF) {
35*0Sstevel@tonic-gate 		if (mask->iplookupptr == NULL) {
36*0Sstevel@tonic-gate 			printf("(!)");
37*0Sstevel@tonic-gate 		}
38*0Sstevel@tonic-gate 	}
39*0Sstevel@tonic-gate }
40*0Sstevel@tonic-gate 
41*0Sstevel@tonic-gate 
42*0Sstevel@tonic-gate /*
43*0Sstevel@tonic-gate  * print the filter structure in a useful way
44*0Sstevel@tonic-gate  */
45*0Sstevel@tonic-gate void	printfr(fp, iocfunc)
46*0Sstevel@tonic-gate struct	frentry	*fp;
47*0Sstevel@tonic-gate ioctlfunc_t	iocfunc;
48*0Sstevel@tonic-gate {
49*0Sstevel@tonic-gate 	struct protoent	*p;
50*0Sstevel@tonic-gate 	u_short	sec[2];
51*0Sstevel@tonic-gate 	u_32_t type;
52*0Sstevel@tonic-gate 	u_char *t;
53*0Sstevel@tonic-gate 	char *s;
54*0Sstevel@tonic-gate 	int pr;
55*0Sstevel@tonic-gate 
56*0Sstevel@tonic-gate 	pr = -2;
57*0Sstevel@tonic-gate 	type = fp->fr_type & ~FR_T_BUILTIN;
58*0Sstevel@tonic-gate 
59*0Sstevel@tonic-gate 	if ((fp->fr_type & FR_T_BUILTIN) != 0)
60*0Sstevel@tonic-gate 		printf("# Builtin: ");
61*0Sstevel@tonic-gate 
62*0Sstevel@tonic-gate 	if (fp->fr_type == FR_T_CALLFUNC) {
63*0Sstevel@tonic-gate 		;
64*0Sstevel@tonic-gate 	} else if (fp->fr_func != NULL) {
65*0Sstevel@tonic-gate 		printf("call");
66*0Sstevel@tonic-gate 		if ((fp->fr_flags & FR_CALLNOW) != 0)
67*0Sstevel@tonic-gate 			printf(" now");
68*0Sstevel@tonic-gate 		s = kvatoname(fp->fr_func, iocfunc);
69*0Sstevel@tonic-gate 		printf(" %s/%u", s ? s : "?", fp->fr_arg);
70*0Sstevel@tonic-gate 	} else if (FR_ISPASS(fp->fr_flags))
71*0Sstevel@tonic-gate 		printf("pass");
72*0Sstevel@tonic-gate 	else if (FR_ISBLOCK(fp->fr_flags)) {
73*0Sstevel@tonic-gate 		printf("block");
74*0Sstevel@tonic-gate 		if (fp->fr_flags & FR_RETICMP) {
75*0Sstevel@tonic-gate 			if ((fp->fr_flags & FR_RETMASK) == FR_FAKEICMP)
76*0Sstevel@tonic-gate 				printf(" return-icmp-as-dest");
77*0Sstevel@tonic-gate 			else if ((fp->fr_flags & FR_RETMASK) == FR_RETICMP)
78*0Sstevel@tonic-gate 				printf(" return-icmp");
79*0Sstevel@tonic-gate 			if (fp->fr_icode) {
80*0Sstevel@tonic-gate 				if (fp->fr_icode <= MAX_ICMPCODE)
81*0Sstevel@tonic-gate 					printf("(%s)",
82*0Sstevel@tonic-gate 						icmpcodes[(int)fp->fr_icode]);
83*0Sstevel@tonic-gate 				else
84*0Sstevel@tonic-gate 					printf("(%d)", fp->fr_icode);
85*0Sstevel@tonic-gate 			}
86*0Sstevel@tonic-gate 		} else if ((fp->fr_flags & FR_RETMASK) == FR_RETRST)
87*0Sstevel@tonic-gate 			printf(" return-rst");
88*0Sstevel@tonic-gate 	} else if ((fp->fr_flags & FR_LOGMASK) == FR_LOG) {
89*0Sstevel@tonic-gate 		printlog(fp);
90*0Sstevel@tonic-gate 	} else if (FR_ISACCOUNT(fp->fr_flags))
91*0Sstevel@tonic-gate 		printf("count");
92*0Sstevel@tonic-gate 	else if (FR_ISAUTH(fp->fr_flags))
93*0Sstevel@tonic-gate 		printf("auth");
94*0Sstevel@tonic-gate 	else if (FR_ISPREAUTH(fp->fr_flags))
95*0Sstevel@tonic-gate 		printf("preauth");
96*0Sstevel@tonic-gate 	else if (FR_ISNOMATCH(fp->fr_flags))
97*0Sstevel@tonic-gate 		printf("nomatch");
98*0Sstevel@tonic-gate 	else if (FR_ISSKIP(fp->fr_flags))
99*0Sstevel@tonic-gate 		printf("skip %u", fp->fr_arg);
100*0Sstevel@tonic-gate 	else {
101*0Sstevel@tonic-gate 		printf("%x", fp->fr_flags);
102*0Sstevel@tonic-gate 	}
103*0Sstevel@tonic-gate 
104*0Sstevel@tonic-gate 	if (fp->fr_flags & FR_OUTQUE)
105*0Sstevel@tonic-gate 		printf(" out ");
106*0Sstevel@tonic-gate 	else
107*0Sstevel@tonic-gate 		printf(" in ");
108*0Sstevel@tonic-gate 
109*0Sstevel@tonic-gate 	if (((fp->fr_flags & FR_LOGB) == FR_LOGB) ||
110*0Sstevel@tonic-gate 	    ((fp->fr_flags & FR_LOGP) == FR_LOGP)) {
111*0Sstevel@tonic-gate 		printlog(fp);
112*0Sstevel@tonic-gate 		putchar(' ');
113*0Sstevel@tonic-gate 	}
114*0Sstevel@tonic-gate 
115*0Sstevel@tonic-gate 	if (fp->fr_flags & FR_QUICK)
116*0Sstevel@tonic-gate 		printf("quick ");
117*0Sstevel@tonic-gate 
118*0Sstevel@tonic-gate 	if (*fp->fr_ifname) {
119*0Sstevel@tonic-gate 		printifname("on ", fp->fr_ifname, fp->fr_ifa);
120*0Sstevel@tonic-gate 		if (*fp->fr_ifnames[1] && strcmp(fp->fr_ifnames[1], "*"))
121*0Sstevel@tonic-gate 			printifname(",", fp->fr_ifnames[1], fp->fr_ifas[1]);
122*0Sstevel@tonic-gate 		putchar(' ');
123*0Sstevel@tonic-gate 
124*0Sstevel@tonic-gate 		if (*fp->fr_dif.fd_ifname)
125*0Sstevel@tonic-gate 			print_toif("dup-to", &fp->fr_dif);
126*0Sstevel@tonic-gate 		if (*fp->fr_tif.fd_ifname)
127*0Sstevel@tonic-gate 			print_toif("to", &fp->fr_tif);
128*0Sstevel@tonic-gate 		if (fp->fr_flags & FR_FASTROUTE)
129*0Sstevel@tonic-gate 			printf("fastroute ");
130*0Sstevel@tonic-gate 
131*0Sstevel@tonic-gate 		if ((*fp->fr_ifnames[2] && strcmp(fp->fr_ifnames[2], "*")) ||
132*0Sstevel@tonic-gate 		    (*fp->fr_ifnames[3] && strcmp(fp->fr_ifnames[3], "*"))) {
133*0Sstevel@tonic-gate 			if (fp->fr_flags & FR_OUTQUE)
134*0Sstevel@tonic-gate 				printf("in-via ");
135*0Sstevel@tonic-gate 			else
136*0Sstevel@tonic-gate 				printf("out-via ");
137*0Sstevel@tonic-gate 
138*0Sstevel@tonic-gate 			if (*fp->fr_ifnames[2]) {
139*0Sstevel@tonic-gate 				printifname("", fp->fr_ifnames[2],
140*0Sstevel@tonic-gate 					    fp->fr_ifas[2]);
141*0Sstevel@tonic-gate 				putchar(' ');
142*0Sstevel@tonic-gate 
143*0Sstevel@tonic-gate 				if (*fp->fr_ifnames[3]) {
144*0Sstevel@tonic-gate 					printifname(",", fp->fr_ifnames[3],
145*0Sstevel@tonic-gate 						    fp->fr_ifas[3]);
146*0Sstevel@tonic-gate 				}
147*0Sstevel@tonic-gate 			}
148*0Sstevel@tonic-gate 		}
149*0Sstevel@tonic-gate 	}
150*0Sstevel@tonic-gate 
151*0Sstevel@tonic-gate 	if (type == FR_T_IPF) {
152*0Sstevel@tonic-gate 		if (fp->fr_mip.fi_tos)
153*0Sstevel@tonic-gate 			printf("tos %#x ", fp->fr_tos);
154*0Sstevel@tonic-gate 		if (fp->fr_mip.fi_ttl)
155*0Sstevel@tonic-gate 			printf("ttl %d ", fp->fr_ttl);
156*0Sstevel@tonic-gate 		if (fp->fr_flx & FI_TCPUDP) {
157*0Sstevel@tonic-gate 			printf("proto tcp/udp ");
158*0Sstevel@tonic-gate 			pr = -1;
159*0Sstevel@tonic-gate 		} else if (fp->fr_mip.fi_p) {
160*0Sstevel@tonic-gate 			pr = fp->fr_ip.fi_p;
161*0Sstevel@tonic-gate 			if ((p = getprotobynumber(fp->fr_proto)))
162*0Sstevel@tonic-gate 				printf("proto %s ", p->p_name);
163*0Sstevel@tonic-gate 			else
164*0Sstevel@tonic-gate 				printf("proto %d ", fp->fr_proto);
165*0Sstevel@tonic-gate 		}
166*0Sstevel@tonic-gate 	}
167*0Sstevel@tonic-gate 
168*0Sstevel@tonic-gate 	if (type == FR_T_NONE) {
169*0Sstevel@tonic-gate 		printf("all");
170*0Sstevel@tonic-gate 	} else if (type == FR_T_IPF) {
171*0Sstevel@tonic-gate 		printf("from %s", fp->fr_flags & FR_NOTSRCIP ? "!" : "");
172*0Sstevel@tonic-gate 		if (fp->fr_satype != FRI_NORMAL) {
173*0Sstevel@tonic-gate 			printf("%s", fp->fr_ifname);
174*0Sstevel@tonic-gate 			if (fp->fr_satype == FRI_BROADCAST)
175*0Sstevel@tonic-gate 				printf("/bcast");
176*0Sstevel@tonic-gate 			else if (fp->fr_satype == FRI_NETWORK)
177*0Sstevel@tonic-gate 				printf("/net");
178*0Sstevel@tonic-gate 			else if (fp->fr_satype == FRI_NETMASKED)
179*0Sstevel@tonic-gate 				printf("/netmasked");
180*0Sstevel@tonic-gate 			else if (fp->fr_satype == FRI_PEERADDR)
181*0Sstevel@tonic-gate 				printf("/peer");
182*0Sstevel@tonic-gate 			else if (fp->fr_satype == FRI_LOOKUP)
183*0Sstevel@tonic-gate 				printlookup(&fp->fr_ip.fi_src,
184*0Sstevel@tonic-gate 					    &fp->fr_mip.fi_src);
185*0Sstevel@tonic-gate 			else
186*0Sstevel@tonic-gate 				printmask((u_32_t *)&fp->fr_smsk.s_addr);
187*0Sstevel@tonic-gate 		} else
188*0Sstevel@tonic-gate 			printhostmask(fp->fr_v, (u_32_t *)&fp->fr_src.s_addr,
189*0Sstevel@tonic-gate 				      (u_32_t *)&fp->fr_smsk.s_addr);
190*0Sstevel@tonic-gate 		if (fp->fr_scmp)
191*0Sstevel@tonic-gate 			printportcmp(pr, &fp->fr_tuc.ftu_src);
192*0Sstevel@tonic-gate 
193*0Sstevel@tonic-gate 		printf(" to %s", fp->fr_flags & FR_NOTDSTIP ? "!" : "");
194*0Sstevel@tonic-gate 		if (fp->fr_datype != FRI_NORMAL) {
195*0Sstevel@tonic-gate 			printf("%s", fp->fr_ifname);
196*0Sstevel@tonic-gate 			if (fp->fr_datype == FRI_BROADCAST)
197*0Sstevel@tonic-gate 				printf("/bcast");
198*0Sstevel@tonic-gate 			else if (fp->fr_datype == FRI_NETWORK)
199*0Sstevel@tonic-gate 				printf("/net");
200*0Sstevel@tonic-gate 			else if (fp->fr_datype == FRI_NETMASKED)
201*0Sstevel@tonic-gate 				printf("/netmasked");
202*0Sstevel@tonic-gate 			else if (fp->fr_datype == FRI_PEERADDR)
203*0Sstevel@tonic-gate 				printf("/peer");
204*0Sstevel@tonic-gate 			else if (fp->fr_datype == FRI_LOOKUP)
205*0Sstevel@tonic-gate 				printlookup(&fp->fr_ip.fi_dst,
206*0Sstevel@tonic-gate 					    &fp->fr_mip.fi_dst);
207*0Sstevel@tonic-gate 			else
208*0Sstevel@tonic-gate 				printmask((u_32_t *)&fp->fr_dmsk.s_addr);
209*0Sstevel@tonic-gate 		} else
210*0Sstevel@tonic-gate 			printhostmask(fp->fr_v, (u_32_t *)&fp->fr_dst.s_addr,
211*0Sstevel@tonic-gate 				      (u_32_t *)&fp->fr_dmsk.s_addr);
212*0Sstevel@tonic-gate 		if (fp->fr_dcmp)
213*0Sstevel@tonic-gate 			printportcmp(pr, &fp->fr_tuc.ftu_dst);
214*0Sstevel@tonic-gate 
215*0Sstevel@tonic-gate 		if ((fp->fr_flx & FI_WITH) || (fp->fr_mflx & FI_WITH) ||
216*0Sstevel@tonic-gate 		    fp->fr_optbits || fp->fr_optmask ||
217*0Sstevel@tonic-gate 		    fp->fr_secbits || fp->fr_secmask) {
218*0Sstevel@tonic-gate 			printf(" with");
219*0Sstevel@tonic-gate 			if (fp->fr_optbits || fp->fr_optmask ||
220*0Sstevel@tonic-gate 			    fp->fr_secbits || fp->fr_secmask) {
221*0Sstevel@tonic-gate 				sec[0] = fp->fr_secmask;
222*0Sstevel@tonic-gate 				sec[1] = fp->fr_secbits;
223*0Sstevel@tonic-gate 				if (fp->fr_v == 4)
224*0Sstevel@tonic-gate 					optprint(sec, fp->fr_optmask,
225*0Sstevel@tonic-gate 						 fp->fr_optbits);
226*0Sstevel@tonic-gate #ifdef	USE_INET6
227*0Sstevel@tonic-gate 				else
228*0Sstevel@tonic-gate 					optprintv6(sec, fp->fr_optmask,
229*0Sstevel@tonic-gate 						   fp->fr_optbits);
230*0Sstevel@tonic-gate #endif
231*0Sstevel@tonic-gate 			} else if (fp->fr_mflx & FI_OPTIONS) {
232*0Sstevel@tonic-gate 				if (!(fp->fr_flx & FI_OPTIONS))
233*0Sstevel@tonic-gate 					printf(" not");
234*0Sstevel@tonic-gate 				printf(" ipopts");
235*0Sstevel@tonic-gate 			}
236*0Sstevel@tonic-gate 			if (fp->fr_mflx & FI_SHORT) {
237*0Sstevel@tonic-gate 				if (!(fp->fr_flx & FI_SHORT))
238*0Sstevel@tonic-gate 					printf(" not");
239*0Sstevel@tonic-gate 				printf(" short");
240*0Sstevel@tonic-gate 			}
241*0Sstevel@tonic-gate 			if (fp->fr_mflx & FI_FRAG) {
242*0Sstevel@tonic-gate 				if (!(fp->fr_flx & FI_FRAG))
243*0Sstevel@tonic-gate 					printf(" not");
244*0Sstevel@tonic-gate 				printf(" frag");
245*0Sstevel@tonic-gate 			}
246*0Sstevel@tonic-gate 			if (fp->fr_mflx & FI_NATED) {
247*0Sstevel@tonic-gate 				if (!(fp->fr_flx & FI_NATED))
248*0Sstevel@tonic-gate 					printf(" not");
249*0Sstevel@tonic-gate 				printf(" nat");
250*0Sstevel@tonic-gate 			}
251*0Sstevel@tonic-gate 			if (fp->fr_mflx & FI_LOWTTL) {
252*0Sstevel@tonic-gate 				if (!(fp->fr_flx & FI_LOWTTL))
253*0Sstevel@tonic-gate 					printf(" not");
254*0Sstevel@tonic-gate 				printf(" lowttl");
255*0Sstevel@tonic-gate 			}
256*0Sstevel@tonic-gate 			if (fp->fr_mflx & FI_BADSRC) {
257*0Sstevel@tonic-gate 				if (!(fp->fr_flx & FI_BADSRC))
258*0Sstevel@tonic-gate 					printf(" not");
259*0Sstevel@tonic-gate 				printf(" bad-src");
260*0Sstevel@tonic-gate 			}
261*0Sstevel@tonic-gate 		}
262*0Sstevel@tonic-gate 		if (fp->fr_proto == IPPROTO_ICMP && fp->fr_icmpm) {
263*0Sstevel@tonic-gate 			int	type = fp->fr_icmp, code;
264*0Sstevel@tonic-gate 
265*0Sstevel@tonic-gate 			type = ntohs(fp->fr_icmp);
266*0Sstevel@tonic-gate 			code = type & 0xff;
267*0Sstevel@tonic-gate 			type /= 256;
268*0Sstevel@tonic-gate 			if (type < (sizeof(icmptypes) / sizeof(char *) - 1) &&
269*0Sstevel@tonic-gate 			    icmptypes[type])
270*0Sstevel@tonic-gate 				printf(" icmp-type %s", icmptypes[type]);
271*0Sstevel@tonic-gate 			else
272*0Sstevel@tonic-gate 				printf(" icmp-type %d", type);
273*0Sstevel@tonic-gate 			if (ntohs(fp->fr_icmpm) & 0xff)
274*0Sstevel@tonic-gate 				printf(" code %d", code);
275*0Sstevel@tonic-gate 		}
276*0Sstevel@tonic-gate 		if ((fp->fr_proto == IPPROTO_TCP) &&
277*0Sstevel@tonic-gate 		    (fp->fr_tcpf || fp->fr_tcpfm)) {
278*0Sstevel@tonic-gate 			printf(" flags ");
279*0Sstevel@tonic-gate 			if (fp->fr_tcpf & ~TCPF_ALL)
280*0Sstevel@tonic-gate 				printf("0x%x", fp->fr_tcpf);
281*0Sstevel@tonic-gate 			else
282*0Sstevel@tonic-gate 				for (s = flagset, t = flags; *s; s++, t++)
283*0Sstevel@tonic-gate 					if (fp->fr_tcpf & *t)
284*0Sstevel@tonic-gate 						(void)putchar(*s);
285*0Sstevel@tonic-gate 			if (fp->fr_tcpfm) {
286*0Sstevel@tonic-gate 				(void)putchar('/');
287*0Sstevel@tonic-gate 				if (fp->fr_tcpfm & ~TCPF_ALL)
288*0Sstevel@tonic-gate 					printf("0x%x", fp->fr_tcpfm);
289*0Sstevel@tonic-gate 				else
290*0Sstevel@tonic-gate 					for (s = flagset, t = flags; *s;
291*0Sstevel@tonic-gate 					     s++, t++)
292*0Sstevel@tonic-gate 						if (fp->fr_tcpfm & *t)
293*0Sstevel@tonic-gate 							(void)putchar(*s);
294*0Sstevel@tonic-gate 			}
295*0Sstevel@tonic-gate 		}
296*0Sstevel@tonic-gate #ifdef IPFILTER_BPF
297*0Sstevel@tonic-gate 	} else if (type == FR_T_BPFOPC) {
298*0Sstevel@tonic-gate 		u_32_t *bp;
299*0Sstevel@tonic-gate 		int i;
300*0Sstevel@tonic-gate 
301*0Sstevel@tonic-gate 		printf("{");
302*0Sstevel@tonic-gate 		i = fp->fr_dsize / sizeof(*bp);
303*0Sstevel@tonic-gate 
304*0Sstevel@tonic-gate 		for (bp = fp->fr_data; i; i--, bp++)
305*0Sstevel@tonic-gate 			printf(" 0x%08x", *bp);
306*0Sstevel@tonic-gate 
307*0Sstevel@tonic-gate 		printf(" }");
308*0Sstevel@tonic-gate #endif
309*0Sstevel@tonic-gate 	} else if (type == FR_T_COMPIPF) {
310*0Sstevel@tonic-gate 		;
311*0Sstevel@tonic-gate 	} else if (type == FR_T_CALLFUNC) {
312*0Sstevel@tonic-gate 		printf("call function at %p", fp->fr_data);
313*0Sstevel@tonic-gate 	} else {
314*0Sstevel@tonic-gate 		printf("[unknown filter type %#x]", fp->fr_type);
315*0Sstevel@tonic-gate 	}
316*0Sstevel@tonic-gate 
317*0Sstevel@tonic-gate 	if (fp->fr_flags & FR_KEEPSTATE) {
318*0Sstevel@tonic-gate 		printf(" keep state");
319*0Sstevel@tonic-gate 		if ((fp->fr_flags & (FR_STSTRICT|FR_NEWISN)) ||
320*0Sstevel@tonic-gate 		    (fp->fr_statemax != 0) || (fp->fr_age[0] != 0)) {
321*0Sstevel@tonic-gate 			printf(" (");
322*0Sstevel@tonic-gate 			if (fp->fr_statemax != 0)
323*0Sstevel@tonic-gate 				printf(" limit %u", fp->fr_statemax);
324*0Sstevel@tonic-gate 			if (fp->fr_flags & FR_FRSTRICT)
325*0Sstevel@tonic-gate 				printf(" strict");
326*0Sstevel@tonic-gate 			if (fp->fr_flags & FR_NEWISN)
327*0Sstevel@tonic-gate 				printf(" newisn");
328*0Sstevel@tonic-gate 			if (fp->fr_age[0] || fp->fr_age[1])
329*0Sstevel@tonic-gate 				printf(" age %d/%d", fp->fr_age[0],
330*0Sstevel@tonic-gate 				       fp->fr_age[1]);
331*0Sstevel@tonic-gate 			printf(" )");
332*0Sstevel@tonic-gate 		}
333*0Sstevel@tonic-gate 	}
334*0Sstevel@tonic-gate 	if (fp->fr_flags & FR_KEEPFRAG) {
335*0Sstevel@tonic-gate 		printf(" keep frags");
336*0Sstevel@tonic-gate 		if (fp->fr_flags & (FR_FRSTRICT)) {
337*0Sstevel@tonic-gate 			printf(" (");
338*0Sstevel@tonic-gate 			if (fp->fr_flags & FR_FRSTRICT)
339*0Sstevel@tonic-gate 				printf(" strict");
340*0Sstevel@tonic-gate 			printf(" )");
341*0Sstevel@tonic-gate 
342*0Sstevel@tonic-gate 		}
343*0Sstevel@tonic-gate 	}
344*0Sstevel@tonic-gate 	if (fp->fr_isc != (struct ipscan *)-1) {
345*0Sstevel@tonic-gate 		if (fp->fr_isctag[0])
346*0Sstevel@tonic-gate 			printf(" scan %s", fp->fr_isctag);
347*0Sstevel@tonic-gate 		else
348*0Sstevel@tonic-gate 			printf(" scan *");
349*0Sstevel@tonic-gate 	}
350*0Sstevel@tonic-gate 	if (*fp->fr_grhead != '\0')
351*0Sstevel@tonic-gate 		printf(" head %s", fp->fr_grhead);
352*0Sstevel@tonic-gate 	if (*fp->fr_group != '\0')
353*0Sstevel@tonic-gate 		printf(" group %s", fp->fr_group);
354*0Sstevel@tonic-gate 	if (fp->fr_logtag != FR_NOLOGTAG)
355*0Sstevel@tonic-gate 		printf(" log-tag %u", fp->fr_logtag);
356*0Sstevel@tonic-gate 	if (fp->fr_pps)
357*0Sstevel@tonic-gate 		printf(" pps %d", fp->fr_pps);
358*0Sstevel@tonic-gate 	(void)putchar('\n');
359*0Sstevel@tonic-gate }
360