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