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