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