141edb306SCy Schubert
241edb306SCy Schubert /*
341edb306SCy Schubert * Copyright (C) 2012 by Darren Reed.
441edb306SCy Schubert *
541edb306SCy Schubert * See the IPFILTER.LICENCE file for details on licencing.
641edb306SCy Schubert *
741edb306SCy Schubert * $Id$
841edb306SCy Schubert */
941edb306SCy Schubert
1041edb306SCy Schubert #include "ipf.h"
1141edb306SCy Schubert
1241edb306SCy Schubert
1341edb306SCy Schubert /*
1441edb306SCy Schubert * print the filter structure in a useful way
1541edb306SCy Schubert */
1641edb306SCy Schubert void
printfr(struct frentry * fp,ioctlfunc_t iocfunc)17*efeb8bffSCy Schubert printfr( struct frentry *fp, ioctlfunc_t iocfunc)
1841edb306SCy Schubert {
1941edb306SCy Schubert struct protoent *p;
2041edb306SCy Schubert u_short sec[2];
2141edb306SCy Schubert u_32_t type;
2241edb306SCy Schubert int pr, af;
2341edb306SCy Schubert char *s;
2441edb306SCy Schubert int hash;
2541edb306SCy Schubert
2641edb306SCy Schubert pr = -2;
2741edb306SCy Schubert type = fp->fr_type & ~FR_T_BUILTIN;
2841edb306SCy Schubert
2941edb306SCy Schubert if ((fp->fr_type & FR_T_BUILTIN) != 0)
3041edb306SCy Schubert PRINTF("# Builtin: ");
3141edb306SCy Schubert
3241edb306SCy Schubert if (fp->fr_collect != 0)
3341edb306SCy Schubert PRINTF("%u ", fp->fr_collect);
3441edb306SCy Schubert
3541edb306SCy Schubert if (fp->fr_type == FR_T_CALLFUNC) {
3641edb306SCy Schubert ;
3741edb306SCy Schubert } else if (fp->fr_func != NULL) {
3841edb306SCy Schubert PRINTF("call");
3941edb306SCy Schubert if ((fp->fr_flags & FR_CALLNOW) != 0)
4041edb306SCy Schubert PRINTF(" now");
4141edb306SCy Schubert s = kvatoname(fp->fr_func, iocfunc);
4241edb306SCy Schubert PRINTF(" %s/%u", s ? s : "?", fp->fr_arg);
4341edb306SCy Schubert } else if (FR_ISPASS(fp->fr_flags))
4441edb306SCy Schubert PRINTF("pass");
4541edb306SCy Schubert else if (FR_ISBLOCK(fp->fr_flags)) {
4641edb306SCy Schubert PRINTF("block");
4741edb306SCy Schubert } else if ((fp->fr_flags & FR_LOGMASK) == FR_LOG) {
4841edb306SCy Schubert printlog(fp);
4941edb306SCy Schubert } else if (FR_ISACCOUNT(fp->fr_flags))
5041edb306SCy Schubert PRINTF("count");
5141edb306SCy Schubert else if (FR_ISAUTH(fp->fr_flags))
5241edb306SCy Schubert PRINTF("auth");
5341edb306SCy Schubert else if (FR_ISPREAUTH(fp->fr_flags))
5441edb306SCy Schubert PRINTF("preauth");
5541edb306SCy Schubert else if (FR_ISNOMATCH(fp->fr_flags))
5641edb306SCy Schubert PRINTF("nomatch");
5741edb306SCy Schubert else if (FR_ISDECAPS(fp->fr_flags))
5841edb306SCy Schubert PRINTF("decapsulate");
5941edb306SCy Schubert else if (FR_ISSKIP(fp->fr_flags))
6041edb306SCy Schubert PRINTF("skip %u", fp->fr_arg);
6141edb306SCy Schubert else {
6241edb306SCy Schubert PRINTF("%x", fp->fr_flags);
6341edb306SCy Schubert }
6441edb306SCy Schubert if (fp->fr_flags & FR_RETICMP) {
6541edb306SCy Schubert if ((fp->fr_flags & FR_RETMASK) == FR_FAKEICMP)
6641edb306SCy Schubert PRINTF(" return-icmp-as-dest");
6741edb306SCy Schubert else if ((fp->fr_flags & FR_RETMASK) == FR_RETICMP)
6841edb306SCy Schubert PRINTF(" return-icmp");
6941edb306SCy Schubert if (fp->fr_icode) {
7041edb306SCy Schubert if (fp->fr_icode <= MAX_ICMPCODE)
7141edb306SCy Schubert PRINTF("(%s)",
7241edb306SCy Schubert icmpcodes[(int)fp->fr_icode]);
7341edb306SCy Schubert else
7441edb306SCy Schubert PRINTF("(%d)", fp->fr_icode);
7541edb306SCy Schubert }
7641edb306SCy Schubert } else if ((fp->fr_flags & FR_RETMASK) == FR_RETRST)
7741edb306SCy Schubert PRINTF(" return-rst");
7841edb306SCy Schubert
7941edb306SCy Schubert if (fp->fr_flags & FR_OUTQUE)
8041edb306SCy Schubert PRINTF(" out ");
8141edb306SCy Schubert else if (fp->fr_flags & FR_INQUE)
8241edb306SCy Schubert PRINTF(" in ");
8341edb306SCy Schubert
8441edb306SCy Schubert if (((fp->fr_flags & FR_LOGB) == FR_LOGB) ||
8541edb306SCy Schubert ((fp->fr_flags & FR_LOGP) == FR_LOGP)) {
8641edb306SCy Schubert printlog(fp);
8741edb306SCy Schubert putchar(' ');
8841edb306SCy Schubert }
8941edb306SCy Schubert
9041edb306SCy Schubert if (fp->fr_flags & FR_QUICK)
9141edb306SCy Schubert PRINTF("quick ");
9241edb306SCy Schubert
9341edb306SCy Schubert if (fp->fr_ifnames[0] != -1) {
9441edb306SCy Schubert printifname("on ", fp->fr_names + fp->fr_ifnames[0],
9541edb306SCy Schubert fp->fr_ifa);
9641edb306SCy Schubert if (fp->fr_ifnames[1] != -1 &&
9741edb306SCy Schubert strcmp(fp->fr_names + fp->fr_ifnames[1], "*"))
9841edb306SCy Schubert printifname(",", fp->fr_names + fp->fr_ifnames[1],
9941edb306SCy Schubert fp->fr_ifas[1]);
10041edb306SCy Schubert putchar(' ');
10141edb306SCy Schubert }
10241edb306SCy Schubert
10341edb306SCy Schubert if (fp->fr_tif.fd_name != -1)
10441edb306SCy Schubert print_toif(fp->fr_family, "to", fp->fr_names, &fp->fr_tif);
10541edb306SCy Schubert if (fp->fr_dif.fd_name != -1)
10641edb306SCy Schubert print_toif(fp->fr_family, "dup-to", fp->fr_names,
10741edb306SCy Schubert &fp->fr_dif);
10841edb306SCy Schubert if (fp->fr_rif.fd_name != -1)
10941edb306SCy Schubert print_toif(fp->fr_family, "reply-to", fp->fr_names,
11041edb306SCy Schubert &fp->fr_rif);
11141edb306SCy Schubert if (fp->fr_flags & FR_FASTROUTE)
11241edb306SCy Schubert PRINTF("fastroute ");
11341edb306SCy Schubert
11441edb306SCy Schubert if ((fp->fr_ifnames[2] != -1 &&
11541edb306SCy Schubert strcmp(fp->fr_names + fp->fr_ifnames[2], "*")) ||
11641edb306SCy Schubert (fp->fr_ifnames[3] != -1 &&
11741edb306SCy Schubert strcmp(fp->fr_names + fp->fr_ifnames[3], "*"))) {
11841edb306SCy Schubert if (fp->fr_flags & FR_OUTQUE)
11941edb306SCy Schubert PRINTF("in-via ");
12041edb306SCy Schubert else
12141edb306SCy Schubert PRINTF("out-via ");
12241edb306SCy Schubert
12341edb306SCy Schubert if (fp->fr_ifnames[2] != -1) {
12441edb306SCy Schubert printifname("", fp->fr_names + fp->fr_ifnames[2],
12541edb306SCy Schubert fp->fr_ifas[2]);
12641edb306SCy Schubert if (fp->fr_ifnames[3] != -1) {
12741edb306SCy Schubert printifname(",",
12841edb306SCy Schubert fp->fr_names + fp->fr_ifnames[3],
12941edb306SCy Schubert fp->fr_ifas[3]);
13041edb306SCy Schubert }
13141edb306SCy Schubert putchar(' ');
13241edb306SCy Schubert }
13341edb306SCy Schubert }
13441edb306SCy Schubert
13541edb306SCy Schubert if (fp->fr_family == AF_INET) {
13641edb306SCy Schubert PRINTF("inet ");
13741edb306SCy Schubert af = AF_INET;
13841edb306SCy Schubert #ifdef USE_INET6
13941edb306SCy Schubert } else if (fp->fr_family == AF_INET6) {
14041edb306SCy Schubert PRINTF("inet6 ");
14141edb306SCy Schubert af = AF_INET6;
14241edb306SCy Schubert #endif
14341edb306SCy Schubert } else {
14441edb306SCy Schubert af = -1;
14541edb306SCy Schubert }
14641edb306SCy Schubert
14741edb306SCy Schubert if (type == FR_T_IPF) {
14841edb306SCy Schubert if (fp->fr_mip.fi_tos)
14941edb306SCy Schubert PRINTF("tos %#x ", fp->fr_tos);
15041edb306SCy Schubert if (fp->fr_mip.fi_ttl)
15141edb306SCy Schubert PRINTF("ttl %d ", fp->fr_ttl);
15241edb306SCy Schubert if (fp->fr_flx & FI_TCPUDP) {
15341edb306SCy Schubert PRINTF("proto tcp/udp ");
15441edb306SCy Schubert pr = -1;
15541edb306SCy Schubert } else if (fp->fr_mip.fi_p) {
15641edb306SCy Schubert pr = fp->fr_ip.fi_p;
15741edb306SCy Schubert p = getprotobynumber(pr);
15841edb306SCy Schubert PRINTF("proto ");
15941edb306SCy Schubert printproto(p, pr, NULL);
16041edb306SCy Schubert putchar(' ');
16141edb306SCy Schubert }
16241edb306SCy Schubert }
16341edb306SCy Schubert
16441edb306SCy Schubert switch (type)
16541edb306SCy Schubert {
16641edb306SCy Schubert case FR_T_NONE :
16741edb306SCy Schubert PRINTF("all");
16841edb306SCy Schubert break;
16941edb306SCy Schubert
17041edb306SCy Schubert case FR_T_IPF :
17141edb306SCy Schubert PRINTF("from %s", fp->fr_flags & FR_NOTSRCIP ? "!" : "");
17241edb306SCy Schubert printaddr(af, fp->fr_satype, fp->fr_names, fp->fr_ifnames[0],
17341edb306SCy Schubert &fp->fr_src.s_addr, &fp->fr_smsk.s_addr);
17441edb306SCy Schubert if (fp->fr_scmp)
17541edb306SCy Schubert printportcmp(pr, &fp->fr_tuc.ftu_src);
17641edb306SCy Schubert
17741edb306SCy Schubert PRINTF(" to %s", fp->fr_flags & FR_NOTDSTIP ? "!" : "");
17841edb306SCy Schubert printaddr(af, fp->fr_datype, fp->fr_names, fp->fr_ifnames[0],
17941edb306SCy Schubert &fp->fr_dst.s_addr, &fp->fr_dmsk.s_addr);
18041edb306SCy Schubert if (fp->fr_dcmp)
18141edb306SCy Schubert printportcmp(pr, &fp->fr_tuc.ftu_dst);
18241edb306SCy Schubert
18341edb306SCy Schubert if (((fp->fr_proto == IPPROTO_ICMP) ||
18441edb306SCy Schubert (fp->fr_proto == IPPROTO_ICMPV6)) && fp->fr_icmpm) {
18541edb306SCy Schubert int type = fp->fr_icmp, code;
18641edb306SCy Schubert char *name;
18741edb306SCy Schubert
18841edb306SCy Schubert type = ntohs(fp->fr_icmp);
18941edb306SCy Schubert code = type & 0xff;
19041edb306SCy Schubert type /= 256;
19141edb306SCy Schubert name = icmptypename(fp->fr_family, type);
19241edb306SCy Schubert if (name == NULL)
19341edb306SCy Schubert PRINTF(" icmp-type %d", type);
19441edb306SCy Schubert else
19541edb306SCy Schubert PRINTF(" icmp-type %s", name);
19641edb306SCy Schubert if (ntohs(fp->fr_icmpm) & 0xff)
19741edb306SCy Schubert PRINTF(" code %d", code);
19841edb306SCy Schubert }
19941edb306SCy Schubert if ((fp->fr_proto == IPPROTO_TCP) &&
20041edb306SCy Schubert (fp->fr_tcpf || fp->fr_tcpfm)) {
20141edb306SCy Schubert PRINTF(" flags ");
20241edb306SCy Schubert printtcpflags(fp->fr_tcpf, fp->fr_tcpfm);
20341edb306SCy Schubert }
20441edb306SCy Schubert break;
20541edb306SCy Schubert
20641edb306SCy Schubert case FR_T_BPFOPC :
20741edb306SCy Schubert {
20841edb306SCy Schubert fakebpf_t *fb;
20941edb306SCy Schubert int i;
21041edb306SCy Schubert
21141edb306SCy Schubert PRINTF("bpf-v%d { \"", fp->fr_family);
21241edb306SCy Schubert i = fp->fr_dsize / sizeof(*fb);
21341edb306SCy Schubert
21441edb306SCy Schubert for (fb = fp->fr_data, s = ""; i; i--, fb++, s = " ")
21541edb306SCy Schubert PRINTF("%s%#x %#x %#x %#x", s, fb->fb_c, fb->fb_t,
21641edb306SCy Schubert fb->fb_f, fb->fb_k);
21741edb306SCy Schubert
21841edb306SCy Schubert PRINTF("\" }");
21941edb306SCy Schubert break;
22041edb306SCy Schubert }
22141edb306SCy Schubert
22241edb306SCy Schubert case FR_T_COMPIPF :
22341edb306SCy Schubert break;
22441edb306SCy Schubert
22541edb306SCy Schubert case FR_T_CALLFUNC :
22641edb306SCy Schubert PRINTF("call function at %p", fp->fr_data);
22741edb306SCy Schubert break;
22841edb306SCy Schubert
22941edb306SCy Schubert case FR_T_IPFEXPR :
23041edb306SCy Schubert PRINTF("exp { \"");
23141edb306SCy Schubert printipfexpr(fp->fr_data);
23241edb306SCy Schubert PRINTF("\" } ");
23341edb306SCy Schubert break;
23441edb306SCy Schubert
23541edb306SCy Schubert default :
23641edb306SCy Schubert PRINTF("[unknown filter type %#x]", fp->fr_type);
23741edb306SCy Schubert break;
23841edb306SCy Schubert }
23941edb306SCy Schubert
24041edb306SCy Schubert if ((type == FR_T_IPF) &&
24141edb306SCy Schubert ((fp->fr_flx & FI_WITH) || (fp->fr_mflx & FI_WITH) ||
24241edb306SCy Schubert fp->fr_optbits || fp->fr_optmask ||
24341edb306SCy Schubert fp->fr_secbits || fp->fr_secmask)) {
24441edb306SCy Schubert char *comma = " ";
24541edb306SCy Schubert
24641edb306SCy Schubert PRINTF(" with");
24741edb306SCy Schubert if (fp->fr_optbits || fp->fr_optmask ||
24841edb306SCy Schubert fp->fr_secbits || fp->fr_secmask) {
24941edb306SCy Schubert sec[0] = fp->fr_secmask;
25041edb306SCy Schubert sec[1] = fp->fr_secbits;
25141edb306SCy Schubert if (fp->fr_family == AF_INET)
25241edb306SCy Schubert optprint(sec, fp->fr_optmask, fp->fr_optbits);
25341edb306SCy Schubert #ifdef USE_INET6
25441edb306SCy Schubert else
25541edb306SCy Schubert optprintv6(sec, fp->fr_optmask,
25641edb306SCy Schubert fp->fr_optbits);
25741edb306SCy Schubert #endif
25841edb306SCy Schubert } else if (fp->fr_mflx & FI_OPTIONS) {
25941edb306SCy Schubert fputs(comma, stdout);
26041edb306SCy Schubert if (!(fp->fr_flx & FI_OPTIONS))
26141edb306SCy Schubert PRINTF("not ");
26241edb306SCy Schubert PRINTF("ipopts");
26341edb306SCy Schubert comma = ",";
26441edb306SCy Schubert }
26541edb306SCy Schubert if (fp->fr_mflx & FI_SHORT) {
26641edb306SCy Schubert fputs(comma, stdout);
26741edb306SCy Schubert if (!(fp->fr_flx & FI_SHORT))
26841edb306SCy Schubert PRINTF("not ");
26941edb306SCy Schubert PRINTF("short");
27041edb306SCy Schubert comma = ",";
27141edb306SCy Schubert }
27241edb306SCy Schubert if (fp->fr_mflx & FI_FRAG) {
27341edb306SCy Schubert fputs(comma, stdout);
27441edb306SCy Schubert if (!(fp->fr_flx & FI_FRAG))
27541edb306SCy Schubert PRINTF("not ");
27641edb306SCy Schubert PRINTF("frag");
27741edb306SCy Schubert comma = ",";
27841edb306SCy Schubert }
27941edb306SCy Schubert if (fp->fr_mflx & FI_FRAGBODY) {
28041edb306SCy Schubert fputs(comma, stdout);
28141edb306SCy Schubert if (!(fp->fr_flx & FI_FRAGBODY))
28241edb306SCy Schubert PRINTF("not ");
28341edb306SCy Schubert PRINTF("frag-body");
28441edb306SCy Schubert comma = ",";
28541edb306SCy Schubert }
28641edb306SCy Schubert if (fp->fr_mflx & FI_NATED) {
28741edb306SCy Schubert fputs(comma, stdout);
28841edb306SCy Schubert if (!(fp->fr_flx & FI_NATED))
28941edb306SCy Schubert PRINTF("not ");
29041edb306SCy Schubert PRINTF("nat");
29141edb306SCy Schubert comma = ",";
29241edb306SCy Schubert }
29341edb306SCy Schubert if (fp->fr_mflx & FI_LOWTTL) {
29441edb306SCy Schubert fputs(comma, stdout);
29541edb306SCy Schubert if (!(fp->fr_flx & FI_LOWTTL))
29641edb306SCy Schubert PRINTF("not ");
29741edb306SCy Schubert PRINTF("lowttl");
29841edb306SCy Schubert comma = ",";
29941edb306SCy Schubert }
30041edb306SCy Schubert if (fp->fr_mflx & FI_BAD) {
30141edb306SCy Schubert fputs(comma, stdout);
30241edb306SCy Schubert if (!(fp->fr_flx & FI_BAD))
30341edb306SCy Schubert PRINTF("not ");
30441edb306SCy Schubert PRINTF("bad");
30541edb306SCy Schubert comma = ",";
30641edb306SCy Schubert }
30741edb306SCy Schubert if (fp->fr_mflx & FI_BADSRC) {
30841edb306SCy Schubert fputs(comma, stdout);
30941edb306SCy Schubert if (!(fp->fr_flx & FI_BADSRC))
31041edb306SCy Schubert PRINTF("not ");
31141edb306SCy Schubert PRINTF("bad-src");
31241edb306SCy Schubert comma = ",";
31341edb306SCy Schubert }
31441edb306SCy Schubert if (fp->fr_mflx & FI_BADNAT) {
31541edb306SCy Schubert fputs(comma, stdout);
31641edb306SCy Schubert if (!(fp->fr_flx & FI_BADNAT))
31741edb306SCy Schubert PRINTF("not ");
31841edb306SCy Schubert PRINTF("bad-nat");
31941edb306SCy Schubert comma = ",";
32041edb306SCy Schubert }
32141edb306SCy Schubert if (fp->fr_mflx & FI_OOW) {
32241edb306SCy Schubert fputs(comma, stdout);
32341edb306SCy Schubert if (!(fp->fr_flx & FI_OOW))
32441edb306SCy Schubert PRINTF("not ");
32541edb306SCy Schubert PRINTF("oow");
32641edb306SCy Schubert comma = ",";
32741edb306SCy Schubert }
32841edb306SCy Schubert if (fp->fr_mflx & FI_MBCAST) {
32941edb306SCy Schubert fputs(comma, stdout);
33041edb306SCy Schubert if (!(fp->fr_flx & FI_MBCAST))
33141edb306SCy Schubert PRINTF("not ");
33241edb306SCy Schubert PRINTF("mbcast");
33341edb306SCy Schubert comma = ",";
33441edb306SCy Schubert }
33541edb306SCy Schubert if (fp->fr_mflx & FI_BROADCAST) {
33641edb306SCy Schubert fputs(comma, stdout);
33741edb306SCy Schubert if (!(fp->fr_flx & FI_BROADCAST))
33841edb306SCy Schubert PRINTF("not ");
33941edb306SCy Schubert PRINTF("bcast");
34041edb306SCy Schubert comma = ",";
34141edb306SCy Schubert }
34241edb306SCy Schubert if (fp->fr_mflx & FI_MULTICAST) {
34341edb306SCy Schubert fputs(comma, stdout);
34441edb306SCy Schubert if (!(fp->fr_flx & FI_MULTICAST))
34541edb306SCy Schubert PRINTF("not ");
34641edb306SCy Schubert PRINTF("mcast");
34741edb306SCy Schubert comma = ",";
34841edb306SCy Schubert }
34941edb306SCy Schubert if (fp->fr_mflx & FI_STATE) {
35041edb306SCy Schubert fputs(comma, stdout);
35141edb306SCy Schubert if (!(fp->fr_flx & FI_STATE))
35241edb306SCy Schubert PRINTF("not ");
35341edb306SCy Schubert PRINTF("state");
35441edb306SCy Schubert comma = ",";
35541edb306SCy Schubert }
35641edb306SCy Schubert if (fp->fr_mflx & FI_V6EXTHDR) {
35741edb306SCy Schubert fputs(comma, stdout);
35841edb306SCy Schubert if (!(fp->fr_flx & FI_V6EXTHDR))
35941edb306SCy Schubert PRINTF("not ");
36041edb306SCy Schubert PRINTF("v6hdrs");
36141edb306SCy Schubert comma = ",";
36241edb306SCy Schubert }
36341edb306SCy Schubert }
36441edb306SCy Schubert
36541edb306SCy Schubert if (fp->fr_flags & FR_KEEPSTATE) {
36641edb306SCy Schubert host_track_t *src = &fp->fr_srctrack;
36741edb306SCy Schubert PRINTF(" keep state");
36841edb306SCy Schubert if ((fp->fr_flags & (FR_STSTRICT|FR_NEWISN|
36941edb306SCy Schubert FR_NOICMPERR|FR_STATESYNC)) ||
37041edb306SCy Schubert (fp->fr_statemax != 0) || (fp->fr_age[0] != 0) ||
37141edb306SCy Schubert (src->ht_max_nodes != 0)) {
37241edb306SCy Schubert char *comma = "";
37341edb306SCy Schubert PRINTF(" (");
37441edb306SCy Schubert if (fp->fr_statemax != 0) {
37541edb306SCy Schubert PRINTF("limit %u", fp->fr_statemax);
37641edb306SCy Schubert comma = ",";
37741edb306SCy Schubert }
37841edb306SCy Schubert if (src->ht_max_nodes != 0) {
37941edb306SCy Schubert PRINTF("%smax-nodes %d", comma,
38041edb306SCy Schubert src->ht_max_nodes);
38141edb306SCy Schubert if (src->ht_max_per_node)
38241edb306SCy Schubert PRINTF(", max-per-src %d/%d",
38341edb306SCy Schubert src->ht_max_per_node,
38441edb306SCy Schubert src->ht_netmask);
38541edb306SCy Schubert comma = ",";
38641edb306SCy Schubert }
38741edb306SCy Schubert if (fp->fr_flags & FR_STSTRICT) {
38841edb306SCy Schubert PRINTF("%sstrict", comma);
38941edb306SCy Schubert comma = ",";
39041edb306SCy Schubert }
39141edb306SCy Schubert if (fp->fr_flags & FR_STLOOSE) {
39241edb306SCy Schubert PRINTF("%sloose", comma);
39341edb306SCy Schubert comma = ",";
39441edb306SCy Schubert }
39541edb306SCy Schubert if (fp->fr_flags & FR_NEWISN) {
39641edb306SCy Schubert PRINTF("%snewisn", comma);
39741edb306SCy Schubert comma = ",";
39841edb306SCy Schubert }
39941edb306SCy Schubert if (fp->fr_flags & FR_NOICMPERR) {
40041edb306SCy Schubert PRINTF("%sno-icmp-err", comma);
40141edb306SCy Schubert comma = ",";
40241edb306SCy Schubert }
40341edb306SCy Schubert if (fp->fr_flags & FR_STATESYNC) {
40441edb306SCy Schubert PRINTF("%ssync", comma);
40541edb306SCy Schubert comma = ",";
40641edb306SCy Schubert }
40741edb306SCy Schubert if (fp->fr_age[0] || fp->fr_age[1])
40841edb306SCy Schubert PRINTF("%sage %d/%d", comma, fp->fr_age[0],
40941edb306SCy Schubert fp->fr_age[1]);
41041edb306SCy Schubert PRINTF(")");
41141edb306SCy Schubert }
41241edb306SCy Schubert }
41341edb306SCy Schubert if (fp->fr_flags & FR_KEEPFRAG) {
41441edb306SCy Schubert PRINTF(" keep frags");
41541edb306SCy Schubert if (fp->fr_flags & (FR_FRSTRICT)) {
41641edb306SCy Schubert PRINTF(" (");
41741edb306SCy Schubert if (fp->fr_flags & FR_FRSTRICT)
41841edb306SCy Schubert PRINTF("strict");
41941edb306SCy Schubert PRINTF(")");
42041edb306SCy Schubert
42141edb306SCy Schubert }
42241edb306SCy Schubert }
42341edb306SCy Schubert if (fp->fr_isc != (struct ipscan *)-1) {
42441edb306SCy Schubert if (fp->fr_isctag != -1)
42541edb306SCy Schubert PRINTF(" scan %s", fp->fr_isctag + fp->fr_names);
42641edb306SCy Schubert else
42741edb306SCy Schubert PRINTF(" scan *");
42841edb306SCy Schubert }
42941edb306SCy Schubert if (fp->fr_grhead != -1)
43041edb306SCy Schubert PRINTF(" head %s", fp->fr_names + fp->fr_grhead);
43141edb306SCy Schubert if (fp->fr_group != -1)
43241edb306SCy Schubert PRINTF(" group %s", fp->fr_names + fp->fr_group);
43341edb306SCy Schubert if (fp->fr_logtag != FR_NOLOGTAG || *fp->fr_nattag.ipt_tag) {
43441edb306SCy Schubert char *s = "";
43541edb306SCy Schubert
43641edb306SCy Schubert PRINTF(" set-tag(");
43741edb306SCy Schubert if (fp->fr_logtag != FR_NOLOGTAG) {
43841edb306SCy Schubert PRINTF("log=%u", fp->fr_logtag);
43941edb306SCy Schubert s = ", ";
44041edb306SCy Schubert }
44141edb306SCy Schubert if (*fp->fr_nattag.ipt_tag) {
44241edb306SCy Schubert PRINTF("%snat=%-.*s", s, IPFTAG_LEN,
44341edb306SCy Schubert fp->fr_nattag.ipt_tag);
44441edb306SCy Schubert }
44541edb306SCy Schubert PRINTF(")");
44641edb306SCy Schubert }
44741edb306SCy Schubert
44841edb306SCy Schubert if (fp->fr_pps)
44941edb306SCy Schubert PRINTF(" pps %d", fp->fr_pps);
45041edb306SCy Schubert
45141edb306SCy Schubert if (fp->fr_comment != -1)
45241edb306SCy Schubert PRINTF(" comment \"%s\"", fp->fr_names + fp->fr_comment);
45341edb306SCy Schubert
45441edb306SCy Schubert hash = 0;
45541edb306SCy Schubert if ((fp->fr_flags & FR_KEEPSTATE) && (opts & OPT_VERBOSE)) {
45641edb306SCy Schubert PRINTF(" # count %d", fp->fr_statecnt);
45741edb306SCy Schubert if (fp->fr_die != 0)
45841edb306SCy Schubert PRINTF(" rule-ttl %u", fp->fr_die);
45941edb306SCy Schubert hash = 1;
46041edb306SCy Schubert } else if (fp->fr_die != 0) {
46141edb306SCy Schubert PRINTF(" # rule-ttl %u", fp->fr_die);
46241edb306SCy Schubert hash = 1;
46341edb306SCy Schubert }
46441edb306SCy Schubert if (opts & OPT_DEBUG) {
46541edb306SCy Schubert if (hash == 0)
46641edb306SCy Schubert putchar('#');
46741edb306SCy Schubert PRINTF(" ref %d", fp->fr_ref);
46841edb306SCy Schubert }
46941edb306SCy Schubert (void)putchar('\n');
47041edb306SCy Schubert }
471