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