1 /* $FreeBSD$ */ 2 3 /* 4 * Copyright (C) 2012 by Darren Reed. 5 * 6 * See the IPFILTER.LICENCE file for details on licencing. 7 * 8 * $Id$ 9 */ 10 11 #include "ipf.h" 12 13 14 /* 15 * print the filter structure in a useful way 16 */ 17 void 18 printfr( struct frentry *fp, ioctlfunc_t iocfunc) 19 { 20 struct protoent *p; 21 u_short sec[2]; 22 u_32_t type; 23 int pr, af; 24 char *s; 25 int hash; 26 27 pr = -2; 28 type = fp->fr_type & ~FR_T_BUILTIN; 29 30 if ((fp->fr_type & FR_T_BUILTIN) != 0) 31 PRINTF("# Builtin: "); 32 33 if (fp->fr_collect != 0) 34 PRINTF("%u ", fp->fr_collect); 35 36 if (fp->fr_type == FR_T_CALLFUNC) { 37 ; 38 } else if (fp->fr_func != NULL) { 39 PRINTF("call"); 40 if ((fp->fr_flags & FR_CALLNOW) != 0) 41 PRINTF(" now"); 42 s = kvatoname(fp->fr_func, iocfunc); 43 PRINTF(" %s/%u", s ? s : "?", fp->fr_arg); 44 } else if (FR_ISPASS(fp->fr_flags)) 45 PRINTF("pass"); 46 else if (FR_ISBLOCK(fp->fr_flags)) { 47 PRINTF("block"); 48 } else if ((fp->fr_flags & FR_LOGMASK) == FR_LOG) { 49 printlog(fp); 50 } else if (FR_ISACCOUNT(fp->fr_flags)) 51 PRINTF("count"); 52 else if (FR_ISAUTH(fp->fr_flags)) 53 PRINTF("auth"); 54 else if (FR_ISPREAUTH(fp->fr_flags)) 55 PRINTF("preauth"); 56 else if (FR_ISNOMATCH(fp->fr_flags)) 57 PRINTF("nomatch"); 58 else if (FR_ISDECAPS(fp->fr_flags)) 59 PRINTF("decapsulate"); 60 else if (FR_ISSKIP(fp->fr_flags)) 61 PRINTF("skip %u", fp->fr_arg); 62 else { 63 PRINTF("%x", fp->fr_flags); 64 } 65 if (fp->fr_flags & FR_RETICMP) { 66 if ((fp->fr_flags & FR_RETMASK) == FR_FAKEICMP) 67 PRINTF(" return-icmp-as-dest"); 68 else if ((fp->fr_flags & FR_RETMASK) == FR_RETICMP) 69 PRINTF(" return-icmp"); 70 if (fp->fr_icode) { 71 if (fp->fr_icode <= MAX_ICMPCODE) 72 PRINTF("(%s)", 73 icmpcodes[(int)fp->fr_icode]); 74 else 75 PRINTF("(%d)", fp->fr_icode); 76 } 77 } else if ((fp->fr_flags & FR_RETMASK) == FR_RETRST) 78 PRINTF(" return-rst"); 79 80 if (fp->fr_flags & FR_OUTQUE) 81 PRINTF(" out "); 82 else if (fp->fr_flags & FR_INQUE) 83 PRINTF(" in "); 84 85 if (((fp->fr_flags & FR_LOGB) == FR_LOGB) || 86 ((fp->fr_flags & FR_LOGP) == FR_LOGP)) { 87 printlog(fp); 88 putchar(' '); 89 } 90 91 if (fp->fr_flags & FR_QUICK) 92 PRINTF("quick "); 93 94 if (fp->fr_ifnames[0] != -1) { 95 printifname("on ", fp->fr_names + fp->fr_ifnames[0], 96 fp->fr_ifa); 97 if (fp->fr_ifnames[1] != -1 && 98 strcmp(fp->fr_names + fp->fr_ifnames[1], "*")) 99 printifname(",", fp->fr_names + fp->fr_ifnames[1], 100 fp->fr_ifas[1]); 101 putchar(' '); 102 } 103 104 if (fp->fr_tif.fd_name != -1) 105 print_toif(fp->fr_family, "to", fp->fr_names, &fp->fr_tif); 106 if (fp->fr_dif.fd_name != -1) 107 print_toif(fp->fr_family, "dup-to", fp->fr_names, 108 &fp->fr_dif); 109 if (fp->fr_rif.fd_name != -1) 110 print_toif(fp->fr_family, "reply-to", fp->fr_names, 111 &fp->fr_rif); 112 if (fp->fr_flags & FR_FASTROUTE) 113 PRINTF("fastroute "); 114 115 if ((fp->fr_ifnames[2] != -1 && 116 strcmp(fp->fr_names + fp->fr_ifnames[2], "*")) || 117 (fp->fr_ifnames[3] != -1 && 118 strcmp(fp->fr_names + fp->fr_ifnames[3], "*"))) { 119 if (fp->fr_flags & FR_OUTQUE) 120 PRINTF("in-via "); 121 else 122 PRINTF("out-via "); 123 124 if (fp->fr_ifnames[2] != -1) { 125 printifname("", fp->fr_names + fp->fr_ifnames[2], 126 fp->fr_ifas[2]); 127 if (fp->fr_ifnames[3] != -1) { 128 printifname(",", 129 fp->fr_names + fp->fr_ifnames[3], 130 fp->fr_ifas[3]); 131 } 132 putchar(' '); 133 } 134 } 135 136 if (fp->fr_family == AF_INET) { 137 PRINTF("inet "); 138 af = AF_INET; 139 #ifdef USE_INET6 140 } else if (fp->fr_family == AF_INET6) { 141 PRINTF("inet6 "); 142 af = AF_INET6; 143 #endif 144 } else { 145 af = -1; 146 } 147 148 if (type == FR_T_IPF) { 149 if (fp->fr_mip.fi_tos) 150 PRINTF("tos %#x ", fp->fr_tos); 151 if (fp->fr_mip.fi_ttl) 152 PRINTF("ttl %d ", fp->fr_ttl); 153 if (fp->fr_flx & FI_TCPUDP) { 154 PRINTF("proto tcp/udp "); 155 pr = -1; 156 } else if (fp->fr_mip.fi_p) { 157 pr = fp->fr_ip.fi_p; 158 p = getprotobynumber(pr); 159 PRINTF("proto "); 160 printproto(p, pr, NULL); 161 putchar(' '); 162 } 163 } 164 165 switch (type) 166 { 167 case FR_T_NONE : 168 PRINTF("all"); 169 break; 170 171 case FR_T_IPF : 172 PRINTF("from %s", fp->fr_flags & FR_NOTSRCIP ? "!" : ""); 173 printaddr(af, fp->fr_satype, fp->fr_names, fp->fr_ifnames[0], 174 &fp->fr_src.s_addr, &fp->fr_smsk.s_addr); 175 if (fp->fr_scmp) 176 printportcmp(pr, &fp->fr_tuc.ftu_src); 177 178 PRINTF(" to %s", fp->fr_flags & FR_NOTDSTIP ? "!" : ""); 179 printaddr(af, fp->fr_datype, fp->fr_names, fp->fr_ifnames[0], 180 &fp->fr_dst.s_addr, &fp->fr_dmsk.s_addr); 181 if (fp->fr_dcmp) 182 printportcmp(pr, &fp->fr_tuc.ftu_dst); 183 184 if (((fp->fr_proto == IPPROTO_ICMP) || 185 (fp->fr_proto == IPPROTO_ICMPV6)) && fp->fr_icmpm) { 186 int type = fp->fr_icmp, code; 187 char *name; 188 189 type = ntohs(fp->fr_icmp); 190 code = type & 0xff; 191 type /= 256; 192 name = icmptypename(fp->fr_family, type); 193 if (name == NULL) 194 PRINTF(" icmp-type %d", type); 195 else 196 PRINTF(" icmp-type %s", name); 197 if (ntohs(fp->fr_icmpm) & 0xff) 198 PRINTF(" code %d", code); 199 } 200 if ((fp->fr_proto == IPPROTO_TCP) && 201 (fp->fr_tcpf || fp->fr_tcpfm)) { 202 PRINTF(" flags "); 203 printtcpflags(fp->fr_tcpf, fp->fr_tcpfm); 204 } 205 break; 206 207 case FR_T_BPFOPC : 208 { 209 fakebpf_t *fb; 210 int i; 211 212 PRINTF("bpf-v%d { \"", fp->fr_family); 213 i = fp->fr_dsize / sizeof(*fb); 214 215 for (fb = fp->fr_data, s = ""; i; i--, fb++, s = " ") 216 PRINTF("%s%#x %#x %#x %#x", s, fb->fb_c, fb->fb_t, 217 fb->fb_f, fb->fb_k); 218 219 PRINTF("\" }"); 220 break; 221 } 222 223 case FR_T_COMPIPF : 224 break; 225 226 case FR_T_CALLFUNC : 227 PRINTF("call function at %p", fp->fr_data); 228 break; 229 230 case FR_T_IPFEXPR : 231 PRINTF("exp { \""); 232 printipfexpr(fp->fr_data); 233 PRINTF("\" } "); 234 break; 235 236 default : 237 PRINTF("[unknown filter type %#x]", fp->fr_type); 238 break; 239 } 240 241 if ((type == FR_T_IPF) && 242 ((fp->fr_flx & FI_WITH) || (fp->fr_mflx & FI_WITH) || 243 fp->fr_optbits || fp->fr_optmask || 244 fp->fr_secbits || fp->fr_secmask)) { 245 char *comma = " "; 246 247 PRINTF(" with"); 248 if (fp->fr_optbits || fp->fr_optmask || 249 fp->fr_secbits || fp->fr_secmask) { 250 sec[0] = fp->fr_secmask; 251 sec[1] = fp->fr_secbits; 252 if (fp->fr_family == AF_INET) 253 optprint(sec, fp->fr_optmask, fp->fr_optbits); 254 #ifdef USE_INET6 255 else 256 optprintv6(sec, fp->fr_optmask, 257 fp->fr_optbits); 258 #endif 259 } else if (fp->fr_mflx & FI_OPTIONS) { 260 fputs(comma, stdout); 261 if (!(fp->fr_flx & FI_OPTIONS)) 262 PRINTF("not "); 263 PRINTF("ipopts"); 264 comma = ","; 265 } 266 if (fp->fr_mflx & FI_SHORT) { 267 fputs(comma, stdout); 268 if (!(fp->fr_flx & FI_SHORT)) 269 PRINTF("not "); 270 PRINTF("short"); 271 comma = ","; 272 } 273 if (fp->fr_mflx & FI_FRAG) { 274 fputs(comma, stdout); 275 if (!(fp->fr_flx & FI_FRAG)) 276 PRINTF("not "); 277 PRINTF("frag"); 278 comma = ","; 279 } 280 if (fp->fr_mflx & FI_FRAGBODY) { 281 fputs(comma, stdout); 282 if (!(fp->fr_flx & FI_FRAGBODY)) 283 PRINTF("not "); 284 PRINTF("frag-body"); 285 comma = ","; 286 } 287 if (fp->fr_mflx & FI_NATED) { 288 fputs(comma, stdout); 289 if (!(fp->fr_flx & FI_NATED)) 290 PRINTF("not "); 291 PRINTF("nat"); 292 comma = ","; 293 } 294 if (fp->fr_mflx & FI_LOWTTL) { 295 fputs(comma, stdout); 296 if (!(fp->fr_flx & FI_LOWTTL)) 297 PRINTF("not "); 298 PRINTF("lowttl"); 299 comma = ","; 300 } 301 if (fp->fr_mflx & FI_BAD) { 302 fputs(comma, stdout); 303 if (!(fp->fr_flx & FI_BAD)) 304 PRINTF("not "); 305 PRINTF("bad"); 306 comma = ","; 307 } 308 if (fp->fr_mflx & FI_BADSRC) { 309 fputs(comma, stdout); 310 if (!(fp->fr_flx & FI_BADSRC)) 311 PRINTF("not "); 312 PRINTF("bad-src"); 313 comma = ","; 314 } 315 if (fp->fr_mflx & FI_BADNAT) { 316 fputs(comma, stdout); 317 if (!(fp->fr_flx & FI_BADNAT)) 318 PRINTF("not "); 319 PRINTF("bad-nat"); 320 comma = ","; 321 } 322 if (fp->fr_mflx & FI_OOW) { 323 fputs(comma, stdout); 324 if (!(fp->fr_flx & FI_OOW)) 325 PRINTF("not "); 326 PRINTF("oow"); 327 comma = ","; 328 } 329 if (fp->fr_mflx & FI_MBCAST) { 330 fputs(comma, stdout); 331 if (!(fp->fr_flx & FI_MBCAST)) 332 PRINTF("not "); 333 PRINTF("mbcast"); 334 comma = ","; 335 } 336 if (fp->fr_mflx & FI_BROADCAST) { 337 fputs(comma, stdout); 338 if (!(fp->fr_flx & FI_BROADCAST)) 339 PRINTF("not "); 340 PRINTF("bcast"); 341 comma = ","; 342 } 343 if (fp->fr_mflx & FI_MULTICAST) { 344 fputs(comma, stdout); 345 if (!(fp->fr_flx & FI_MULTICAST)) 346 PRINTF("not "); 347 PRINTF("mcast"); 348 comma = ","; 349 } 350 if (fp->fr_mflx & FI_STATE) { 351 fputs(comma, stdout); 352 if (!(fp->fr_flx & FI_STATE)) 353 PRINTF("not "); 354 PRINTF("state"); 355 comma = ","; 356 } 357 if (fp->fr_mflx & FI_V6EXTHDR) { 358 fputs(comma, stdout); 359 if (!(fp->fr_flx & FI_V6EXTHDR)) 360 PRINTF("not "); 361 PRINTF("v6hdrs"); 362 comma = ","; 363 } 364 } 365 366 if (fp->fr_flags & FR_KEEPSTATE) { 367 host_track_t *src = &fp->fr_srctrack; 368 PRINTF(" keep state"); 369 if ((fp->fr_flags & (FR_STSTRICT|FR_NEWISN| 370 FR_NOICMPERR|FR_STATESYNC)) || 371 (fp->fr_statemax != 0) || (fp->fr_age[0] != 0) || 372 (src->ht_max_nodes != 0)) { 373 char *comma = ""; 374 PRINTF(" ("); 375 if (fp->fr_statemax != 0) { 376 PRINTF("limit %u", fp->fr_statemax); 377 comma = ","; 378 } 379 if (src->ht_max_nodes != 0) { 380 PRINTF("%smax-nodes %d", comma, 381 src->ht_max_nodes); 382 if (src->ht_max_per_node) 383 PRINTF(", max-per-src %d/%d", 384 src->ht_max_per_node, 385 src->ht_netmask); 386 comma = ","; 387 } 388 if (fp->fr_flags & FR_STSTRICT) { 389 PRINTF("%sstrict", comma); 390 comma = ","; 391 } 392 if (fp->fr_flags & FR_STLOOSE) { 393 PRINTF("%sloose", comma); 394 comma = ","; 395 } 396 if (fp->fr_flags & FR_NEWISN) { 397 PRINTF("%snewisn", comma); 398 comma = ","; 399 } 400 if (fp->fr_flags & FR_NOICMPERR) { 401 PRINTF("%sno-icmp-err", comma); 402 comma = ","; 403 } 404 if (fp->fr_flags & FR_STATESYNC) { 405 PRINTF("%ssync", comma); 406 comma = ","; 407 } 408 if (fp->fr_age[0] || fp->fr_age[1]) 409 PRINTF("%sage %d/%d", comma, fp->fr_age[0], 410 fp->fr_age[1]); 411 PRINTF(")"); 412 } 413 } 414 if (fp->fr_flags & FR_KEEPFRAG) { 415 PRINTF(" keep frags"); 416 if (fp->fr_flags & (FR_FRSTRICT)) { 417 PRINTF(" ("); 418 if (fp->fr_flags & FR_FRSTRICT) 419 PRINTF("strict"); 420 PRINTF(")"); 421 422 } 423 } 424 if (fp->fr_isc != (struct ipscan *)-1) { 425 if (fp->fr_isctag != -1) 426 PRINTF(" scan %s", fp->fr_isctag + fp->fr_names); 427 else 428 PRINTF(" scan *"); 429 } 430 if (fp->fr_grhead != -1) 431 PRINTF(" head %s", fp->fr_names + fp->fr_grhead); 432 if (fp->fr_group != -1) 433 PRINTF(" group %s", fp->fr_names + fp->fr_group); 434 if (fp->fr_logtag != FR_NOLOGTAG || *fp->fr_nattag.ipt_tag) { 435 char *s = ""; 436 437 PRINTF(" set-tag("); 438 if (fp->fr_logtag != FR_NOLOGTAG) { 439 PRINTF("log=%u", fp->fr_logtag); 440 s = ", "; 441 } 442 if (*fp->fr_nattag.ipt_tag) { 443 PRINTF("%snat=%-.*s", s, IPFTAG_LEN, 444 fp->fr_nattag.ipt_tag); 445 } 446 PRINTF(")"); 447 } 448 449 if (fp->fr_pps) 450 PRINTF(" pps %d", fp->fr_pps); 451 452 if (fp->fr_comment != -1) 453 PRINTF(" comment \"%s\"", fp->fr_names + fp->fr_comment); 454 455 hash = 0; 456 if ((fp->fr_flags & FR_KEEPSTATE) && (opts & OPT_VERBOSE)) { 457 PRINTF(" # count %d", fp->fr_statecnt); 458 if (fp->fr_die != 0) 459 PRINTF(" rule-ttl %u", fp->fr_die); 460 hash = 1; 461 } else if (fp->fr_die != 0) { 462 PRINTF(" # rule-ttl %u", fp->fr_die); 463 hash = 1; 464 } 465 if (opts & OPT_DEBUG) { 466 if (hash == 0) 467 putchar('#'); 468 PRINTF(" ref %d", fp->fr_ref); 469 } 470 (void)putchar('\n'); 471 } 472