printfr.c revision 288683
1/*	$FreeBSD: head/contrib/ipfilter/lib/printfr.c 255332 2013-09-06 23:11:19Z cy $	*/
2
3/*
4 * Copyright (C) 2012 by Darren Reed.
5 *
6 * See the IPFILTER.LICENCE file for details on licencing.
7 *
8 * $Id$
9 */
10
11#include "ipf.h"
12
13
14/*
15 * print the filter structure in a useful way
16 */
17void
18printfr(fp, iocfunc)
19	struct	frentry	*fp;
20	ioctlfunc_t	iocfunc;
21{
22	struct protoent	*p;
23	u_short	sec[2];
24	u_32_t type;
25	int pr, af;
26	char *s;
27	int hash;
28
29	pr = -2;
30	type = fp->fr_type & ~FR_T_BUILTIN;
31
32	if ((fp->fr_type & FR_T_BUILTIN) != 0)
33		PRINTF("# Builtin: ");
34
35	if (fp->fr_collect != 0)
36		PRINTF("%u ", fp->fr_collect);
37
38	if (fp->fr_type == FR_T_CALLFUNC) {
39		;
40	} else if (fp->fr_func != NULL) {
41		PRINTF("call");
42		if ((fp->fr_flags & FR_CALLNOW) != 0)
43			PRINTF(" now");
44		s = kvatoname(fp->fr_func, iocfunc);
45		PRINTF(" %s/%u", s ? s : "?", fp->fr_arg);
46	} else if (FR_ISPASS(fp->fr_flags))
47		PRINTF("pass");
48	else if (FR_ISBLOCK(fp->fr_flags)) {
49		PRINTF("block");
50	} else if ((fp->fr_flags & FR_LOGMASK) == FR_LOG) {
51		printlog(fp);
52	} else if (FR_ISACCOUNT(fp->fr_flags))
53		PRINTF("count");
54	else if (FR_ISAUTH(fp->fr_flags))
55		PRINTF("auth");
56	else if (FR_ISPREAUTH(fp->fr_flags))
57		PRINTF("preauth");
58	else if (FR_ISNOMATCH(fp->fr_flags))
59		PRINTF("nomatch");
60	else if (FR_ISDECAPS(fp->fr_flags))
61		PRINTF("decapsulate");
62	else if (FR_ISSKIP(fp->fr_flags))
63		PRINTF("skip %u", fp->fr_arg);
64	else {
65		PRINTF("%x", fp->fr_flags);
66	}
67	if (fp->fr_flags & FR_RETICMP) {
68		if ((fp->fr_flags & FR_RETMASK) == FR_FAKEICMP)
69			PRINTF(" return-icmp-as-dest");
70		else if ((fp->fr_flags & FR_RETMASK) == FR_RETICMP)
71			PRINTF(" return-icmp");
72		if (fp->fr_icode) {
73			if (fp->fr_icode <= MAX_ICMPCODE)
74				PRINTF("(%s)",
75					icmpcodes[(int)fp->fr_icode]);
76			else
77				PRINTF("(%d)", fp->fr_icode);
78		}
79	} else if ((fp->fr_flags & FR_RETMASK) == FR_RETRST)
80		PRINTF(" return-rst");
81
82	if (fp->fr_flags & FR_OUTQUE)
83		PRINTF(" out ");
84	else if (fp->fr_flags & FR_INQUE)
85		PRINTF(" in ");
86
87	if (((fp->fr_flags & FR_LOGB) == FR_LOGB) ||
88	    ((fp->fr_flags & FR_LOGP) == FR_LOGP)) {
89		printlog(fp);
90		putchar(' ');
91	}
92
93	if (fp->fr_flags & FR_QUICK)
94		PRINTF("quick ");
95
96	if (fp->fr_ifnames[0] != -1) {
97		printifname("on ", fp->fr_names + fp->fr_ifnames[0],
98			    fp->fr_ifa);
99		if (fp->fr_ifnames[1] != -1 &&
100		    strcmp(fp->fr_names + fp->fr_ifnames[1], "*"))
101			printifname(",", fp->fr_names + fp->fr_ifnames[1],
102				    fp->fr_ifas[1]);
103		putchar(' ');
104	}
105
106	if (fp->fr_tif.fd_name != -1)
107		print_toif(fp->fr_family, "to", fp->fr_names, &fp->fr_tif);
108	if (fp->fr_dif.fd_name != -1)
109		print_toif(fp->fr_family, "dup-to", fp->fr_names,
110			   &fp->fr_dif);
111	if (fp->fr_rif.fd_name != -1)
112		print_toif(fp->fr_family, "reply-to", fp->fr_names,
113			   &fp->fr_rif);
114	if (fp->fr_flags & FR_FASTROUTE)
115		PRINTF("fastroute ");
116
117	if ((fp->fr_ifnames[2] != -1 &&
118	     strcmp(fp->fr_names + fp->fr_ifnames[2], "*")) ||
119	    (fp->fr_ifnames[3] != -1 &&
120		 strcmp(fp->fr_names + fp->fr_ifnames[3], "*"))) {
121		if (fp->fr_flags & FR_OUTQUE)
122			PRINTF("in-via ");
123		else
124			PRINTF("out-via ");
125
126		if (fp->fr_ifnames[2] != -1) {
127			printifname("", fp->fr_names + fp->fr_ifnames[2],
128				    fp->fr_ifas[2]);
129			if (fp->fr_ifnames[3] != -1) {
130				printifname(",",
131					    fp->fr_names + fp->fr_ifnames[3],
132					    fp->fr_ifas[3]);
133			}
134			putchar(' ');
135		}
136	}
137
138	if (fp->fr_family == AF_INET) {
139		PRINTF("inet ");
140		af = AF_INET;
141#ifdef USE_INET6
142	} else if (fp->fr_family == AF_INET6) {
143		PRINTF("inet6 ");
144		af = AF_INET6;
145#endif
146	} else {
147		af = -1;
148	}
149
150	if (type == FR_T_IPF) {
151		if (fp->fr_mip.fi_tos)
152			PRINTF("tos %#x ", fp->fr_tos);
153		if (fp->fr_mip.fi_ttl)
154			PRINTF("ttl %d ", fp->fr_ttl);
155		if (fp->fr_flx & FI_TCPUDP) {
156			PRINTF("proto tcp/udp ");
157			pr = -1;
158		} else if (fp->fr_mip.fi_p) {
159			pr = fp->fr_ip.fi_p;
160			p = getprotobynumber(pr);
161			PRINTF("proto ");
162			printproto(p, pr, NULL);
163			putchar(' ');
164		}
165	}
166
167	switch (type)
168	{
169	case FR_T_NONE :
170		PRINTF("all");
171		break;
172
173	case FR_T_IPF :
174		PRINTF("from %s", fp->fr_flags & FR_NOTSRCIP ? "!" : "");
175		printaddr(af, fp->fr_satype, fp->fr_names, fp->fr_ifnames[0],
176			  &fp->fr_src.s_addr, &fp->fr_smsk.s_addr);
177		if (fp->fr_scmp)
178			printportcmp(pr, &fp->fr_tuc.ftu_src);
179
180		PRINTF(" to %s", fp->fr_flags & FR_NOTDSTIP ? "!" : "");
181		printaddr(af, fp->fr_datype, fp->fr_names, fp->fr_ifnames[0],
182			  &fp->fr_dst.s_addr, &fp->fr_dmsk.s_addr);
183		if (fp->fr_dcmp)
184			printportcmp(pr, &fp->fr_tuc.ftu_dst);
185
186		if (((fp->fr_proto == IPPROTO_ICMP) ||
187		     (fp->fr_proto == IPPROTO_ICMPV6)) && fp->fr_icmpm) {
188			int	type = fp->fr_icmp, code;
189			char	*name;
190
191			type = ntohs(fp->fr_icmp);
192			code = type & 0xff;
193			type /= 256;
194			name = icmptypename(fp->fr_family, type);
195			if (name == NULL)
196				PRINTF(" icmp-type %d", type);
197			else
198				PRINTF(" icmp-type %s", name);
199			if (ntohs(fp->fr_icmpm) & 0xff)
200				PRINTF(" code %d", code);
201		}
202		if ((fp->fr_proto == IPPROTO_TCP) &&
203		    (fp->fr_tcpf || fp->fr_tcpfm)) {
204			PRINTF(" flags ");
205			printtcpflags(fp->fr_tcpf, fp->fr_tcpfm);
206		}
207		break;
208
209	case FR_T_BPFOPC :
210	    {
211		fakebpf_t *fb;
212		int i;
213
214		PRINTF("bpf-v%d { \"", fp->fr_family);
215		i = fp->fr_dsize / sizeof(*fb);
216
217		for (fb = fp->fr_data, s = ""; i; i--, fb++, s = " ")
218			PRINTF("%s%#x %#x %#x %#x", s, fb->fb_c, fb->fb_t,
219			       fb->fb_f, fb->fb_k);
220
221		PRINTF("\" }");
222		break;
223	    }
224
225	case FR_T_COMPIPF :
226		break;
227
228	case FR_T_CALLFUNC :
229		PRINTF("call function at %p", fp->fr_data);
230		break;
231
232	case FR_T_IPFEXPR :
233		PRINTF("exp { \"");
234		printipfexpr(fp->fr_data);
235		PRINTF("\" } ");
236		break;
237
238	default :
239		PRINTF("[unknown filter type %#x]", fp->fr_type);
240		break;
241	}
242
243	if ((type == FR_T_IPF) &&
244	    ((fp->fr_flx & FI_WITH) || (fp->fr_mflx & FI_WITH) ||
245	     fp->fr_optbits || fp->fr_optmask ||
246	     fp->fr_secbits || fp->fr_secmask)) {
247		char *comma = " ";
248
249		PRINTF(" with");
250		if (fp->fr_optbits || fp->fr_optmask ||
251		    fp->fr_secbits || fp->fr_secmask) {
252			sec[0] = fp->fr_secmask;
253			sec[1] = fp->fr_secbits;
254			if (fp->fr_family == AF_INET)
255				optprint(sec, fp->fr_optmask, fp->fr_optbits);
256#ifdef	USE_INET6
257			else
258				optprintv6(sec, fp->fr_optmask,
259					   fp->fr_optbits);
260#endif
261		} else if (fp->fr_mflx & FI_OPTIONS) {
262			fputs(comma, stdout);
263			if (!(fp->fr_flx & FI_OPTIONS))
264				PRINTF("not ");
265			PRINTF("ipopts");
266			comma = ",";
267		}
268		if (fp->fr_mflx & FI_SHORT) {
269			fputs(comma, stdout);
270			if (!(fp->fr_flx & FI_SHORT))
271				PRINTF("not ");
272			PRINTF("short");
273			comma = ",";
274		}
275		if (fp->fr_mflx & FI_FRAG) {
276			fputs(comma, stdout);
277			if (!(fp->fr_flx & FI_FRAG))
278				PRINTF("not ");
279			PRINTF("frag");
280			comma = ",";
281		}
282		if (fp->fr_mflx & FI_FRAGBODY) {
283			fputs(comma, stdout);
284			if (!(fp->fr_flx & FI_FRAGBODY))
285				PRINTF("not ");
286			PRINTF("frag-body");
287			comma = ",";
288		}
289		if (fp->fr_mflx & FI_NATED) {
290			fputs(comma, stdout);
291			if (!(fp->fr_flx & FI_NATED))
292				PRINTF("not ");
293			PRINTF("nat");
294			comma = ",";
295		}
296		if (fp->fr_mflx & FI_LOWTTL) {
297			fputs(comma, stdout);
298			if (!(fp->fr_flx & FI_LOWTTL))
299				PRINTF("not ");
300			PRINTF("lowttl");
301			comma = ",";
302		}
303		if (fp->fr_mflx & FI_BAD) {
304			fputs(comma, stdout);
305			if (!(fp->fr_flx & FI_BAD))
306				PRINTF("not ");
307			PRINTF("bad");
308			comma = ",";
309		}
310		if (fp->fr_mflx & FI_BADSRC) {
311			fputs(comma, stdout);
312			if (!(fp->fr_flx & FI_BADSRC))
313				PRINTF("not ");
314			PRINTF("bad-src");
315			comma = ",";
316		}
317		if (fp->fr_mflx & FI_BADNAT) {
318			fputs(comma, stdout);
319			if (!(fp->fr_flx & FI_BADNAT))
320				PRINTF("not ");
321			PRINTF("bad-nat");
322			comma = ",";
323		}
324		if (fp->fr_mflx & FI_OOW) {
325			fputs(comma, stdout);
326			if (!(fp->fr_flx & FI_OOW))
327				PRINTF("not ");
328			PRINTF("oow");
329			comma = ",";
330		}
331		if (fp->fr_mflx & FI_MBCAST) {
332			fputs(comma, stdout);
333			if (!(fp->fr_flx & FI_MBCAST))
334				PRINTF("not ");
335			PRINTF("mbcast");
336			comma = ",";
337		}
338		if (fp->fr_mflx & FI_BROADCAST) {
339			fputs(comma, stdout);
340			if (!(fp->fr_flx & FI_BROADCAST))
341				PRINTF("not ");
342			PRINTF("bcast");
343			comma = ",";
344		}
345		if (fp->fr_mflx & FI_MULTICAST) {
346			fputs(comma, stdout);
347			if (!(fp->fr_flx & FI_MULTICAST))
348				PRINTF("not ");
349			PRINTF("mcast");
350			comma = ",";
351		}
352		if (fp->fr_mflx & FI_STATE) {
353			fputs(comma, stdout);
354			if (!(fp->fr_flx & FI_STATE))
355				PRINTF("not ");
356			PRINTF("state");
357			comma = ",";
358		}
359		if (fp->fr_mflx & FI_V6EXTHDR) {
360			fputs(comma, stdout);
361			if (!(fp->fr_flx & FI_V6EXTHDR))
362				PRINTF("not ");
363			PRINTF("v6hdrs");
364			comma = ",";
365		}
366	}
367
368	if (fp->fr_flags & FR_KEEPSTATE) {
369		host_track_t *src = &fp->fr_srctrack;
370		PRINTF(" keep state");
371		if ((fp->fr_flags & (FR_STSTRICT|FR_NEWISN|
372				     FR_NOICMPERR|FR_STATESYNC)) ||
373		    (fp->fr_statemax != 0) || (fp->fr_age[0] != 0) ||
374		    (src->ht_max_nodes != 0)) {
375			char *comma = "";
376			PRINTF(" (");
377			if (fp->fr_statemax != 0) {
378				PRINTF("limit %u", fp->fr_statemax);
379				comma = ",";
380			}
381			if (src->ht_max_nodes != 0) {
382				PRINTF("%smax-nodes %d", comma,
383				       src->ht_max_nodes);
384				if (src->ht_max_per_node)
385					PRINTF(", max-per-src %d/%d",
386					       src->ht_max_per_node,
387					       src->ht_netmask);
388				comma = ",";
389			}
390			if (fp->fr_flags & FR_STSTRICT) {
391				PRINTF("%sstrict", comma);
392				comma = ",";
393			}
394			if (fp->fr_flags & FR_STLOOSE) {
395				PRINTF("%sloose", comma);
396				comma = ",";
397			}
398			if (fp->fr_flags & FR_NEWISN) {
399				PRINTF("%snewisn", comma);
400				comma = ",";
401			}
402			if (fp->fr_flags & FR_NOICMPERR) {
403				PRINTF("%sno-icmp-err", comma);
404				comma = ",";
405			}
406			if (fp->fr_flags & FR_STATESYNC) {
407				PRINTF("%ssync", comma);
408				comma = ",";
409			}
410			if (fp->fr_age[0] || fp->fr_age[1])
411				PRINTF("%sage %d/%d", comma, fp->fr_age[0],
412				       fp->fr_age[1]);
413			PRINTF(")");
414		}
415	}
416	if (fp->fr_flags & FR_KEEPFRAG) {
417		PRINTF(" keep frags");
418		if (fp->fr_flags & (FR_FRSTRICT)) {
419			PRINTF(" (");
420			if (fp->fr_flags & FR_FRSTRICT)
421				PRINTF("strict");
422			PRINTF(")");
423
424		}
425	}
426	if (fp->fr_isc != (struct ipscan *)-1) {
427		if (fp->fr_isctag != -1)
428			PRINTF(" scan %s", fp->fr_isctag + fp->fr_names);
429		else
430			PRINTF(" scan *");
431	}
432	if (fp->fr_grhead != -1)
433		PRINTF(" head %s", fp->fr_names + fp->fr_grhead);
434	if (fp->fr_group != -1)
435		PRINTF(" group %s", fp->fr_names + fp->fr_group);
436	if (fp->fr_logtag != FR_NOLOGTAG || *fp->fr_nattag.ipt_tag) {
437		char *s = "";
438
439		PRINTF(" set-tag(");
440		if (fp->fr_logtag != FR_NOLOGTAG) {
441			PRINTF("log=%u", fp->fr_logtag);
442			s = ", ";
443		}
444		if (*fp->fr_nattag.ipt_tag) {
445			PRINTF("%snat=%-.*s", s, IPFTAG_LEN,
446				fp->fr_nattag.ipt_tag);
447		}
448		PRINTF(")");
449	}
450
451	if (fp->fr_pps)
452		PRINTF(" pps %d", fp->fr_pps);
453
454	if (fp->fr_comment != -1)
455		PRINTF(" comment \"%s\"", fp->fr_names + fp->fr_comment);
456
457	hash = 0;
458	if ((fp->fr_flags & FR_KEEPSTATE) && (opts & OPT_VERBOSE)) {
459		PRINTF(" # count %d", fp->fr_statecnt);
460		if (fp->fr_die != 0)
461			PRINTF(" rule-ttl %u", fp->fr_die);
462		hash = 1;
463	} else if (fp->fr_die != 0) {
464		PRINTF(" # rule-ttl %u", fp->fr_die);
465		hash = 1;
466	}
467	if (opts & OPT_DEBUG) {
468		if (hash == 0)
469			putchar('#');
470		PRINTF(" ref %d", fp->fr_ref);
471	}
472	(void)putchar('\n');
473}
474