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 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