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