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
printfr(struct frentry * fp,ioctlfunc_t iocfunc)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