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