1 /* $NetBSD: printfr.c,v 1.2 2012/07/22 14:27:36 darrenr Exp $ */
2
3 /*
4 * Copyright (C) 2012 by Darren Reed.
5 *
6 * See the IPFILTER.LICENCE file for details on licencing.
7 *
8 * Id: printfr.c,v 1.1.1.2 2012/07/22 13:44:40 darrenr Exp $
9 */
10
11 #include "ipf.h"
12
13
14 /*
15 * print the filter structure in a useful way
16 */
17 void
printfr(fp,iocfunc)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