xref: /freebsd/sbin/ipf/libipf/printfr.c (revision 963f5dc7a30624e95d72fb7f87b8892651164e46)
1 /*	$FreeBSD$	*/
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  */
17 void
18 printfr(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