1 2 /* 3 * Copyright (C) 2012 by Darren Reed. 4 * 5 * See the IPFILTER.LICENCE file for details on licencing. 6 */ 7 #include <sys/ioctl.h> 8 #include <ctype.h> 9 #include <fcntl.h> 10 # include <nlist.h> 11 #include <ctype.h> 12 #if defined(sun) && defined(__SVR4) 13 # include <stddef.h> 14 #endif 15 #include "ipf.h" 16 #include "netinet/ipl.h" 17 #if defined(STATETOP) 18 # if defined(sun) && defined(__SVR4) 19 # include <sys/select.h> 20 # endif 21 # include <netinet/ip_var.h> 22 # include <netinet/tcp_fsm.h> 23 # include <ctype.h> 24 # include <signal.h> 25 # include <time.h> 26 # if SOLARIS || defined(__NetBSD__) 27 # ifdef ERR 28 # undef ERR 29 # endif 30 # include <curses.h> 31 # else /* SOLARIS */ 32 # include <ncurses.h> 33 # endif /* SOLARIS */ 34 #endif /* STATETOP */ 35 #include "kmem.h" 36 #if defined(__NetBSD__) 37 # include <paths.h> 38 #endif 39 40 41 42 extern char *optarg; 43 extern int optind; 44 extern int opterr; 45 46 #define PRINTF (void)printf 47 #define FPRINTF (void)fprintf 48 static char *filters[4] = { "ipfilter(in)", "ipfilter(out)", 49 "ipacct(in)", "ipacct(out)" }; 50 static int state_logging = -1; 51 static wordtab_t *state_fields = NULL; 52 53 int nohdrfields = 0; 54 int opts = 0; 55 #ifdef USE_INET6 56 int use_inet4 = 0; 57 int use_inet6 = 0; 58 #endif 59 int live_kernel = 1; 60 int state_fd = -1; 61 int ipf_fd = -1; 62 int auth_fd = -1; 63 int nat_fd = -1; 64 frgroup_t *grtop = NULL; 65 frgroup_t *grtail = NULL; 66 67 char *blockreasons[FRB_MAX_VALUE + 1] = { 68 "packet blocked", 69 "log rule failure", 70 "pps rate exceeded", 71 "jumbogram", 72 "makefrip failed", 73 "cannot add state", 74 "IP ID update failed", 75 "log-or-block failed", 76 "decapsulate failure", 77 "cannot create new auth entry", 78 "packet queued for auth", 79 "buffer coalesce failure", 80 "buffer pullup failure", 81 "auth feedback", 82 "bad fragment", 83 "IPv4 NAT failure", 84 "IPv6 NAT failure" 85 }; 86 87 #ifdef STATETOP 88 #define STSTRSIZE 80 89 #define STGROWSIZE 16 90 #define HOSTNMLEN 40 91 92 #define STSORT_PR 0 93 #define STSORT_PKTS 1 94 #define STSORT_BYTES 2 95 #define STSORT_TTL 3 96 #define STSORT_SRCIP 4 97 #define STSORT_SRCPT 5 98 #define STSORT_DSTIP 6 99 #define STSORT_DSTPT 7 100 #define STSORT_MAX STSORT_DSTPT 101 #define STSORT_DEFAULT STSORT_BYTES 102 103 104 typedef struct statetop { 105 i6addr_t st_src; 106 i6addr_t st_dst; 107 u_short st_sport; 108 u_short st_dport; 109 u_char st_p; 110 u_char st_v; 111 u_char st_state[2]; 112 U_QUAD_T st_pkts; 113 U_QUAD_T st_bytes; 114 u_long st_age; 115 } statetop_t; 116 #endif 117 118 int main(int, char *[]); 119 120 static int fetchfrag(int, int, ipfr_t *); 121 static void showstats(friostat_t *, u_32_t); 122 static void showfrstates(ipfrstat_t *, u_long); 123 static void showlist(friostat_t *); 124 static void showstatestats(ips_stat_t *); 125 static void showipstates(ips_stat_t *, int *); 126 static void showauthstates(ipf_authstat_t *); 127 static void showtqtable_live(int); 128 static void showgroups(friostat_t *); 129 static void usage(char *); 130 static int state_matcharray(ipstate_t *, int *); 131 static int printlivelist(friostat_t *, int, int, frentry_t *, 132 char *, char *); 133 static void printdeadlist(friostat_t *, int, int, frentry_t *, 134 char *, char *); 135 static void printside(char *, ipf_statistics_t *); 136 static void parse_ipportstr(const char *, i6addr_t *, int *); 137 static void ipfstate_live(char *, friostat_t **, ips_stat_t **, 138 ipfrstat_t **, ipf_authstat_t **, u_32_t *); 139 static void ipfstate_dead(char *, friostat_t **, ips_stat_t **, 140 ipfrstat_t **, ipf_authstat_t **, u_32_t *); 141 static ipstate_t *fetchstate(ipstate_t *, ipstate_t *); 142 #ifdef STATETOP 143 static void topipstates(i6addr_t, i6addr_t, int, int, int, 144 int, int, int, int *); 145 static void sig_break(int); 146 static void sig_resize(int); 147 static char *getip(int, i6addr_t *); 148 static char *ttl_to_string(long); 149 static int sort_p(const void *, const void *); 150 static int sort_pkts(const void *, const void *); 151 static int sort_bytes(const void *, const void *); 152 static int sort_ttl(const void *, const void *); 153 static int sort_srcip(const void *, const void *); 154 static int sort_srcpt(const void *, const void *); 155 static int sort_dstip(const void *, const void *); 156 static int sort_dstpt(const void *, const void *); 157 #endif 158 159 160 static void usage(char *name) 161 { 162 #ifdef USE_INET6 163 fprintf(stderr, "Usage: %s [-46aAdfghIilnoRsv]\n", name); 164 #else 165 fprintf(stderr, "Usage: %s [-4aAdfghIilnoRsv]\n", name); 166 #endif 167 fprintf(stderr, " %s [-M corefile] [-N symbol-list]\n", name); 168 #ifdef STATETOP 169 #ifdef USE_INET6 170 fprintf(stderr, " %s -t [-46C] ", name); 171 #else 172 fprintf(stderr, " %s -t [-4C] ", name); 173 #endif 174 #endif 175 fprintf(stderr, "[-D destination address] [-P protocol] [-S source address] [-T refresh time]\n"); 176 exit(1); 177 } 178 179 180 int main(int argc, char *argv[]) 181 { 182 ipf_authstat_t frauthst; 183 ipf_authstat_t *frauthstp = &frauthst; 184 friostat_t fio; 185 friostat_t *fiop = &fio; 186 ips_stat_t ipsst; 187 ips_stat_t *ipsstp = &ipsst; 188 ipfrstat_t ifrst; 189 ipfrstat_t *ifrstp = &ifrst; 190 char *options; 191 char *kern = NULL; 192 char *memf = NULL; 193 int c; 194 int myoptind; 195 int *filter = NULL; 196 197 int protocol = -1; /* -1 = wild card for any protocol */ 198 int refreshtime = 1; /* default update time */ 199 int sport = -1; /* -1 = wild card for any source port */ 200 int dport = -1; /* -1 = wild card for any dest port */ 201 int topclosed = 0; /* do not show closed tcp sessions */ 202 i6addr_t saddr, daddr; 203 u_32_t frf; 204 205 #ifdef USE_INET6 206 options = "46aACdfghIilnostvD:m:M:N:O:P:RS:T:"; 207 #else 208 options = "4aACdfghIilnostvD:m:M:N:O:P:RS:T:"; 209 #endif 210 211 saddr.in4.s_addr = INADDR_ANY; /* default any v4 source addr */ 212 daddr.in4.s_addr = INADDR_ANY; /* default any v4 dest addr */ 213 #ifdef USE_INET6 214 saddr.in6 = in6addr_any; /* default any v6 source addr */ 215 daddr.in6 = in6addr_any; /* default any v6 dest addr */ 216 #endif 217 218 /* Don't warn about invalid flags when we run getopt for the 1st time */ 219 opterr = 0; 220 221 /* 222 * Parse these two arguments now lest there be any buffer overflows 223 * in the parsing of the rest. 224 */ 225 myoptind = optind; 226 while ((c = getopt(argc, argv, options)) != -1) { 227 switch (c) 228 { 229 case 'M' : 230 memf = optarg; 231 live_kernel = 0; 232 break; 233 case 'N' : 234 kern = optarg; 235 live_kernel = 0; 236 break; 237 } 238 } 239 optind = myoptind; 240 241 if (live_kernel == 1) { 242 if ((state_fd = open(IPSTATE_NAME, O_RDONLY)) == -1) { 243 perror("open(IPSTATE_NAME)"); 244 exit(-1); 245 } 246 if ((auth_fd = open(IPAUTH_NAME, O_RDONLY)) == -1) { 247 perror("open(IPAUTH_NAME)"); 248 exit(-1); 249 } 250 if ((nat_fd = open(IPNAT_NAME, O_RDONLY)) == -1) { 251 perror("open(IPAUTH_NAME)"); 252 exit(-1); 253 } 254 if ((ipf_fd = open(IPL_NAME, O_RDONLY)) == -1) { 255 fprintf(stderr, "open(%s)", IPL_NAME); 256 perror(""); 257 exit(-1); 258 } 259 } 260 261 if (kern != NULL || memf != NULL) { 262 (void)setgid(getgid()); 263 (void)setuid(getuid()); 264 } 265 266 if (live_kernel == 1) { 267 (void) checkrev(IPL_NAME); 268 } else { 269 if (openkmem(kern, memf) == -1) 270 exit(-1); 271 } 272 273 (void)setgid(getgid()); 274 (void)setuid(getuid()); 275 276 opterr = 1; 277 278 while ((c = getopt(argc, argv, options)) != -1) 279 { 280 switch (c) 281 { 282 #ifdef USE_INET6 283 case '4' : 284 use_inet4 = 1; 285 break; 286 case '6' : 287 use_inet6 = 1; 288 break; 289 #endif 290 case 'a' : 291 opts |= OPT_ACCNT|OPT_SHOWLIST; 292 break; 293 case 'A' : 294 opts |= OPT_AUTHSTATS; 295 break; 296 case 'C' : 297 topclosed = 1; 298 break; 299 case 'd' : 300 opts |= OPT_DEBUG; 301 break; 302 case 'D' : 303 parse_ipportstr(optarg, &daddr, &dport); 304 break; 305 case 'f' : 306 opts |= OPT_FRSTATES; 307 break; 308 case 'g' : 309 opts |= OPT_GROUPS; 310 break; 311 case 'h' : 312 opts |= OPT_HITS; 313 break; 314 case 'i' : 315 opts |= OPT_INQUE|OPT_SHOWLIST; 316 break; 317 case 'I' : 318 opts |= OPT_INACTIVE; 319 break; 320 case 'l' : 321 opts |= OPT_SHOWLIST; 322 break; 323 case 'm' : 324 filter = parseipfexpr(optarg, NULL); 325 if (filter == NULL) { 326 fprintf(stderr, "Error parsing '%s'\n", 327 optarg); 328 exit(1); 329 } 330 break; 331 case 'M' : 332 break; 333 case 'N' : 334 break; 335 case 'n' : 336 opts |= OPT_SHOWLINENO; 337 break; 338 case 'o' : 339 opts |= OPT_OUTQUE|OPT_SHOWLIST; 340 break; 341 case 'O' : 342 state_fields = parsefields(statefields, optarg); 343 break; 344 case 'P' : 345 protocol = getproto(optarg); 346 if (protocol == -1) { 347 fprintf(stderr, "%s: Invalid protocol: %s\n", 348 argv[0], optarg); 349 exit(-2); 350 } 351 break; 352 case 'R' : 353 opts |= OPT_NORESOLVE; 354 break; 355 case 's' : 356 opts |= OPT_IPSTATES; 357 break; 358 case 'S' : 359 parse_ipportstr(optarg, &saddr, &sport); 360 break; 361 case 't' : 362 #ifdef STATETOP 363 opts |= OPT_STATETOP; 364 break; 365 #else 366 fprintf(stderr, 367 "%s: state top facility not compiled in\n", 368 argv[0]); 369 exit(-2); 370 #endif 371 case 'T' : 372 if (!sscanf(optarg, "%d", &refreshtime) || 373 (refreshtime <= 0)) { 374 fprintf(stderr, 375 "%s: Invalid refreshtime < 1 : %s\n", 376 argv[0], optarg); 377 exit(-2); 378 } 379 break; 380 case 'v' : 381 opts |= OPT_VERBOSE; 382 break; 383 default : 384 usage(argv[0]); 385 break; 386 } 387 } 388 #ifdef USE_INET6 389 if ((use_inet4 || use_inet6) && 390 !(opts & (OPT_INQUE | OPT_OUTQUE | OPT_STATETOP))) { 391 #ifdef STATETOP 392 FPRINTF(stderr, "No -i, -o, or -t given with -4 or -6\n"); 393 #else 394 FPRINTF(stderr, "No -i or -o given with -4 or -6\n"); 395 #endif 396 exit(-2); 397 } 398 if (use_inet4 == 0 && use_inet6 == 0) 399 use_inet4 = use_inet6 = 1; 400 #endif 401 402 if (live_kernel == 1) { 403 bzero((char *)&fio, sizeof(fio)); 404 bzero((char *)&ipsst, sizeof(ipsst)); 405 bzero((char *)&ifrst, sizeof(ifrst)); 406 407 ipfstate_live(IPL_NAME, &fiop, &ipsstp, &ifrstp, 408 &frauthstp, &frf); 409 } else { 410 ipfstate_dead(kern, &fiop, &ipsstp, &ifrstp, &frauthstp, &frf); 411 } 412 413 if (opts & OPT_IPSTATES) { 414 showipstates(ipsstp, filter); 415 } else if (opts & OPT_SHOWLIST) { 416 showlist(fiop); 417 if ((opts & OPT_OUTQUE) && (opts & OPT_INQUE)){ 418 opts &= ~OPT_OUTQUE; 419 showlist(fiop); 420 } 421 } else if (opts & OPT_FRSTATES) 422 showfrstates(ifrstp, fiop->f_ticks); 423 #ifdef STATETOP 424 else if (opts & OPT_STATETOP) 425 topipstates(saddr, daddr, sport, dport, protocol, 426 #ifdef USE_INET6 427 use_inet6 && use_inet4 ? 0 : use_inet6 && !use_inet4 ? 6 : 4, 428 #else 429 4, 430 #endif 431 #endif 432 refreshtime, topclosed, filter); 433 else if (opts & OPT_AUTHSTATS) 434 showauthstates(frauthstp); 435 else if (opts & OPT_GROUPS) 436 showgroups(fiop); 437 else 438 showstats(fiop, frf); 439 440 return (0); 441 } 442 443 444 /* 445 * Fill in the stats structures from the live kernel, using a combination 446 * of ioctl's and copying directly from kernel memory. 447 */ 448 static void ipfstate_live(char *device, friostat_t **fiopp, 449 ips_stat_t **ipsstpp, ipfrstat_t **ifrstpp, 450 ipf_authstat_t **frauthstpp, u_32_t *frfp) 451 { 452 ipfobj_t ipfo; 453 454 if (checkrev(device) == -1) { 455 fprintf(stderr, "User/kernel version check failed\n"); 456 exit(1); 457 } 458 459 if ((opts & OPT_AUTHSTATS) == 0) { 460 bzero((caddr_t)&ipfo, sizeof(ipfo)); 461 ipfo.ipfo_rev = IPFILTER_VERSION; 462 ipfo.ipfo_type = IPFOBJ_IPFSTAT; 463 ipfo.ipfo_size = sizeof(friostat_t); 464 ipfo.ipfo_ptr = (void *)*fiopp; 465 466 if (ioctl(ipf_fd, SIOCGETFS, &ipfo) == -1) { 467 ipferror(ipf_fd, "ioctl(ipf:SIOCGETFS)"); 468 exit(-1); 469 } 470 471 if (ioctl(ipf_fd, SIOCGETFF, frfp) == -1) 472 ipferror(ipf_fd, "ioctl(SIOCGETFF)"); 473 } 474 475 if ((opts & OPT_IPSTATES) != 0) { 476 477 bzero((caddr_t)&ipfo, sizeof(ipfo)); 478 ipfo.ipfo_rev = IPFILTER_VERSION; 479 ipfo.ipfo_type = IPFOBJ_STATESTAT; 480 ipfo.ipfo_size = sizeof(ips_stat_t); 481 ipfo.ipfo_ptr = (void *)*ipsstpp; 482 483 if ((ioctl(state_fd, SIOCGETFS, &ipfo) == -1)) { 484 ipferror(state_fd, "ioctl(state:SIOCGETFS)"); 485 exit(-1); 486 } 487 if (ioctl(state_fd, SIOCGETLG, &state_logging) == -1) { 488 ipferror(state_fd, "ioctl(state:SIOCGETLG)"); 489 exit(-1); 490 } 491 } 492 493 if ((opts & OPT_FRSTATES) != 0) { 494 bzero((caddr_t)&ipfo, sizeof(ipfo)); 495 ipfo.ipfo_rev = IPFILTER_VERSION; 496 ipfo.ipfo_type = IPFOBJ_FRAGSTAT; 497 ipfo.ipfo_size = sizeof(ipfrstat_t); 498 ipfo.ipfo_ptr = (void *)*ifrstpp; 499 500 if (ioctl(ipf_fd, SIOCGFRST, &ipfo) == -1) { 501 ipferror(ipf_fd, "ioctl(SIOCGFRST)"); 502 exit(-1); 503 } 504 } 505 506 if (opts & OPT_DEBUG) 507 PRINTF("opts %#x name %s\n", opts, device); 508 509 if ((opts & OPT_AUTHSTATS) != 0) { 510 bzero((caddr_t)&ipfo, sizeof(ipfo)); 511 ipfo.ipfo_rev = IPFILTER_VERSION; 512 ipfo.ipfo_type = IPFOBJ_AUTHSTAT; 513 ipfo.ipfo_size = sizeof(ipf_authstat_t); 514 ipfo.ipfo_ptr = (void *)*frauthstpp; 515 516 if (ioctl(auth_fd, SIOCATHST, &ipfo) == -1) { 517 ipferror(auth_fd, "ioctl(SIOCATHST)"); 518 exit(-1); 519 } 520 } 521 } 522 523 524 /* 525 * Build up the stats structures from data held in the "core" memory. 526 * This is mainly useful when looking at data in crash dumps and ioctl's 527 * just won't work any more. 528 */ 529 static void ipfstate_dead( char *kernel, friostat_t **fiopp, 530 ips_stat_t **ipsstpp, ipfrstat_t **ifrstpp, 531 ipf_authstat_t **frauthstpp, u_32_t *frfp) 532 { 533 static ipf_authstat_t frauthst, *frauthstp; 534 static ipftq_t ipstcptab[IPF_TCP_NSTATES]; 535 static ips_stat_t ipsst, *ipsstp; 536 static ipfrstat_t ifrst, *ifrstp; 537 static friostat_t fio, *fiop; 538 int temp; 539 540 void *rules[2][2]; 541 struct nlist deadlist[44] = { 542 { "ipf_auth_stats", 0, 0, 0, 0 }, /* 0 */ 543 { "fae_list", 0, 0, 0, 0 }, 544 { "ipauth", 0, 0, 0, 0 }, 545 { "ipf_auth_list", 0, 0, 0, 0 }, 546 { "ipf_auth_start", 0, 0, 0, 0 }, 547 { "ipf_auth_end", 0, 0, 0, 0 }, /* 5 */ 548 { "ipf_auth_next", 0, 0, 0, 0 }, 549 { "ipf_auth", 0, 0, 0, 0 }, 550 { "ipf_auth_used", 0, 0, 0, 0 }, 551 { "ipf_auth_size", 0, 0, 0, 0 }, 552 { "ipf_auth_defaultage", 0, 0, 0, 0 }, /* 10 */ 553 { "ipf_auth_pkts", 0, 0, 0, 0 }, 554 { "ipf_auth_lock", 0, 0, 0, 0 }, 555 { "frstats", 0, 0, 0, 0 }, 556 { "ips_stats", 0, 0, 0, 0 }, 557 { "ips_num", 0, 0, 0, 0 }, /* 15 */ 558 { "ips_wild", 0, 0, 0, 0 }, 559 { "ips_list", 0, 0, 0, 0 }, 560 { "ips_table", 0, 0, 0, 0 }, 561 { "ipf_state_max", 0, 0, 0, 0 }, 562 { "ipf_state_size", 0, 0, 0, 0 }, /* 20 */ 563 { "ipf_state_doflush", 0, 0, 0, 0 }, 564 { "ipf_state_lock", 0, 0, 0, 0 }, 565 { "ipfr_heads", 0, 0, 0, 0 }, 566 { "ipfr_nattab", 0, 0, 0, 0 }, 567 { "ipfr_stats", 0, 0, 0, 0 }, /* 25 */ 568 { "ipfr_inuse", 0, 0, 0, 0 }, 569 { "ipf_ipfrttl", 0, 0, 0, 0 }, 570 { "ipf_frag_lock", 0, 0, 0, 0 }, 571 { "ipfr_timer_id", 0, 0, 0, 0 }, 572 { "ipf_nat_lock", 0, 0, 0, 0 }, /* 30 */ 573 { "ipf_rules", 0, 0, 0, 0 }, 574 { "ipf_acct", 0, 0, 0, 0 }, 575 { "ipl_frouteok", 0, 0, 0, 0 }, 576 { "ipf_running", 0, 0, 0, 0 }, 577 { "ipf_groups", 0, 0, 0, 0 }, /* 35 */ 578 { "ipf_active", 0, 0, 0, 0 }, 579 { "ipf_pass", 0, 0, 0, 0 }, 580 { "ipf_flags", 0, 0, 0, 0 }, 581 { "ipf_state_logging", 0, 0, 0, 0 }, 582 { "ips_tqtqb", 0, 0, 0, 0 }, /* 40 */ 583 { NULL, 0, 0, 0, 0 } 584 }; 585 586 587 frauthstp = &frauthst; 588 ipsstp = &ipsst; 589 ifrstp = &ifrst; 590 fiop = &fio; 591 592 *frfp = 0; 593 *fiopp = fiop; 594 *ipsstpp = ipsstp; 595 *ifrstpp = ifrstp; 596 *frauthstpp = frauthstp; 597 598 bzero((char *)fiop, sizeof(*fiop)); 599 bzero((char *)ipsstp, sizeof(*ipsstp)); 600 bzero((char *)ifrstp, sizeof(*ifrstp)); 601 bzero((char *)frauthstp, sizeof(*frauthstp)); 602 603 if (nlist(kernel, deadlist) == -1) { 604 fprintf(stderr, "nlist error\n"); 605 return; 606 } 607 608 /* 609 * This is for SIOCGETFF. 610 */ 611 kmemcpy((char *)frfp, (u_long)deadlist[40].n_value, sizeof(*frfp)); 612 613 /* 614 * f_locks is a combination of the lock variable from each part of 615 * ipfilter (state, auth, nat, fragments). 616 */ 617 kmemcpy((char *)fiop, (u_long)deadlist[13].n_value, sizeof(*fiop)); 618 kmemcpy((char *)&fiop->f_locks[0], (u_long)deadlist[22].n_value, 619 sizeof(fiop->f_locks[0])); 620 kmemcpy((char *)&fiop->f_locks[0], (u_long)deadlist[30].n_value, 621 sizeof(fiop->f_locks[1])); 622 kmemcpy((char *)&fiop->f_locks[2], (u_long)deadlist[28].n_value, 623 sizeof(fiop->f_locks[2])); 624 kmemcpy((char *)&fiop->f_locks[3], (u_long)deadlist[12].n_value, 625 sizeof(fiop->f_locks[3])); 626 627 /* 628 * Get pointers to each list of rules (active, inactive, in, out) 629 */ 630 kmemcpy((char *)&rules, (u_long)deadlist[31].n_value, sizeof(rules)); 631 fiop->f_fin[0] = rules[0][0]; 632 fiop->f_fin[1] = rules[0][1]; 633 fiop->f_fout[0] = rules[1][0]; 634 fiop->f_fout[1] = rules[1][1]; 635 636 /* 637 * Now get accounting rules pointers. 638 */ 639 kmemcpy((char *)&rules, (u_long)deadlist[33].n_value, sizeof(rules)); 640 fiop->f_acctin[0] = rules[0][0]; 641 fiop->f_acctin[1] = rules[0][1]; 642 fiop->f_acctout[0] = rules[1][0]; 643 fiop->f_acctout[1] = rules[1][1]; 644 645 /* 646 * A collection of "global" variables used inside the kernel which 647 * are all collected in friostat_t via ioctl. 648 */ 649 kmemcpy((char *)&fiop->f_froute, (u_long)deadlist[33].n_value, 650 sizeof(fiop->f_froute)); 651 kmemcpy((char *)&fiop->f_running, (u_long)deadlist[34].n_value, 652 sizeof(fiop->f_running)); 653 kmemcpy((char *)&fiop->f_groups, (u_long)deadlist[35].n_value, 654 sizeof(fiop->f_groups)); 655 kmemcpy((char *)&fiop->f_active, (u_long)deadlist[36].n_value, 656 sizeof(fiop->f_active)); 657 kmemcpy((char *)&fiop->f_defpass, (u_long)deadlist[37].n_value, 658 sizeof(fiop->f_defpass)); 659 660 /* 661 * Build up the state information stats structure. 662 */ 663 kmemcpy((char *)ipsstp, (u_long)deadlist[14].n_value, sizeof(*ipsstp)); 664 kmemcpy((char *)&temp, (u_long)deadlist[15].n_value, sizeof(temp)); 665 kmemcpy((char *)ipstcptab, (u_long)deadlist[40].n_value, 666 sizeof(ipstcptab)); 667 ipsstp->iss_active = temp; 668 ipsstp->iss_table = (void *)deadlist[18].n_value; 669 ipsstp->iss_list = (void *)deadlist[17].n_value; 670 ipsstp->iss_tcptab = ipstcptab; 671 672 /* 673 * Build up the authentiation information stats structure. 674 */ 675 kmemcpy((char *)frauthstp, (u_long)deadlist[0].n_value, 676 sizeof(*frauthstp)); 677 frauthstp->fas_faelist = (void *)deadlist[1].n_value; 678 679 /* 680 * Build up the fragment information stats structure. 681 */ 682 kmemcpy((char *)ifrstp, (u_long)deadlist[25].n_value, 683 sizeof(*ifrstp)); 684 ifrstp->ifs_table = (void *)deadlist[23].n_value; 685 ifrstp->ifs_nattab = (void *)deadlist[24].n_value; 686 kmemcpy((char *)&ifrstp->ifs_inuse, (u_long)deadlist[26].n_value, 687 sizeof(ifrstp->ifs_inuse)); 688 689 /* 690 * Get logging on/off switches 691 */ 692 kmemcpy((char *)&state_logging, (u_long)deadlist[41].n_value, 693 sizeof(state_logging)); 694 } 695 696 697 static void printside(char *side, ipf_statistics_t *frs) 698 { 699 int i; 700 701 PRINTF("%lu\t%s bad packets\n", frs->fr_bad, side); 702 #ifdef USE_INET6 703 PRINTF("%lu\t%s IPv6 packets\n", frs->fr_ipv6, side); 704 #endif 705 PRINTF("%lu\t%s packets blocked\n", frs->fr_block, side); 706 PRINTF("%lu\t%s packets passed\n", frs->fr_pass, side); 707 PRINTF("%lu\t%s packets not matched\n", frs->fr_nom, side); 708 PRINTF("%lu\t%s packets counted\n", frs->fr_acct, side); 709 PRINTF("%lu\t%s packets short\n", frs->fr_short, side); 710 PRINTF("%lu\t%s packets logged and blocked\n", frs->fr_bpkl, side); 711 PRINTF("%lu\t%s packets logged and passed\n", frs->fr_ppkl, side); 712 PRINTF("%lu\t%s fragment state kept\n", frs->fr_nfr, side); 713 PRINTF("%lu\t%s fragment state lost\n", frs->fr_bnfr, side); 714 PRINTF("%lu\t%s packet state kept\n", frs->fr_ads, side); 715 PRINTF("%lu\t%s packet state lost\n", frs->fr_bads, side); 716 PRINTF("%lu\t%s invalid source\n", frs->fr_v4_badsrc, side); 717 PRINTF("%lu\t%s cache hits\n", frs->fr_chit, side); 718 PRINTF("%lu\t%s cache misses\n", frs->fr_cmiss, side); 719 PRINTF("%lu\t%s bad coalesces\n", frs->fr_badcoalesces, side); 720 PRINTF("%lu\t%s pullups succeeded\n", frs->fr_pull[0], side); 721 PRINTF("%lu\t%s pullups failed\n", frs->fr_pull[1], side); 722 PRINTF("%lu\t%s TCP checksum failures\n", frs->fr_tcpbad, side); 723 for (i = 0; i <= FRB_MAX_VALUE; i++) 724 PRINTF("%lu\t%s block reason %s\n", 725 frs->fr_blocked[i], side, blockreasons[i]); 726 } 727 728 729 /* 730 * Display the kernel stats for packets blocked and passed and other 731 * associated running totals which are kept. 732 */ 733 static void showstats( struct friostat *fp, u_32_t frf) 734 { 735 printside("input", &fp->f_st[0]); 736 printside("output", &fp->f_st[1]); 737 738 PRINTF("%lu\tpackets logged\n", fp->f_log_ok); 739 PRINTF("%lu\tlog failures\n", fp->f_log_fail); 740 PRINTF("%lu\tred-black no memory\n", fp->f_rb_no_mem); 741 PRINTF("%lu\tred-black node maximum\n", fp->f_rb_node_max); 742 PRINTF("%lu\tICMP replies sent\n", fp->f_st[0].fr_ret); 743 PRINTF("%lu\tTCP RSTs sent\n", fp->f_st[1].fr_ret); 744 PRINTF("%lu\tfastroute successes\n", fp->f_froute[0]); 745 PRINTF("%lu\tfastroute failures\n", fp->f_froute[1]); 746 PRINTF("%u\tIPF Ticks\n", fp->f_ticks); 747 748 PRINTF("%x\tPacket log flags set:\n", frf); 749 if (frf & FF_LOGPASS) 750 PRINTF("\tpackets passed through filter\n"); 751 if (frf & FF_LOGBLOCK) 752 PRINTF("\tpackets blocked by filter\n"); 753 if (frf & FF_LOGNOMATCH) 754 PRINTF("\tpackets not matched by filter\n"); 755 if (!frf) 756 PRINTF("\tnone\n"); 757 } 758 759 760 /* 761 * Print out a list of rules from the kernel, starting at the one passed. 762 */ 763 static int 764 printlivelist( struct friostat *fiop, int out, int set, frentry_t *fp, 765 char *group, char *comment) 766 { 767 struct frentry fb; 768 ipfruleiter_t rule; 769 frentry_t zero; 770 frgroup_t *g; 771 ipfobj_t obj; 772 int rules; 773 int num; 774 775 rules = 0; 776 777 rule.iri_inout = out; 778 rule.iri_active = set; 779 rule.iri_rule = &fb; 780 rule.iri_nrules = 1; 781 if (group != NULL) 782 strncpy(rule.iri_group, group, FR_GROUPLEN); 783 else 784 rule.iri_group[0] = '\0'; 785 786 bzero((char *)&zero, sizeof(zero)); 787 788 bzero((char *)&obj, sizeof(obj)); 789 obj.ipfo_rev = IPFILTER_VERSION; 790 obj.ipfo_type = IPFOBJ_IPFITER; 791 obj.ipfo_size = sizeof(rule); 792 obj.ipfo_ptr = &rule; 793 794 while (rule.iri_rule != NULL) { 795 u_long array[1000]; 796 797 memset(array, 0xff, sizeof(array)); 798 fp = (frentry_t *)array; 799 rule.iri_rule = fp; 800 if (ioctl(ipf_fd, SIOCIPFITER, &obj) == -1) { 801 ipferror(ipf_fd, "ioctl(SIOCIPFITER)"); 802 num = IPFGENITER_IPF; 803 (void) ioctl(ipf_fd,SIOCIPFDELTOK, &num); 804 return (rules); 805 } 806 if (bcmp(fp, &zero, sizeof(zero)) == 0) 807 break; 808 if (rule.iri_rule == NULL) 809 break; 810 #ifdef USE_INET6 811 if (use_inet6 != 0 && use_inet4 == 0) { 812 if (fp->fr_family != 0 && fp->fr_family != AF_INET6) 813 continue; 814 } else if (use_inet4 != 0 && use_inet6 == 0) { 815 #endif 816 if (fp->fr_family != 0 && fp->fr_family != AF_INET) 817 continue; 818 #ifdef USE_INET6 819 } else { 820 if (fp->fr_family != 0 && 821 fp->fr_family != AF_INET && fp->fr_family != AF_INET6) 822 continue; 823 } 824 #endif 825 826 if (fp->fr_data != NULL) 827 fp->fr_data = (char *)fp + fp->fr_size; 828 829 rules++; 830 831 if (opts & (OPT_HITS|OPT_DEBUG)) 832 #ifdef USE_QUAD_T 833 PRINTF("%"PRIu64" ", (unsigned long long) fp->fr_hits); 834 #else 835 PRINTF("%lu ", fp->fr_hits); 836 #endif 837 if (opts & (OPT_ACCNT|OPT_DEBUG)) 838 #ifdef USE_QUAD_T 839 PRINTF("%"PRIu64" ", (unsigned long long) fp->fr_bytes); 840 #else 841 PRINTF("%lu ", fp->fr_bytes); 842 #endif 843 if (opts & OPT_SHOWLINENO) 844 PRINTF("@%d ", rules); 845 846 if (fp->fr_die != 0) 847 fp->fr_die -= fiop->f_ticks; 848 849 printfr(fp, ioctl); 850 if (opts & OPT_DEBUG) { 851 binprint(fp, fp->fr_size); 852 if (fp->fr_data != NULL && fp->fr_dsize > 0) 853 binprint(fp->fr_data, fp->fr_dsize); 854 } 855 if (fp->fr_grhead != -1) { 856 for (g = grtop; g != NULL; g = g->fg_next) { 857 if (!strncmp(fp->fr_names + fp->fr_grhead, 858 g->fg_name, 859 FR_GROUPLEN)) 860 break; 861 } 862 if (g == NULL) { 863 g = calloc(1, sizeof(*g)); 864 865 if (g != NULL) { 866 strncpy(g->fg_name, 867 fp->fr_names + fp->fr_grhead, 868 FR_GROUPLEN); 869 if (grtop == NULL) { 870 grtop = g; 871 grtail = g; 872 } else { 873 grtail->fg_next = g; 874 grtail = g; 875 } 876 } 877 } 878 } 879 if (fp->fr_type == FR_T_CALLFUNC) { 880 rules += printlivelist(fiop, out, set, fp->fr_data, 881 group, "# callfunc: "); 882 } 883 } 884 885 num = IPFGENITER_IPF; 886 (void) ioctl(ipf_fd,SIOCIPFDELTOK, &num); 887 888 return (rules); 889 } 890 891 892 static void printdeadlist(friostat_t *fiop, int out, int set, frentry_t *fp, 893 char *group, char *comment) 894 { 895 frgroup_t *grtop, *grtail, *g; 896 struct frentry fb; 897 char *data; 898 u_32_t type; 899 int n; 900 901 fb.fr_next = fp; 902 n = 0; 903 grtop = NULL; 904 grtail = NULL; 905 906 for (n = 1; fp; fp = fb.fr_next, n++) { 907 if (kmemcpy((char *)&fb, (u_long)fb.fr_next, 908 fb.fr_size) == -1) { 909 perror("kmemcpy"); 910 return; 911 } 912 fp = &fb; 913 #ifdef USE_INET6 914 if (use_inet6 != 0 && use_inet4 == 0) { 915 if (fp->fr_family != 0 && fp->fr_family != AF_INET6) 916 continue; 917 } else if (use_inet4 != 0 && use_inet6 == 0) { 918 #endif 919 if (fp->fr_family != 0 && fp->fr_family != AF_INET) 920 continue; 921 #ifdef USE_INET6 922 } else { 923 if (fp->fr_family != 0 && 924 fp->fr_family != AF_INET && fp->fr_family != AF_INET6) 925 continue; 926 } 927 #endif 928 929 data = NULL; 930 type = fb.fr_type & ~FR_T_BUILTIN; 931 if (type == FR_T_IPF || type == FR_T_BPFOPC) { 932 if (fb.fr_dsize) { 933 data = malloc(fb.fr_dsize); 934 935 if (kmemcpy(data, (u_long)fb.fr_data, 936 fb.fr_dsize) == -1) { 937 perror("kmemcpy"); 938 return; 939 } 940 fb.fr_data = data; 941 } 942 } 943 944 if (opts & OPT_HITS) 945 #ifdef USE_QUAD_T 946 PRINTF("%"PRIu64" ", (unsigned long long) fb.fr_hits); 947 #else 948 PRINTF("%lu ", fb.fr_hits); 949 #endif 950 if (opts & OPT_ACCNT) 951 #ifdef USE_QUAD_T 952 PRINTF("%"PRIu64" ", (unsigned long long) fb.fr_bytes); 953 #else 954 PRINTF("%lu ", fb.fr_bytes); 955 #endif 956 if (opts & OPT_SHOWLINENO) 957 PRINTF("@%d ", n); 958 959 printfr(fp, ioctl); 960 if (opts & OPT_DEBUG) { 961 binprint(fp, fp->fr_size); 962 if (fb.fr_data != NULL && fb.fr_dsize > 0) 963 binprint(fb.fr_data, fb.fr_dsize); 964 } 965 if (data != NULL) 966 free(data); 967 if (fb.fr_grhead != -1) { 968 g = calloc(1, sizeof(*g)); 969 970 if (g != NULL) { 971 strncpy(g->fg_name, fb.fr_names + fb.fr_grhead, 972 FR_GROUPLEN); 973 if (grtop == NULL) { 974 grtop = g; 975 grtail = g; 976 } else { 977 grtail->fg_next = g; 978 grtail = g; 979 } 980 } 981 } 982 if (type == FR_T_CALLFUNC) { 983 printdeadlist(fiop, out, set, fb.fr_data, group, 984 "# callfunc: "); 985 } 986 } 987 988 while ((g = grtop) != NULL) { 989 printdeadlist(fiop, out, set, NULL, g->fg_name, comment); 990 grtop = g->fg_next; 991 free(g); 992 } 993 } 994 995 /* 996 * print out all of the asked for rule sets, using the stats struct as 997 * the base from which to get the pointers. 998 */ 999 static void showlist(struct friostat *fiop) 1000 { 1001 struct frentry *fp = NULL; 1002 int i, set; 1003 1004 set = fiop->f_active; 1005 if (opts & OPT_INACTIVE) 1006 set = 1 - set; 1007 if (opts & OPT_ACCNT) { 1008 if (opts & OPT_OUTQUE) { 1009 i = F_ACOUT; 1010 fp = (struct frentry *)fiop->f_acctout[set]; 1011 } else if (opts & OPT_INQUE) { 1012 i = F_ACIN; 1013 fp = (struct frentry *)fiop->f_acctin[set]; 1014 } else { 1015 FPRINTF(stderr, "No -i or -o given with -a\n"); 1016 return; 1017 } 1018 } else { 1019 if (opts & OPT_OUTQUE) { 1020 i = F_OUT; 1021 fp = (struct frentry *)fiop->f_fout[set]; 1022 } else if (opts & OPT_INQUE) { 1023 i = F_IN; 1024 fp = (struct frentry *)fiop->f_fin[set]; 1025 } else 1026 return; 1027 } 1028 if (opts & OPT_DEBUG) 1029 FPRINTF(stderr, "showlist:opts %#x i %d\n", opts, i); 1030 1031 if (opts & OPT_DEBUG) 1032 PRINTF("fp %p set %d\n", fp, set); 1033 1034 if (live_kernel == 1) { 1035 int printed; 1036 1037 printed = printlivelist(fiop, i, set, fp, NULL, NULL); 1038 if (printed == 0) { 1039 FPRINTF(stderr, "# empty list for %s%s\n", 1040 (opts & OPT_INACTIVE) ? "inactive " : "", 1041 filters[i]); 1042 } 1043 } else { 1044 if (!fp) { 1045 FPRINTF(stderr, "# empty list for %s%s\n", 1046 (opts & OPT_INACTIVE) ? "inactive " : "", 1047 filters[i]); 1048 } else { 1049 printdeadlist(fiop, i, set, fp, NULL, NULL); 1050 } 1051 } 1052 } 1053 1054 1055 /* 1056 * Display ipfilter stateful filtering information 1057 */ 1058 static void showipstates(ips_stat_t *ipsp, int *filter) 1059 { 1060 ipstate_t *is; 1061 int i; 1062 1063 /* 1064 * If a list of states hasn't been asked for, only print out stats 1065 */ 1066 if (!(opts & OPT_SHOWLIST)) { 1067 showstatestats(ipsp); 1068 return; 1069 } 1070 1071 if ((state_fields != NULL) && (nohdrfields == 0)) { 1072 for (i = 0; state_fields[i].w_value != 0; i++) { 1073 printfieldhdr(statefields, state_fields + i); 1074 if (state_fields[i + 1].w_value != 0) 1075 printf("\t"); 1076 } 1077 printf("\n"); 1078 } 1079 1080 /* 1081 * Print out all the state information currently held in the kernel. 1082 */ 1083 for (is = ipsp->iss_list; is != NULL; ) { 1084 ipstate_t ips; 1085 1086 is = fetchstate(is, &ips); 1087 1088 if (is == NULL) 1089 break; 1090 1091 is = ips.is_next; 1092 if ((filter != NULL) && 1093 (state_matcharray(&ips, filter) == 0)) { 1094 continue; 1095 } 1096 if (state_fields != NULL) { 1097 for (i = 0; state_fields[i].w_value != 0; i++) { 1098 printstatefield(&ips, state_fields[i].w_value); 1099 if (state_fields[i + 1].w_value != 0) 1100 printf("\t"); 1101 } 1102 printf("\n"); 1103 } else { 1104 printstate(&ips, opts, ipsp->iss_ticks); 1105 } 1106 } 1107 } 1108 1109 1110 static void showstatestats(ips_stat_t *ipsp) 1111 { 1112 int minlen, maxlen, totallen; 1113 ipftable_t table; 1114 u_int *buckets; 1115 ipfobj_t obj; 1116 int i, sz; 1117 1118 /* 1119 * If a list of states hasn't been asked for, only print out stats 1120 */ 1121 1122 sz = sizeof(*buckets) * ipsp->iss_state_size; 1123 buckets = (u_int *)malloc(sz); 1124 1125 obj.ipfo_rev = IPFILTER_VERSION; 1126 obj.ipfo_type = IPFOBJ_GTABLE; 1127 obj.ipfo_size = sizeof(table); 1128 obj.ipfo_ptr = &table; 1129 1130 table.ita_type = IPFTABLE_BUCKETS; 1131 table.ita_table = buckets; 1132 1133 if (live_kernel == 1) { 1134 if (ioctl(state_fd, SIOCGTABL, &obj) != 0) { 1135 free(buckets); 1136 return; 1137 } 1138 } else { 1139 if (kmemcpy((char *)buckets, 1140 (u_long)ipsp->iss_bucketlen, sz)) { 1141 free(buckets); 1142 return; 1143 } 1144 } 1145 1146 PRINTF("%u\tactive state table entries\n",ipsp->iss_active); 1147 PRINTF("%lu\tadd bad\n", ipsp->iss_add_bad); 1148 PRINTF("%lu\tadd duplicate\n", ipsp->iss_add_dup); 1149 PRINTF("%lu\tadd locked\n", ipsp->iss_add_locked); 1150 PRINTF("%lu\tadd oow\n", ipsp->iss_add_oow); 1151 PRINTF("%lu\tbucket full\n", ipsp->iss_bucket_full); 1152 PRINTF("%lu\tcheck bad\n", ipsp->iss_check_bad); 1153 PRINTF("%lu\tcheck miss\n", ipsp->iss_check_miss); 1154 PRINTF("%lu\tcheck nattag\n", ipsp->iss_check_nattag); 1155 PRINTF("%lu\tclone nomem\n", ipsp->iss_clone_nomem); 1156 PRINTF("%lu\tcheck notag\n", ipsp->iss_check_notag); 1157 PRINTF("%lu\tcheck success\n", ipsp->iss_hits); 1158 PRINTF("%lu\tcloned\n", ipsp->iss_cloned); 1159 PRINTF("%lu\texpired\n", ipsp->iss_expire); 1160 PRINTF("%lu\tflush all\n", ipsp->iss_flush_all); 1161 PRINTF("%lu\tflush closing\n", ipsp->iss_flush_closing); 1162 PRINTF("%lu\tflush queue\n", ipsp->iss_flush_queue); 1163 PRINTF("%lu\tflush state\n", ipsp->iss_flush_state); 1164 PRINTF("%lu\tflush timeout\n", ipsp->iss_flush_timeout); 1165 PRINTF("%u\thash buckets in use\n", ipsp->iss_inuse); 1166 PRINTF("%lu\tICMP bad\n", ipsp->iss_icmp_bad); 1167 PRINTF("%lu\tICMP banned\n", ipsp->iss_icmp_banned); 1168 PRINTF("%lu\tICMP errors\n", ipsp->iss_icmp_icmperr); 1169 PRINTF("%lu\tICMP head block\n", ipsp->iss_icmp_headblock); 1170 PRINTF("%lu\tICMP hits\n", ipsp->iss_icmp_hits); 1171 PRINTF("%lu\tICMP not query\n", ipsp->iss_icmp_notquery); 1172 PRINTF("%lu\tICMP short\n", ipsp->iss_icmp_short); 1173 PRINTF("%lu\tICMP too many\n", ipsp->iss_icmp_toomany); 1174 PRINTF("%lu\tICMPv6 errors\n", ipsp->iss_icmp6_icmperr); 1175 PRINTF("%lu\tICMPv6 miss\n", ipsp->iss_icmp6_miss); 1176 PRINTF("%lu\tICMPv6 not info\n", ipsp->iss_icmp6_notinfo); 1177 PRINTF("%lu\tICMPv6 not query\n", ipsp->iss_icmp6_notquery); 1178 PRINTF("%lu\tlog fail\n", ipsp->iss_log_fail); 1179 PRINTF("%lu\tlog ok\n", ipsp->iss_log_ok); 1180 PRINTF("%lu\tlookup interface mismatch\n", ipsp->iss_lookup_badifp); 1181 PRINTF("%lu\tlookup mask mismatch\n", ipsp->iss_miss_mask); 1182 PRINTF("%lu\tlookup port mismatch\n", ipsp->iss_lookup_badport); 1183 PRINTF("%lu\tlookup miss\n", ipsp->iss_lookup_miss); 1184 PRINTF("%lu\tmaximum rule references\n", ipsp->iss_max_ref); 1185 PRINTF("%lu\tmaximum hosts per rule\n", ipsp->iss_max_track); 1186 PRINTF("%lu\tno memory\n", ipsp->iss_nomem); 1187 PRINTF("%lu\tout of window\n", ipsp->iss_oow); 1188 PRINTF("%lu\torphans\n", ipsp->iss_orphan); 1189 PRINTF("%lu\tscan block\n", ipsp->iss_scan_block); 1190 PRINTF("%lu\tstate table maximum reached\n", ipsp->iss_max); 1191 PRINTF("%lu\tTCP closing\n", ipsp->iss_tcp_closing); 1192 PRINTF("%lu\tTCP OOW\n", ipsp->iss_tcp_oow); 1193 PRINTF("%lu\tTCP RST add\n", ipsp->iss_tcp_rstadd); 1194 PRINTF("%lu\tTCP too small\n", ipsp->iss_tcp_toosmall); 1195 PRINTF("%lu\tTCP bad options\n", ipsp->iss_tcp_badopt); 1196 PRINTF("%lu\tTCP removed\n", ipsp->iss_fin); 1197 PRINTF("%lu\tTCP FSM\n", ipsp->iss_tcp_fsm); 1198 PRINTF("%lu\tTCP strict\n", ipsp->iss_tcp_strict); 1199 PRINTF("%lu\tTCP wild\n", ipsp->iss_wild); 1200 PRINTF("%lu\tMicrosoft Windows SACK\n", ipsp->iss_winsack); 1201 1202 PRINTF("State logging %sabled\n", state_logging ? "en" : "dis"); 1203 1204 PRINTF("IP states added:\n"); 1205 for (i = 0; i < 256; i++) { 1206 if (ipsp->iss_proto[i] != 0) { 1207 struct protoent *proto; 1208 1209 proto = getprotobynumber(i); 1210 PRINTF("%lu", ipsp->iss_proto[i]); 1211 if (proto != NULL) 1212 PRINTF("\t%s\n", proto->p_name); 1213 else 1214 PRINTF("\t%d\n", i); 1215 } 1216 } 1217 1218 PRINTF("\nState table bucket statistics:\n"); 1219 PRINTF("%u\tin use\n", ipsp->iss_inuse); 1220 1221 minlen = ipsp->iss_max; 1222 totallen = 0; 1223 maxlen = 0; 1224 1225 for (i = 0; i < ipsp->iss_state_size; i++) { 1226 if (buckets[i] > maxlen) 1227 maxlen = buckets[i]; 1228 if (buckets[i] < minlen) 1229 minlen = buckets[i]; 1230 totallen += buckets[i]; 1231 } 1232 1233 PRINTF("%d\thash efficiency\n", 1234 totallen ? ipsp->iss_inuse * 100 / totallen : 0); 1235 PRINTF("%2.2f%%\tbucket usage\n%u\tminimal length\n", 1236 ((float)ipsp->iss_inuse / ipsp->iss_state_size) * 100.0, 1237 minlen); 1238 PRINTF("%u\tmaximal length\n%.3f\taverage length\n", 1239 maxlen, 1240 ipsp->iss_inuse ? (float) totallen/ ipsp->iss_inuse : 1241 0.0); 1242 1243 #define ENTRIES_PER_LINE 5 1244 1245 if (opts & OPT_VERBOSE) { 1246 PRINTF("\nCurrent bucket sizes :\n"); 1247 for (i = 0; i < ipsp->iss_state_size; i++) { 1248 if ((i % ENTRIES_PER_LINE) == 0) 1249 PRINTF("\t"); 1250 PRINTF("%4d -> %4u", i, buckets[i]); 1251 if ((i % ENTRIES_PER_LINE) == 1252 (ENTRIES_PER_LINE - 1)) 1253 PRINTF("\n"); 1254 else 1255 PRINTF(" "); 1256 } 1257 PRINTF("\n"); 1258 } 1259 PRINTF("\n"); 1260 1261 free(buckets); 1262 1263 if (live_kernel == 1) { 1264 showtqtable_live(state_fd); 1265 } else { 1266 printtqtable(ipsp->iss_tcptab); 1267 } 1268 } 1269 1270 1271 #ifdef STATETOP 1272 static int handle_resize = 0, handle_break = 0; 1273 1274 static void topipstates(i6addr_t saddr, i6addr_t daddr, int sport, int dport, 1275 int protocol, int ver, int refreshtime, int topclosed, int *filter) 1276 { 1277 char str1[STSTRSIZE], str2[STSTRSIZE], str3[STSTRSIZE], str4[STSTRSIZE]; 1278 int maxtsentries = 0, reverse = 0, sorting = STSORT_DEFAULT; 1279 int i, j, winy, tsentry, maxx, maxy, redraw = 0, ret = 0; 1280 int len, srclen, dstlen, forward = 1, c = 0; 1281 ips_stat_t ipsst, *ipsstp = &ipsst; 1282 int token_type = IPFGENITER_STATE; 1283 statetop_t *tstable = NULL, *tp; 1284 const char *errstr = ""; 1285 ipstate_t ips; 1286 ipfobj_t ipfo; 1287 struct timeval selecttimeout; 1288 char hostnm[HOSTNMLEN]; 1289 struct protoent *proto; 1290 fd_set readfd; 1291 time_t t; 1292 1293 /* install signal handlers */ 1294 signal(SIGINT, sig_break); 1295 signal(SIGQUIT, sig_break); 1296 signal(SIGTERM, sig_break); 1297 signal(SIGWINCH, sig_resize); 1298 1299 /* init ncurses stuff */ 1300 initscr(); 1301 cbreak(); 1302 noecho(); 1303 curs_set(0); 1304 timeout(0); 1305 getmaxyx(stdscr, maxy, maxx); 1306 1307 /* init hostname */ 1308 gethostname(hostnm, sizeof(hostnm) - 1); 1309 hostnm[sizeof(hostnm) - 1] = '\0'; 1310 1311 /* init ipfobj_t stuff */ 1312 bzero((caddr_t)&ipfo, sizeof(ipfo)); 1313 ipfo.ipfo_rev = IPFILTER_VERSION; 1314 ipfo.ipfo_type = IPFOBJ_STATESTAT; 1315 ipfo.ipfo_size = sizeof(*ipsstp); 1316 ipfo.ipfo_ptr = (void *)ipsstp; 1317 1318 /* repeat until user aborts */ 1319 while ( 1 ) { 1320 1321 /* get state table */ 1322 bzero((char *)&ipsst, sizeof(ipsst)); 1323 if ((ioctl(state_fd, SIOCGETFS, &ipfo) == -1)) { 1324 errstr = "ioctl(SIOCGETFS)"; 1325 ret = -1; 1326 goto out; 1327 } 1328 1329 /* clear the history */ 1330 tsentry = -1; 1331 1332 /* reset max str len */ 1333 srclen = dstlen = 0; 1334 1335 /* read the state table and store in tstable */ 1336 for (; ipsstp->iss_list; ipsstp->iss_list = ips.is_next) { 1337 1338 ipsstp->iss_list = fetchstate(ipsstp->iss_list, &ips); 1339 if (ipsstp->iss_list == NULL) 1340 break; 1341 1342 if (ver != 0 && ips.is_v != ver) 1343 continue; 1344 1345 if ((filter != NULL) && 1346 (state_matcharray(&ips, filter) == 0)) 1347 continue; 1348 1349 /* check v4 src/dest addresses */ 1350 if (ips.is_v == 4) { 1351 if ((saddr.in4.s_addr != INADDR_ANY && 1352 saddr.in4.s_addr != ips.is_saddr) || 1353 (daddr.in4.s_addr != INADDR_ANY && 1354 daddr.in4.s_addr != ips.is_daddr)) 1355 continue; 1356 } 1357 #ifdef USE_INET6 1358 /* check v6 src/dest addresses */ 1359 if (ips.is_v == 6) { 1360 if ((IP6_NEQ(&saddr, &in6addr_any) && 1361 IP6_NEQ(&saddr, &ips.is_src)) || 1362 (IP6_NEQ(&daddr, &in6addr_any) && 1363 IP6_NEQ(&daddr, &ips.is_dst))) 1364 continue; 1365 } 1366 #endif 1367 /* check protocol */ 1368 if (protocol > 0 && protocol != ips.is_p) 1369 continue; 1370 1371 /* check ports if protocol is TCP or UDP */ 1372 if (((ips.is_p == IPPROTO_TCP) || 1373 (ips.is_p == IPPROTO_UDP)) && 1374 (((sport > 0) && (htons(sport) != ips.is_sport)) || 1375 ((dport > 0) && (htons(dport) != ips.is_dport)))) 1376 continue; 1377 1378 /* show closed TCP sessions ? */ 1379 if ((topclosed == 0) && (ips.is_p == IPPROTO_TCP) && 1380 (ips.is_state[0] >= IPF_TCPS_LAST_ACK) && 1381 (ips.is_state[1] >= IPF_TCPS_LAST_ACK)) 1382 continue; 1383 1384 /* 1385 * if necessary make room for this state 1386 * entry 1387 */ 1388 tsentry++; 1389 if (!maxtsentries || tsentry == maxtsentries) { 1390 maxtsentries += STGROWSIZE; 1391 tstable = reallocarray(tstable, maxtsentries, 1392 sizeof(statetop_t)); 1393 if (tstable == NULL) { 1394 perror("realloc"); 1395 exit(-1); 1396 } 1397 } 1398 1399 /* get max src/dest address string length */ 1400 len = strlen(getip(ips.is_v, &ips.is_src)); 1401 if (srclen < len) 1402 srclen = len; 1403 len = strlen(getip(ips.is_v, &ips.is_dst)); 1404 if (dstlen < len) 1405 dstlen = len; 1406 1407 /* fill structure */ 1408 tp = tstable + tsentry; 1409 tp->st_src = ips.is_src; 1410 tp->st_dst = ips.is_dst; 1411 tp->st_p = ips.is_p; 1412 tp->st_v = ips.is_v; 1413 tp->st_state[0] = ips.is_state[0]; 1414 tp->st_state[1] = ips.is_state[1]; 1415 if (forward) { 1416 tp->st_pkts = ips.is_pkts[0]+ips.is_pkts[1]; 1417 tp->st_bytes = ips.is_bytes[0]+ips.is_bytes[1]; 1418 } else { 1419 tp->st_pkts = ips.is_pkts[2]+ips.is_pkts[3]; 1420 tp->st_bytes = ips.is_bytes[2]+ips.is_bytes[3]; 1421 } 1422 tp->st_age = ips.is_die - ipsstp->iss_ticks; 1423 if ((ips.is_p == IPPROTO_TCP) || 1424 (ips.is_p == IPPROTO_UDP)) { 1425 tp->st_sport = ips.is_sport; 1426 tp->st_dport = ips.is_dport; 1427 } 1428 } 1429 1430 (void) ioctl(state_fd, SIOCIPFDELTOK, &token_type); 1431 1432 /* sort the array */ 1433 if (tsentry != -1) { 1434 switch (sorting) 1435 { 1436 case STSORT_PR: 1437 qsort(tstable, tsentry + 1, 1438 sizeof(statetop_t), sort_p); 1439 break; 1440 case STSORT_PKTS: 1441 qsort(tstable, tsentry + 1, 1442 sizeof(statetop_t), sort_pkts); 1443 break; 1444 case STSORT_BYTES: 1445 qsort(tstable, tsentry + 1, 1446 sizeof(statetop_t), sort_bytes); 1447 break; 1448 case STSORT_TTL: 1449 qsort(tstable, tsentry + 1, 1450 sizeof(statetop_t), sort_ttl); 1451 break; 1452 case STSORT_SRCIP: 1453 qsort(tstable, tsentry + 1, 1454 sizeof(statetop_t), sort_srcip); 1455 break; 1456 case STSORT_SRCPT: 1457 qsort(tstable, tsentry +1, 1458 sizeof(statetop_t), sort_srcpt); 1459 break; 1460 case STSORT_DSTIP: 1461 qsort(tstable, tsentry + 1, 1462 sizeof(statetop_t), sort_dstip); 1463 break; 1464 case STSORT_DSTPT: 1465 qsort(tstable, tsentry + 1, 1466 sizeof(statetop_t), sort_dstpt); 1467 break; 1468 default: 1469 break; 1470 } 1471 } 1472 1473 /* handle window resizes */ 1474 if (handle_resize) { 1475 endwin(); 1476 initscr(); 1477 cbreak(); 1478 noecho(); 1479 curs_set(0); 1480 timeout(0); 1481 getmaxyx(stdscr, maxy, maxx); 1482 redraw = 1; 1483 handle_resize = 0; 1484 } 1485 1486 /* stop program? */ 1487 if (handle_break) 1488 break; 1489 1490 /* print title */ 1491 erase(); 1492 attron(A_BOLD); 1493 winy = 0; 1494 move(winy,0); 1495 snprintf(str1, sizeof(str1), "%s - %s - state top", hostnm, IPL_VERSION); 1496 for (j = 0 ; j < (maxx - 8 - strlen(str1)) / 2; j++) 1497 printw(" "); 1498 printw("%s", str1); 1499 attroff(A_BOLD); 1500 1501 /* just for fun add a clock */ 1502 move(winy, maxx - 8); 1503 t = time(NULL); 1504 strftime(str1, 80, "%T", localtime(&t)); 1505 printw("%s\n", str1); 1506 1507 /* 1508 * print the display filters, this is placed in the loop, 1509 * because someday I might add code for changing these 1510 * while the programming is running :-) 1511 */ 1512 if (sport >= 0) 1513 snprintf(str1, sizeof(str1), "%s,%d", getip(ver, &saddr), sport); 1514 else 1515 snprintf(str1, sizeof(str1), "%s", getip(ver, &saddr)); 1516 1517 if (dport >= 0) 1518 snprintf(str2, sizeof(str2), "%s,%d", getip(ver, &daddr), dport); 1519 else 1520 snprintf(str2, sizeof(str2), "%s", getip(ver, &daddr)); 1521 1522 if (protocol < 0) 1523 strcpy(str3, "any"); 1524 else if ((proto = getprotobynumber(protocol)) != NULL) 1525 snprintf(str3, sizeof(str3), "%s", proto->p_name); 1526 else 1527 snprintf(str3, sizeof(str3), "%d", protocol); 1528 1529 switch (sorting) 1530 { 1531 case STSORT_PR: 1532 snprintf(str4, sizeof(str4), "proto"); 1533 break; 1534 case STSORT_PKTS: 1535 snprintf(str4, sizeof(str4), "# pkts"); 1536 break; 1537 case STSORT_BYTES: 1538 snprintf(str4, sizeof(str4), "# bytes"); 1539 break; 1540 case STSORT_TTL: 1541 snprintf(str4, sizeof(str4), "ttl"); 1542 break; 1543 case STSORT_SRCIP: 1544 snprintf(str4, sizeof(str4), "src ip"); 1545 break; 1546 case STSORT_SRCPT: 1547 snprintf(str4, sizeof(str4), "src port"); 1548 break; 1549 case STSORT_DSTIP: 1550 snprintf(str4, sizeof(str4), "dest ip"); 1551 break; 1552 case STSORT_DSTPT: 1553 snprintf(str4, sizeof(str4), "dest port"); 1554 break; 1555 default: 1556 snprintf(str4, sizeof(str4), "unknown"); 1557 break; 1558 } 1559 1560 if (reverse) 1561 strcat(str4, " (reverse)"); 1562 1563 winy += 2; 1564 move(winy,0); 1565 printw("Src: %s, Dest: %s, Proto: %s, Sorted by: %s\n\n", 1566 str1, str2, str3, str4); 1567 1568 /* 1569 * For an IPv4 IP address we need at most 15 characters, 1570 * 4 tuples of 3 digits, separated by 3 dots. Enforce this 1571 * length, so the columns do not change positions based 1572 * on the size of the IP address. This length makes the 1573 * output fit in a 80 column terminal. 1574 * We are lacking a good solution for IPv6 addresses (that 1575 * can be longer that 15 characters), so we do not enforce 1576 * a maximum on the IP field size. 1577 */ 1578 if (srclen < 15) 1579 srclen = 15; 1580 if (dstlen < 15) 1581 dstlen = 15; 1582 1583 /* print column description */ 1584 winy += 2; 1585 move(winy,0); 1586 attron(A_BOLD); 1587 printw("%-*s %-*s %3s %4s %7s %9s %9s\n", 1588 srclen + 6, "Source IP", dstlen + 6, "Destination IP", 1589 "ST", "PR", "#pkts", "#bytes", "ttl"); 1590 attroff(A_BOLD); 1591 1592 /* print all the entries */ 1593 tp = tstable; 1594 if (reverse) 1595 tp += tsentry; 1596 1597 if (tsentry > maxy - 6) 1598 tsentry = maxy - 6; 1599 for (i = 0; i <= tsentry; i++) { 1600 /* print src/dest and port */ 1601 if ((tp->st_p == IPPROTO_TCP) || 1602 (tp->st_p == IPPROTO_UDP)) { 1603 snprintf(str1, sizeof(str1), "%s,%hu", 1604 getip(tp->st_v, &tp->st_src), 1605 ntohs(tp->st_sport)); 1606 snprintf(str2, sizeof(str2), "%s,%hu", 1607 getip(tp->st_v, &tp->st_dst), 1608 ntohs(tp->st_dport)); 1609 } else { 1610 snprintf(str1, sizeof(str1), "%s", getip(tp->st_v, 1611 &tp->st_src)); 1612 snprintf(str2, sizeof(str2), "%s", getip(tp->st_v, 1613 &tp->st_dst)); 1614 } 1615 winy++; 1616 move(winy, 0); 1617 printw("%-*s %-*s", srclen + 6, str1, dstlen + 6, str2); 1618 1619 /* print state */ 1620 snprintf(str1, sizeof(str1), "%X/%X", tp->st_state[0], 1621 tp->st_state[1]); 1622 printw(" %3s", str1); 1623 1624 /* print protocol */ 1625 proto = getprotobynumber(tp->st_p); 1626 if (proto) { 1627 strncpy(str1, proto->p_name, 4); 1628 str1[4] = '\0'; 1629 } else { 1630 snprintf(str1, sizeof(str1), "%d", tp->st_p); 1631 } 1632 /* just print icmp for IPv6-ICMP */ 1633 if (tp->st_p == IPPROTO_ICMPV6) 1634 strcpy(str1, "icmp"); 1635 printw(" %4s", str1); 1636 1637 /* print #pkt/#bytes */ 1638 #ifdef USE_QUAD_T 1639 printw(" %7qu %9qu", (unsigned long long) tp->st_pkts, 1640 (unsigned long long) tp->st_bytes); 1641 #else 1642 printw(" %7lu %9lu", tp->st_pkts, tp->st_bytes); 1643 #endif 1644 printw(" %9s", ttl_to_string(tp->st_age)); 1645 1646 if (reverse) 1647 tp--; 1648 else 1649 tp++; 1650 } 1651 1652 /* screen data structure is filled, now update the screen */ 1653 if (redraw) 1654 clearok(stdscr,1); 1655 1656 if (refresh() == ERR) 1657 break; 1658 if (redraw) { 1659 clearok(stdscr,0); 1660 redraw = 0; 1661 } 1662 1663 /* wait for key press or a 1 second time out period */ 1664 selecttimeout.tv_sec = refreshtime; 1665 selecttimeout.tv_usec = 0; 1666 FD_ZERO(&readfd); 1667 FD_SET(0, &readfd); 1668 select(1, &readfd, NULL, NULL, &selecttimeout); 1669 1670 /* if key pressed, read all waiting keys */ 1671 if (FD_ISSET(0, &readfd)) { 1672 c = wgetch(stdscr); 1673 if (c == ERR) 1674 continue; 1675 1676 if (ISALPHA(c) && ISUPPER(c)) 1677 c = TOLOWER(c); 1678 if (c == 'l') { 1679 redraw = 1; 1680 } else if (c == 'q') { 1681 break; 1682 } else if (c == 'r') { 1683 reverse = !reverse; 1684 } else if (c == 'b') { 1685 forward = 0; 1686 } else if (c == 'f') { 1687 forward = 1; 1688 } else if (c == 's') { 1689 if (++sorting > STSORT_MAX) 1690 sorting = 0; 1691 } 1692 } 1693 } /* while */ 1694 1695 out: 1696 printw("\n"); 1697 curs_set(1); 1698 /* nocbreak(); XXX - endwin() should make this redundant */ 1699 endwin(); 1700 1701 free(tstable); 1702 if (ret != 0) 1703 perror(errstr); 1704 } 1705 #endif 1706 1707 1708 /* 1709 * Show fragment cache information that's held in the kernel. 1710 */ 1711 static void showfrstates(ipfrstat_t *ifsp, u_long ticks) 1712 { 1713 struct ipfr *ipfrtab[IPFT_SIZE], ifr; 1714 int i; 1715 1716 /* 1717 * print out the numeric statistics 1718 */ 1719 PRINTF("IP fragment states:\n%lu\tnew\n%lu\texpired\n%lu\thits\n", 1720 ifsp->ifs_new, ifsp->ifs_expire, ifsp->ifs_hits); 1721 PRINTF("%lu\tretrans\n%lu\ttoo short\n", 1722 ifsp->ifs_retrans0, ifsp->ifs_short); 1723 PRINTF("%lu\tno memory\n%lu\talready exist\n", 1724 ifsp->ifs_nomem, ifsp->ifs_exists); 1725 PRINTF("%lu\tinuse\n", ifsp->ifs_inuse); 1726 PRINTF("\n"); 1727 1728 if (live_kernel == 0) { 1729 if (kmemcpy((char *)ipfrtab, (u_long)ifsp->ifs_table, 1730 sizeof(ipfrtab))) 1731 return; 1732 } 1733 1734 /* 1735 * Print out the contents (if any) of the fragment cache table. 1736 */ 1737 if (live_kernel == 1) { 1738 do { 1739 if (fetchfrag(ipf_fd, IPFGENITER_FRAG, &ifr) != 0) 1740 break; 1741 if (ifr.ipfr_ifp == NULL) 1742 break; 1743 ifr.ipfr_ttl -= ticks; 1744 printfraginfo("", &ifr); 1745 } while (ifr.ipfr_next != NULL); 1746 } else { 1747 for (i = 0; i < IPFT_SIZE; i++) 1748 while (ipfrtab[i] != NULL) { 1749 if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i], 1750 sizeof(ifr)) == -1) 1751 break; 1752 printfraginfo("", &ifr); 1753 ipfrtab[i] = ifr.ipfr_next; 1754 } 1755 } 1756 /* 1757 * Print out the contents (if any) of the NAT fragment cache table. 1758 */ 1759 1760 if (live_kernel == 0) { 1761 if (kmemcpy((char *)ipfrtab, (u_long)ifsp->ifs_nattab, 1762 sizeof(ipfrtab))) 1763 return; 1764 } 1765 1766 if (live_kernel == 1) { 1767 do { 1768 if (fetchfrag(nat_fd, IPFGENITER_NATFRAG, &ifr) != 0) 1769 break; 1770 if (ifr.ipfr_ifp == NULL) 1771 break; 1772 ifr.ipfr_ttl -= ticks; 1773 printfraginfo("NAT: ", &ifr); 1774 } while (ifr.ipfr_next != NULL); 1775 } else { 1776 for (i = 0; i < IPFT_SIZE; i++) 1777 while (ipfrtab[i] != NULL) { 1778 if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i], 1779 sizeof(ifr)) == -1) 1780 break; 1781 printfraginfo("NAT: ", &ifr); 1782 ipfrtab[i] = ifr.ipfr_next; 1783 } 1784 } 1785 } 1786 1787 1788 /* 1789 * Show stats on how auth within IPFilter has been used 1790 */ 1791 static void showauthstates(ipf_authstat_t *asp) 1792 { 1793 frauthent_t *frap, fra; 1794 ipfgeniter_t auth; 1795 ipfobj_t obj; 1796 1797 obj.ipfo_rev = IPFILTER_VERSION; 1798 obj.ipfo_type = IPFOBJ_GENITER; 1799 obj.ipfo_size = sizeof(auth); 1800 obj.ipfo_ptr = &auth; 1801 1802 auth.igi_type = IPFGENITER_AUTH; 1803 auth.igi_nitems = 1; 1804 auth.igi_data = &fra; 1805 1806 #ifdef USE_QUAD_T 1807 printf("Authorisation hits: %"PRIu64"\tmisses %"PRIu64"\n", 1808 (unsigned long long) asp->fas_hits, 1809 (unsigned long long) asp->fas_miss); 1810 #else 1811 printf("Authorisation hits: %ld\tmisses %ld\n", asp->fas_hits, 1812 asp->fas_miss); 1813 #endif 1814 printf("nospace %ld\nadded %ld\nsendfail %ld\nsendok %ld\n", 1815 asp->fas_nospace, asp->fas_added, asp->fas_sendfail, 1816 asp->fas_sendok); 1817 printf("queok %ld\nquefail %ld\nexpire %ld\n", 1818 asp->fas_queok, asp->fas_quefail, asp->fas_expire); 1819 1820 frap = asp->fas_faelist; 1821 while (frap) { 1822 if (live_kernel == 1) { 1823 if (ioctl(auth_fd, SIOCGENITER, &obj)) 1824 break; 1825 } else { 1826 if (kmemcpy((char *)&fra, (u_long)frap, 1827 sizeof(fra)) == -1) 1828 break; 1829 } 1830 printf("age %ld\t", fra.fae_age); 1831 printfr(&fra.fae_fr, ioctl); 1832 frap = fra.fae_next; 1833 } 1834 } 1835 1836 1837 /* 1838 * Display groups used for each of filter rules, accounting rules and 1839 * authentication, separately. 1840 */ 1841 static void showgroups(struct friostat *fiop) 1842 { 1843 static char *gnames[3] = { "Filter", "Accounting", "Authentication" }; 1844 static int gnums[3] = { IPL_LOGIPF, IPL_LOGCOUNT, IPL_LOGAUTH }; 1845 frgroup_t *fp, grp; 1846 int on, off, i; 1847 1848 on = fiop->f_active; 1849 off = 1 - on; 1850 1851 for (i = 0; i < 3; i++) { 1852 printf("%s groups (active):\n", gnames[i]); 1853 for (fp = fiop->f_groups[gnums[i]][on]; fp != NULL; 1854 fp = grp.fg_next) 1855 if (kmemcpy((char *)&grp, (u_long)fp, sizeof(grp))) 1856 break; 1857 else 1858 printf("%s\n", grp.fg_name); 1859 printf("%s groups (inactive):\n", gnames[i]); 1860 for (fp = fiop->f_groups[gnums[i]][off]; fp != NULL; 1861 fp = grp.fg_next) 1862 if (kmemcpy((char *)&grp, (u_long)fp, sizeof(grp))) 1863 break; 1864 else 1865 printf("%s\n", grp.fg_name); 1866 } 1867 } 1868 1869 1870 static void parse_ipportstr(const char *argument, i6addr_t *ip, int *port) 1871 { 1872 char *s, *comma; 1873 int ok = 0; 1874 1875 /* make working copy of argument, Theoretically you must be able 1876 * to write to optarg, but that seems very ugly to me.... 1877 */ 1878 s = strdup(argument); 1879 if (s == NULL) 1880 return; 1881 1882 /* get port */ 1883 if ((comma = strchr(s, ',')) != NULL) { 1884 if (!strcasecmp(comma + 1, "any")) { 1885 *port = -1; 1886 } else if (!sscanf(comma + 1, "%d", port) || 1887 (*port < 0) || (*port > 65535)) { 1888 fprintf(stderr, "Invalid port specification in %s\n", 1889 argument); 1890 free(s); 1891 exit(-2); 1892 } 1893 *comma = '\0'; 1894 } 1895 1896 1897 /* get ip address */ 1898 if (!strcasecmp(s, "any")) { 1899 ip->in4.s_addr = INADDR_ANY; 1900 ok = 1; 1901 #ifdef USE_INET6 1902 ip->in6 = in6addr_any; 1903 } else if (use_inet6 && !use_inet4 && inet_pton(AF_INET6, s, &ip->in6)) { 1904 ok = 1; 1905 #endif 1906 } else if (inet_aton(s, &ip->in4)) 1907 ok = 1; 1908 1909 if (ok == 0) { 1910 fprintf(stderr, "Invalid IP address: %s\n", s); 1911 free(s); 1912 exit(-2); 1913 } 1914 1915 /* free allocated memory */ 1916 free(s); 1917 } 1918 1919 1920 #ifdef STATETOP 1921 static void sig_resize(int s) 1922 { 1923 handle_resize = 1; 1924 } 1925 1926 static void sig_break(int s) 1927 { 1928 handle_break = 1; 1929 } 1930 1931 static char *getip(int v, i6addr_t *addr) 1932 { 1933 #ifdef USE_INET6 1934 static char hostbuf[MAXHOSTNAMELEN+1]; 1935 #endif 1936 1937 if (v == 0) 1938 return ("any"); 1939 1940 if (v == 4) 1941 return (inet_ntoa(addr->in4)); 1942 1943 #ifdef USE_INET6 1944 (void) inet_ntop(AF_INET6, &addr->in6, hostbuf, sizeof(hostbuf) - 1); 1945 hostbuf[MAXHOSTNAMELEN] = '\0'; 1946 return (hostbuf); 1947 #else 1948 return ("IPv6"); 1949 #endif 1950 } 1951 1952 1953 static char *ttl_to_string(long int ttl) 1954 { 1955 static char ttlbuf[STSTRSIZE]; 1956 int hours, minutes, seconds; 1957 1958 /* ttl is in half seconds */ 1959 ttl /= 2; 1960 1961 hours = ttl / 3600; 1962 ttl = ttl % 3600; 1963 minutes = ttl / 60; 1964 seconds = ttl % 60; 1965 1966 if (hours > 0) 1967 snprintf(ttlbuf, sizeof(ttlbuf), "%2d:%02d:%02d", hours, minutes, seconds); 1968 else 1969 snprintf(ttlbuf, sizeof(ttlbuf), "%2d:%02d", minutes, seconds); 1970 return (ttlbuf); 1971 } 1972 1973 1974 static int sort_pkts(const void *a, const void *b) 1975 { 1976 1977 register const statetop_t *ap = a; 1978 register const statetop_t *bp = b; 1979 1980 if (ap->st_pkts == bp->st_pkts) 1981 return (0); 1982 else if (ap->st_pkts < bp->st_pkts) 1983 return (1); 1984 return (-1); 1985 } 1986 1987 1988 static int sort_bytes(const void *a, const void *b) 1989 { 1990 register const statetop_t *ap = a; 1991 register const statetop_t *bp = b; 1992 1993 if (ap->st_bytes == bp->st_bytes) 1994 return (0); 1995 else if (ap->st_bytes < bp->st_bytes) 1996 return (1); 1997 return (-1); 1998 } 1999 2000 2001 static int sort_p(const void *a, const void *b) 2002 { 2003 register const statetop_t *ap = a; 2004 register const statetop_t *bp = b; 2005 2006 if (ap->st_p == bp->st_p) 2007 return (0); 2008 else if (ap->st_p < bp->st_p) 2009 return (1); 2010 return (-1); 2011 } 2012 2013 2014 static int sort_ttl(const void *a, const void *b) 2015 { 2016 register const statetop_t *ap = a; 2017 register const statetop_t *bp = b; 2018 2019 if (ap->st_age == bp->st_age) 2020 return (0); 2021 else if (ap->st_age < bp->st_age) 2022 return (1); 2023 return (-1); 2024 } 2025 2026 static int sort_srcip(const void *a, const void *b) 2027 { 2028 register const statetop_t *ap = a; 2029 register const statetop_t *bp = b; 2030 2031 #ifdef USE_INET6 2032 if (use_inet6 && !use_inet4) { 2033 if (IP6_EQ(&ap->st_src, &bp->st_src)) 2034 return (0); 2035 else if (IP6_GT(&ap->st_src, &bp->st_src)) 2036 return (1); 2037 } else 2038 #endif 2039 { 2040 if (ntohl(ap->st_src.in4.s_addr) == 2041 ntohl(bp->st_src.in4.s_addr)) 2042 return (0); 2043 else if (ntohl(ap->st_src.in4.s_addr) > 2044 ntohl(bp->st_src.in4.s_addr)) 2045 return (1); 2046 } 2047 return (-1); 2048 } 2049 2050 static int sort_srcpt(const void *a, const void *b) 2051 { 2052 register const statetop_t *ap = a; 2053 register const statetop_t *bp = b; 2054 2055 if (htons(ap->st_sport) == htons(bp->st_sport)) 2056 return (0); 2057 else if (htons(ap->st_sport) > htons(bp->st_sport)) 2058 return (1); 2059 return (-1); 2060 } 2061 2062 static int sort_dstip(const void *a, const void *b) 2063 { 2064 register const statetop_t *ap = a; 2065 register const statetop_t *bp = b; 2066 2067 #ifdef USE_INET6 2068 if (use_inet6 && !use_inet4) { 2069 if (IP6_EQ(&ap->st_dst, &bp->st_dst)) 2070 return (0); 2071 else if (IP6_GT(&ap->st_dst, &bp->st_dst)) 2072 return (1); 2073 } else 2074 #endif 2075 { 2076 if (ntohl(ap->st_dst.in4.s_addr) == 2077 ntohl(bp->st_dst.in4.s_addr)) 2078 return (0); 2079 else if (ntohl(ap->st_dst.in4.s_addr) > 2080 ntohl(bp->st_dst.in4.s_addr)) 2081 return (1); 2082 } 2083 return (-1); 2084 } 2085 2086 static int sort_dstpt(const void *a, const void *b) 2087 { 2088 register const statetop_t *ap = a; 2089 register const statetop_t *bp = b; 2090 2091 if (htons(ap->st_dport) == htons(bp->st_dport)) 2092 return (0); 2093 else if (htons(ap->st_dport) > htons(bp->st_dport)) 2094 return (1); 2095 return (-1); 2096 } 2097 2098 #endif 2099 2100 2101 ipstate_t *fetchstate(ipstate_t *src, ipstate_t *dst) 2102 { 2103 2104 if (live_kernel == 1) { 2105 ipfgeniter_t state; 2106 ipfobj_t obj; 2107 2108 obj.ipfo_rev = IPFILTER_VERSION; 2109 obj.ipfo_type = IPFOBJ_GENITER; 2110 obj.ipfo_size = sizeof(state); 2111 obj.ipfo_ptr = &state; 2112 2113 state.igi_type = IPFGENITER_STATE; 2114 state.igi_nitems = 1; 2115 state.igi_data = dst; 2116 2117 if (ioctl(state_fd, SIOCGENITER, &obj) != 0) 2118 return (NULL); 2119 if (dst->is_next == NULL) { 2120 int n = IPFGENITER_STATE; 2121 (void) ioctl(ipf_fd,SIOCIPFDELTOK, &n); 2122 } 2123 } else { 2124 if (kmemcpy((char *)dst, (u_long)src, sizeof(*dst))) 2125 return (NULL); 2126 } 2127 return (dst); 2128 } 2129 2130 2131 static int fetchfrag( int fd, int type, ipfr_t *frp) 2132 { 2133 ipfgeniter_t frag; 2134 ipfobj_t obj; 2135 2136 obj.ipfo_rev = IPFILTER_VERSION; 2137 obj.ipfo_type = IPFOBJ_GENITER; 2138 obj.ipfo_size = sizeof(frag); 2139 obj.ipfo_ptr = &frag; 2140 2141 frag.igi_type = type; 2142 frag.igi_nitems = 1; 2143 frag.igi_data = frp; 2144 2145 if (ioctl(fd, SIOCGENITER, &obj)) 2146 return (EFAULT); 2147 return (0); 2148 } 2149 2150 2151 static int state_matcharray(ipstate_t *stp, int *array) 2152 { 2153 int i, n, *x, rv, p; 2154 ipfexp_t *e; 2155 2156 rv = 0; 2157 2158 for (n = array[0], x = array + 1; n > 0; x += e->ipfe_size) { 2159 e = (ipfexp_t *)x; 2160 if (e->ipfe_cmd == IPF_EXP_END) 2161 break; 2162 n -= e->ipfe_size; 2163 2164 rv = 0; 2165 /* 2166 * The upper 16 bits currently store the protocol value. 2167 * This is currently used with TCP and UDP port compares and 2168 * allows "tcp.port = 80" without requiring an explicit 2169 " "ip.pr = tcp" first. 2170 */ 2171 p = e->ipfe_cmd >> 16; 2172 if ((p != 0) && (p != stp->is_p)) 2173 break; 2174 2175 switch (e->ipfe_cmd) 2176 { 2177 case IPF_EXP_IP_PR : 2178 for (i = 0; !rv && i < e->ipfe_narg; i++) { 2179 rv |= (stp->is_p == e->ipfe_arg0[i]); 2180 } 2181 break; 2182 2183 case IPF_EXP_IP_SRCADDR : 2184 if (stp->is_v != 4) 2185 break; 2186 for (i = 0; !rv && i < e->ipfe_narg; i++) { 2187 rv |= ((stp->is_saddr & 2188 e->ipfe_arg0[i * 2 + 1]) == 2189 e->ipfe_arg0[i * 2]); 2190 } 2191 break; 2192 2193 case IPF_EXP_IP_DSTADDR : 2194 if (stp->is_v != 4) 2195 break; 2196 for (i = 0; !rv && i < e->ipfe_narg; i++) { 2197 rv |= ((stp->is_daddr & 2198 e->ipfe_arg0[i * 2 + 1]) == 2199 e->ipfe_arg0[i * 2]); 2200 } 2201 break; 2202 2203 case IPF_EXP_IP_ADDR : 2204 if (stp->is_v != 4) 2205 break; 2206 for (i = 0; !rv && i < e->ipfe_narg; i++) { 2207 rv |= ((stp->is_saddr & 2208 e->ipfe_arg0[i * 2 + 1]) == 2209 e->ipfe_arg0[i * 2]) || 2210 ((stp->is_daddr & 2211 e->ipfe_arg0[i * 2 + 1]) == 2212 e->ipfe_arg0[i * 2]); 2213 } 2214 break; 2215 2216 #ifdef USE_INET6 2217 case IPF_EXP_IP6_SRCADDR : 2218 if (stp->is_v != 6) 2219 break; 2220 for (i = 0; !rv && i < e->ipfe_narg; i++) { 2221 rv |= IP6_MASKEQ(&stp->is_src, 2222 &e->ipfe_arg0[i * 8 + 4], 2223 &e->ipfe_arg0[i * 8]); 2224 } 2225 break; 2226 2227 case IPF_EXP_IP6_DSTADDR : 2228 if (stp->is_v != 6) 2229 break; 2230 for (i = 0; !rv && i < e->ipfe_narg; i++) { 2231 rv |= IP6_MASKEQ(&stp->is_dst, 2232 &e->ipfe_arg0[i * 8 + 4], 2233 &e->ipfe_arg0[i * 8]); 2234 } 2235 break; 2236 2237 case IPF_EXP_IP6_ADDR : 2238 if (stp->is_v != 6) 2239 break; 2240 for (i = 0; !rv && i < e->ipfe_narg; i++) { 2241 rv |= IP6_MASKEQ(&stp->is_src, 2242 &e->ipfe_arg0[i * 8 + 4], 2243 &e->ipfe_arg0[i * 8]) || 2244 IP6_MASKEQ(&stp->is_dst, 2245 &e->ipfe_arg0[i * 8 + 4], 2246 &e->ipfe_arg0[i * 8]); 2247 } 2248 break; 2249 #endif 2250 2251 case IPF_EXP_UDP_PORT : 2252 case IPF_EXP_TCP_PORT : 2253 for (i = 0; !rv && i < e->ipfe_narg; i++) { 2254 rv |= (stp->is_sport == e->ipfe_arg0[i]) || 2255 (stp->is_dport == e->ipfe_arg0[i]); 2256 } 2257 break; 2258 2259 case IPF_EXP_UDP_SPORT : 2260 case IPF_EXP_TCP_SPORT : 2261 for (i = 0; !rv && i < e->ipfe_narg; i++) { 2262 rv |= (stp->is_sport == e->ipfe_arg0[i]); 2263 } 2264 break; 2265 2266 case IPF_EXP_UDP_DPORT : 2267 case IPF_EXP_TCP_DPORT : 2268 for (i = 0; !rv && i < e->ipfe_narg; i++) { 2269 rv |= (stp->is_dport == e->ipfe_arg0[i]); 2270 } 2271 break; 2272 2273 case IPF_EXP_IDLE_GT : 2274 for (i = 0; !rv && i < e->ipfe_narg; i++) { 2275 rv |= (stp->is_die < e->ipfe_arg0[i]); 2276 } 2277 break; 2278 2279 case IPF_EXP_TCP_STATE : 2280 for (i = 0; !rv && i < e->ipfe_narg; i++) { 2281 rv |= (stp->is_state[0] == e->ipfe_arg0[i]) || 2282 (stp->is_state[1] == e->ipfe_arg0[i]); 2283 } 2284 break; 2285 } 2286 rv ^= e->ipfe_not; 2287 2288 if (rv == 0) 2289 break; 2290 } 2291 2292 return (rv); 2293 } 2294 2295 2296 static void showtqtable_live(int fd) 2297 { 2298 ipftq_t table[IPF_TCP_NSTATES]; 2299 ipfobj_t obj; 2300 2301 bzero((char *)&obj, sizeof(obj)); 2302 obj.ipfo_rev = IPFILTER_VERSION; 2303 obj.ipfo_size = sizeof(table); 2304 obj.ipfo_ptr = (void *)table; 2305 obj.ipfo_type = IPFOBJ_STATETQTAB; 2306 2307 if (ioctl(fd, SIOCGTQTAB, &obj) == 0) { 2308 printtqtable(table); 2309 } 2310 } 2311