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