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