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