1 /* $NetBSD: ipfstat.c,v 1.3 2012/07/22 14:27:51 darrenr Exp $ */ 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) 74 static const char sccsid[] = "@(#)fils.c 1.21 4/20/96 (C) 1993-2000 Darren Reed"; 75 static const char rcsid[] = "@(#)Id: ipfstat.c,v 1.1.1.2 2012/07/22 13:44:55 darrenr"; 76 #endif 77 78 #ifdef __hpux 79 # define nlist nlist64 80 #endif 81 82 extern char *optarg; 83 extern int optind; 84 extern int opterr; 85 86 #define PRINTF (void)printf 87 #define FPRINTF (void)fprintf 88 static char *filters[4] = { "ipfilter(in)", "ipfilter(out)", 89 "ipacct(in)", "ipacct(out)" }; 90 static int state_logging = -1; 91 static wordtab_t *state_fields = NULL; 92 93 int nohdrfields = 0; 94 int opts = 0; 95 int use_inet6 = 0; 96 int live_kernel = 1; 97 int state_fd = -1; 98 int ipf_fd = -1; 99 int auth_fd = -1; 100 int nat_fd = -1; 101 frgroup_t *grtop = NULL; 102 frgroup_t *grtail = NULL; 103 104 char *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 141 typedef 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 155 int main __P((int, char *[])); 156 157 static int fetchfrag __P((int, int, ipfr_t *)); 158 static void showstats __P((friostat_t *, u_32_t)); 159 static void showfrstates __P((ipfrstat_t *, u_long)); 160 static void showlist __P((friostat_t *)); 161 static void showstatestats __P((ips_stat_t *)); 162 static void showipstates __P((ips_stat_t *, int *)); 163 static void showauthstates __P((ipf_authstat_t *)); 164 static void showtqtable_live __P((int)); 165 static void showgroups __P((friostat_t *)); 166 static void usage __P((char *)); 167 static int state_matcharray __P((ipstate_t *, int *)); 168 static int printlivelist __P((friostat_t *, int, int, frentry_t *, 169 char *, char *)); 170 static void printdeadlist __P((friostat_t *, int, int, frentry_t *, 171 char *, char *)); 172 static void printside __P((char *, ipf_statistics_t *)); 173 static void parse_ipportstr __P((const char *, i6addr_t *, int *)); 174 static void ipfstate_live __P((char *, friostat_t **, ips_stat_t **, 175 ipfrstat_t **, ipf_authstat_t **, u_32_t *)); 176 static void ipfstate_dead __P((char *, friostat_t **, ips_stat_t **, 177 ipfrstat_t **, ipf_authstat_t **, u_32_t *)); 178 static ipstate_t *fetchstate __P((ipstate_t *, ipstate_t *)); 179 #ifdef STATETOP 180 static void topipstates __P((i6addr_t, i6addr_t, int, int, int, 181 int, int, int, int *)); 182 static void sig_break __P((int)); 183 static void sig_resize __P((int)); 184 static char *getip __P((int, i6addr_t *)); 185 static char *ttl_to_string __P((long)); 186 static int sort_p __P((const void *, const void *)); 187 static int sort_pkts __P((const void *, const void *)); 188 static int sort_bytes __P((const void *, const void *)); 189 static int sort_ttl __P((const void *, const void *)); 190 static int sort_srcip __P((const void *, const void *)); 191 static int sort_srcpt __P((const void *, const void *)); 192 static int sort_dstip __P((const void *, const void *)); 193 static int sort_dstpt __P((const void *, const void *)); 194 #endif 195 196 197 static 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 216 int 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 */ 465 static 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 */ 550 static 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 722 static 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 */ 760 static 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 */ 792 static int 793 printlivelist(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 void *buf; 805 size_t bufsiz; 806 int rules; 807 int num; 808 809 rules = 0; 810 811 rule.iri_inout = out; 812 rule.iri_active = set; 813 rule.iri_rule = &fb; 814 rule.iri_nrules = 1; 815 if (group != NULL) 816 strncpy(rule.iri_group, group, FR_GROUPLEN); 817 else 818 rule.iri_group[0] = '\0'; 819 820 bzero((char *)&zero, sizeof(zero)); 821 822 bzero((char *)&obj, sizeof(obj)); 823 obj.ipfo_rev = IPFILTER_VERSION; 824 obj.ipfo_type = IPFOBJ_IPFITER; 825 obj.ipfo_size = sizeof(rule); 826 obj.ipfo_ptr = &rule; 827 828 /* 829 * The API does not know how much we need for filter data. Assume 830 * 10K is large enough. XXX: The code silently fails elsewhere on 831 * allocation, we do the same here. 832 */ 833 if ((buf = malloc(bufsiz = sizeof(*fp) + 10240)) == NULL) 834 return 0; 835 836 do { 837 memset(buf, 0xff, bufsiz); 838 fp = buf; 839 rule.iri_rule = fp; 840 if (ioctl(ipf_fd, SIOCIPFITER, &obj) == -1) { 841 ipferror(ipf_fd, "ioctl(SIOCIPFITER)"); 842 num = IPFGENITER_IPF; 843 (void) ioctl(ipf_fd,SIOCIPFDELTOK, &num); 844 return rules; 845 } 846 if (bcmp(fp, &zero, sizeof(zero)) == 0) 847 break; 848 if (rule.iri_rule == NULL) 849 break; 850 #ifdef USE_INET6 851 if (use_inet6 != 0) { 852 if (fp->fr_family != 0 && fp->fr_family != AF_INET6) 853 continue; 854 } else 855 #endif 856 { 857 if (fp->fr_family != 0 && fp->fr_family != AF_INET) 858 continue; 859 } 860 if (fp->fr_data != NULL) 861 fp->fr_data = (char *)fp + fp->fr_size; 862 863 rules++; 864 865 if (opts & (OPT_HITS|OPT_DEBUG)) 866 #ifdef USE_QUAD_T 867 PRINTF("%llu ", (unsigned long long) fp->fr_hits); 868 #else 869 PRINTF("%lu ", fp->fr_hits); 870 #endif 871 if (opts & (OPT_ACCNT|OPT_DEBUG)) 872 #ifdef USE_QUAD_T 873 PRINTF("%llu ", (unsigned long long) fp->fr_bytes); 874 #else 875 PRINTF("%lu ", fp->fr_bytes); 876 #endif 877 if (opts & OPT_SHOWLINENO) 878 PRINTF("@%d ", rules); 879 880 if (fp->fr_die != 0) 881 fp->fr_die -= fiop->f_ticks; 882 883 printfr(fp, ioctl); 884 if (opts & OPT_DEBUG) { 885 binprint(fp, fp->fr_size); 886 if (fp->fr_data != NULL && fp->fr_dsize > 0) 887 binprint(fp->fr_data, fp->fr_dsize); 888 } 889 if (fp->fr_grhead != -1) { 890 for (g = grtop; g != NULL; g = g->fg_next) { 891 if (!strncmp(fp->fr_names + fp->fr_grhead, 892 g->fg_name, 893 FR_GROUPLEN)) 894 break; 895 } 896 if (g == NULL) { 897 g = calloc(1, sizeof(*g)); 898 899 if (g != NULL) { 900 strncpy(g->fg_name, 901 fp->fr_names + fp->fr_grhead, 902 FR_GROUPLEN); 903 if (grtop == NULL) { 904 grtop = g; 905 grtail = g; 906 } else { 907 grtail->fg_next = g; 908 grtail = g; 909 } 910 } 911 } 912 } 913 if (fp->fr_type == FR_T_CALLFUNC) { 914 rules += printlivelist(fiop, out, set, fp->fr_data, 915 group, "# callfunc: "); 916 } 917 } while (fp->fr_next != NULL); 918 919 num = IPFGENITER_IPF; 920 (void) ioctl(ipf_fd,SIOCIPFDELTOK, &num); 921 922 return rules; 923 } 924 925 926 static void printdeadlist(fiop, out, set, fp, group, comment) 927 friostat_t *fiop; 928 int out, set; 929 frentry_t *fp; 930 char *group, *comment; 931 { 932 frgroup_t *grtop, *grtail, *g; 933 struct frentry fb; 934 char *data; 935 u_32_t type; 936 int n; 937 938 fb.fr_next = fp; 939 n = 0; 940 grtop = NULL; 941 grtail = NULL; 942 943 for (n = 1; fp; fp = fb.fr_next, n++) { 944 if (kmemcpy((char *)&fb, (u_long)fb.fr_next, 945 fb.fr_size) == -1) { 946 perror("kmemcpy"); 947 return; 948 } 949 fp = &fb; 950 if (use_inet6 != 0) { 951 if (fp->fr_family != 0 && fp->fr_family != 6) 952 continue; 953 } else { 954 if (fp->fr_family != 0 && fp->fr_family != 4) 955 continue; 956 } 957 958 data = NULL; 959 type = fb.fr_type & ~FR_T_BUILTIN; 960 if (type == FR_T_IPF || type == FR_T_BPFOPC) { 961 if (fb.fr_dsize) { 962 data = malloc(fb.fr_dsize); 963 964 if (kmemcpy(data, (u_long)fb.fr_data, 965 fb.fr_dsize) == -1) { 966 perror("kmemcpy"); 967 return; 968 } 969 fb.fr_data = data; 970 } 971 } 972 973 if (opts & OPT_HITS) 974 #ifdef USE_QUAD_T 975 PRINTF("%llu ", (unsigned long long) fb.fr_hits); 976 #else 977 PRINTF("%lu ", fb.fr_hits); 978 #endif 979 if (opts & OPT_ACCNT) 980 #ifdef USE_QUAD_T 981 PRINTF("%llu ", (unsigned long long) fb.fr_bytes); 982 #else 983 PRINTF("%lu ", fb.fr_bytes); 984 #endif 985 if (opts & OPT_SHOWLINENO) 986 PRINTF("@%d ", n); 987 988 printfr(fp, ioctl); 989 if (opts & OPT_DEBUG) { 990 binprint(fp, fp->fr_size); 991 if (fb.fr_data != NULL && fb.fr_dsize > 0) 992 binprint(fb.fr_data, fb.fr_dsize); 993 } 994 if (data != NULL) 995 free(data); 996 if (fb.fr_grhead != -1) { 997 g = calloc(1, sizeof(*g)); 998 999 if (g != NULL) { 1000 strncpy(g->fg_name, fb.fr_names + fb.fr_grhead, 1001 FR_GROUPLEN); 1002 if (grtop == NULL) { 1003 grtop = g; 1004 grtail = g; 1005 } else { 1006 grtail->fg_next = g; 1007 grtail = g; 1008 } 1009 } 1010 } 1011 if (type == FR_T_CALLFUNC) { 1012 printdeadlist(fiop, out, set, fb.fr_data, group, 1013 "# callfunc: "); 1014 } 1015 } 1016 1017 while ((g = grtop) != NULL) { 1018 printdeadlist(fiop, out, set, NULL, g->fg_name, comment); 1019 grtop = g->fg_next; 1020 free(g); 1021 } 1022 } 1023 1024 /* 1025 * print out all of the asked for rule sets, using the stats struct as 1026 * the base from which to get the pointers. 1027 */ 1028 static void showlist(fiop) 1029 struct friostat *fiop; 1030 { 1031 struct frentry *fp = NULL; 1032 int i, set; 1033 1034 set = fiop->f_active; 1035 if (opts & OPT_INACTIVE) 1036 set = 1 - set; 1037 if (opts & OPT_ACCNT) { 1038 if (opts & OPT_OUTQUE) { 1039 i = F_ACOUT; 1040 fp = (struct frentry *)fiop->f_acctout[set]; 1041 } else if (opts & OPT_INQUE) { 1042 i = F_ACIN; 1043 fp = (struct frentry *)fiop->f_acctin[set]; 1044 } else { 1045 FPRINTF(stderr, "No -i or -o given with -a\n"); 1046 return; 1047 } 1048 } else { 1049 if (opts & OPT_OUTQUE) { 1050 i = F_OUT; 1051 fp = (struct frentry *)fiop->f_fout[set]; 1052 } else if (opts & OPT_INQUE) { 1053 i = F_IN; 1054 fp = (struct frentry *)fiop->f_fin[set]; 1055 } else 1056 return; 1057 } 1058 if (opts & OPT_DEBUG) 1059 FPRINTF(stderr, "showlist:opts %#x i %d\n", opts, i); 1060 1061 if (opts & OPT_DEBUG) 1062 PRINTF("fp %p set %d\n", fp, set); 1063 1064 if (live_kernel == 1) { 1065 int printed; 1066 1067 printed = printlivelist(fiop, i, set, fp, NULL, NULL); 1068 if (printed == 0) { 1069 FPRINTF(stderr, "# empty list for %s%s\n", 1070 (opts & OPT_INACTIVE) ? "inactive " : "", 1071 filters[i]); 1072 } 1073 } else { 1074 if (!fp) { 1075 FPRINTF(stderr, "# empty list for %s%s\n", 1076 (opts & OPT_INACTIVE) ? "inactive " : "", 1077 filters[i]); 1078 } else { 1079 printdeadlist(fiop, i, set, fp, NULL, NULL); 1080 } 1081 } 1082 } 1083 1084 1085 /* 1086 * Display ipfilter stateful filtering information 1087 */ 1088 static void showipstates(ipsp, filter) 1089 ips_stat_t *ipsp; 1090 int *filter; 1091 { 1092 ipstate_t *is; 1093 int i; 1094 1095 /* 1096 * If a list of states hasn't been asked for, only print out stats 1097 */ 1098 if (!(opts & OPT_SHOWLIST)) { 1099 showstatestats(ipsp); 1100 return; 1101 } 1102 1103 if ((state_fields != NULL) && (nohdrfields == 0)) { 1104 for (i = 0; state_fields[i].w_value != 0; i++) { 1105 printfieldhdr(statefields, state_fields + i); 1106 if (state_fields[i + 1].w_value != 0) 1107 printf("\t"); 1108 } 1109 printf("\n"); 1110 } 1111 1112 /* 1113 * Print out all the state information currently held in the kernel. 1114 */ 1115 for (is = ipsp->iss_list; is != NULL; ) { 1116 ipstate_t ips; 1117 1118 is = fetchstate(is, &ips); 1119 1120 if (is == NULL) 1121 break; 1122 1123 is = ips.is_next; 1124 if ((filter != NULL) && 1125 (state_matcharray(&ips, filter) == 0)) { 1126 continue; 1127 } 1128 if (state_fields != NULL) { 1129 for (i = 0; state_fields[i].w_value != 0; i++) { 1130 printstatefield(&ips, state_fields[i].w_value); 1131 if (state_fields[i + 1].w_value != 0) 1132 printf("\t"); 1133 } 1134 printf("\n"); 1135 } else { 1136 printstate(&ips, opts, ipsp->iss_ticks); 1137 } 1138 } 1139 } 1140 1141 1142 static void showstatestats(ipsp) 1143 ips_stat_t *ipsp; 1144 { 1145 int minlen, maxlen, totallen; 1146 ipftable_t table; 1147 u_int *buckets; 1148 ipfobj_t obj; 1149 int i, sz; 1150 1151 /* 1152 * If a list of states hasn't been asked for, only print out stats 1153 */ 1154 1155 sz = sizeof(*buckets) * ipsp->iss_state_size; 1156 buckets = (u_int *)malloc(sz); 1157 1158 obj.ipfo_rev = IPFILTER_VERSION; 1159 obj.ipfo_type = IPFOBJ_GTABLE; 1160 obj.ipfo_size = sizeof(table); 1161 obj.ipfo_ptr = &table; 1162 1163 table.ita_type = IPFTABLE_BUCKETS; 1164 table.ita_table = buckets; 1165 1166 if (live_kernel == 1) { 1167 if (ioctl(state_fd, SIOCGTABL, &obj) != 0) { 1168 free(buckets); 1169 return; 1170 } 1171 } else { 1172 if (kmemcpy((char *)buckets, 1173 (u_long)ipsp->iss_bucketlen, sz)) { 1174 free(buckets); 1175 return; 1176 } 1177 } 1178 1179 PRINTF("%u\tactive state table entries\n",ipsp->iss_active); 1180 PRINTF("%lu\tadd bad\n", ipsp->iss_add_bad); 1181 PRINTF("%lu\tadd duplicate\n", ipsp->iss_add_dup); 1182 PRINTF("%lu\tadd locked\n", ipsp->iss_add_locked); 1183 PRINTF("%lu\tadd oow\n", ipsp->iss_add_oow); 1184 PRINTF("%lu\tbucket full\n", ipsp->iss_bucket_full); 1185 PRINTF("%lu\tcheck bad\n", ipsp->iss_check_bad); 1186 PRINTF("%lu\tcheck miss\n", ipsp->iss_check_miss); 1187 PRINTF("%lu\tcheck nattag\n", ipsp->iss_check_nattag); 1188 PRINTF("%lu\tclone nomem\n", ipsp->iss_clone_nomem); 1189 PRINTF("%lu\tcheck notag\n", ipsp->iss_check_notag); 1190 PRINTF("%lu\tcheck success\n", ipsp->iss_hits); 1191 PRINTF("%lu\tcloned\n", ipsp->iss_cloned); 1192 PRINTF("%lu\texpired\n", ipsp->iss_expire); 1193 PRINTF("%lu\tflush all\n", ipsp->iss_flush_all); 1194 PRINTF("%lu\tflush closing\n", ipsp->iss_flush_closing); 1195 PRINTF("%lu\tflush queue\n", ipsp->iss_flush_queue); 1196 PRINTF("%lu\tflush state\n", ipsp->iss_flush_state); 1197 PRINTF("%lu\tflush timeout\n", ipsp->iss_flush_timeout); 1198 PRINTF("%u\thash buckets in use\n", ipsp->iss_inuse); 1199 PRINTF("%lu\tICMP bad\n", ipsp->iss_icmp_bad); 1200 PRINTF("%lu\tICMP banned\n", ipsp->iss_icmp_banned); 1201 PRINTF("%lu\tICMP errors\n", ipsp->iss_icmp_icmperr); 1202 PRINTF("%lu\tICMP head block\n", ipsp->iss_icmp_headblock); 1203 PRINTF("%lu\tICMP hits\n", ipsp->iss_icmp_hits); 1204 PRINTF("%lu\tICMP not query\n", ipsp->iss_icmp_notquery); 1205 PRINTF("%lu\tICMP short\n", ipsp->iss_icmp_short); 1206 PRINTF("%lu\tICMP too many\n", ipsp->iss_icmp_toomany); 1207 PRINTF("%lu\tICMPv6 errors\n", ipsp->iss_icmp6_icmperr); 1208 PRINTF("%lu\tICMPv6 miss\n", ipsp->iss_icmp6_miss); 1209 PRINTF("%lu\tICMPv6 not info\n", ipsp->iss_icmp6_notinfo); 1210 PRINTF("%lu\tICMPv6 not query\n", ipsp->iss_icmp6_notquery); 1211 PRINTF("%lu\tlog fail\n", ipsp->iss_log_fail); 1212 PRINTF("%lu\tlog ok\n", ipsp->iss_log_ok); 1213 PRINTF("%lu\tlookup interface mismatch\n", ipsp->iss_lookup_badifp); 1214 PRINTF("%lu\tlookup mask mismatch\n", ipsp->iss_miss_mask); 1215 PRINTF("%lu\tlookup port mismatch\n", ipsp->iss_lookup_badport); 1216 PRINTF("%lu\tlookup miss\n", ipsp->iss_lookup_miss); 1217 PRINTF("%lu\tmaximum rule references\n", ipsp->iss_max_ref); 1218 PRINTF("%lu\tmaximum hosts per rule\n", ipsp->iss_max_track); 1219 PRINTF("%lu\tno memory\n", ipsp->iss_nomem); 1220 PRINTF("%lu\tout of window\n", ipsp->iss_oow); 1221 PRINTF("%lu\torphans\n", ipsp->iss_orphan); 1222 PRINTF("%lu\tscan block\n", ipsp->iss_scan_block); 1223 PRINTF("%lu\tstate table maximum reached\n", ipsp->iss_max); 1224 PRINTF("%lu\tTCP closing\n", ipsp->iss_tcp_closing); 1225 PRINTF("%lu\tTCP OOW\n", ipsp->iss_tcp_oow); 1226 PRINTF("%lu\tTCP RST add\n", ipsp->iss_tcp_rstadd); 1227 PRINTF("%lu\tTCP too small\n", ipsp->iss_tcp_toosmall); 1228 PRINTF("%lu\tTCP bad options\n", ipsp->iss_tcp_badopt); 1229 PRINTF("%lu\tTCP removed\n", ipsp->iss_fin); 1230 PRINTF("%lu\tTCP FSM\n", ipsp->iss_tcp_fsm); 1231 PRINTF("%lu\tTCP strict\n", ipsp->iss_tcp_strict); 1232 PRINTF("%lu\tTCP wild\n", ipsp->iss_wild); 1233 PRINTF("%lu\tMicrosoft Windows SACK\n", ipsp->iss_winsack); 1234 1235 PRINTF("State logging %sabled\n", state_logging ? "en" : "dis"); 1236 1237 PRINTF("IP states added:\n"); 1238 for (i = 0; i < 256; i++) { 1239 if (ipsp->iss_proto[i] != 0) { 1240 struct protoent *proto; 1241 1242 proto = getprotobynumber(i); 1243 PRINTF("%lu", ipsp->iss_proto[i]); 1244 if (proto != NULL) 1245 PRINTF("\t%s\n", proto->p_name); 1246 else 1247 PRINTF("\t%d\n", i); 1248 } 1249 } 1250 1251 PRINTF("\nState table bucket statistics:\n"); 1252 PRINTF("%u\tin use\n", ipsp->iss_inuse); 1253 1254 minlen = ipsp->iss_max; 1255 totallen = 0; 1256 maxlen = 0; 1257 1258 for (i = 0; i < ipsp->iss_state_size; i++) { 1259 if (buckets[i] > maxlen) 1260 maxlen = buckets[i]; 1261 if (buckets[i] < minlen) 1262 minlen = buckets[i]; 1263 totallen += buckets[i]; 1264 } 1265 1266 PRINTF("%d\thash efficiency\n", 1267 totallen ? ipsp->iss_inuse * 100 / totallen : 0); 1268 PRINTF("%2.2f%%\tbucket usage\n%u\tminimal length\n", 1269 ((float)ipsp->iss_inuse / ipsp->iss_state_size) * 100.0, 1270 minlen); 1271 PRINTF("%u\tmaximal length\n%.3f\taverage length\n", 1272 maxlen, 1273 ipsp->iss_inuse ? (float) totallen/ ipsp->iss_inuse : 1274 0.0); 1275 1276 #define ENTRIES_PER_LINE 5 1277 1278 if (opts & OPT_VERBOSE) { 1279 PRINTF("\nCurrent bucket sizes :\n"); 1280 for (i = 0; i < ipsp->iss_state_size; i++) { 1281 if ((i % ENTRIES_PER_LINE) == 0) 1282 PRINTF("\t"); 1283 PRINTF("%4d -> %4u", i, buckets[i]); 1284 if ((i % ENTRIES_PER_LINE) == 1285 (ENTRIES_PER_LINE - 1)) 1286 PRINTF("\n"); 1287 else 1288 PRINTF(" "); 1289 } 1290 PRINTF("\n"); 1291 } 1292 PRINTF("\n"); 1293 1294 free(buckets); 1295 1296 if (live_kernel == 1) { 1297 showtqtable_live(state_fd); 1298 } else { 1299 printtqtable(ipsp->iss_tcptab); 1300 } 1301 } 1302 1303 1304 #ifdef STATETOP 1305 static int handle_resize = 0, handle_break = 0; 1306 1307 static void topipstates(saddr, daddr, sport, dport, protocol, ver, 1308 refreshtime, topclosed, filter) 1309 i6addr_t saddr; 1310 i6addr_t daddr; 1311 int sport; 1312 int dport; 1313 int protocol; 1314 int ver; 1315 int refreshtime; 1316 int topclosed; 1317 int *filter; 1318 { 1319 char str1[STSTRSIZE], str2[STSTRSIZE], str3[STSTRSIZE], str4[STSTRSIZE]; 1320 int maxtsentries = 0, reverse = 0, sorting = STSORT_DEFAULT; 1321 int i, j, winy, tsentry, maxx, maxy, redraw = 0, ret = 0; 1322 int len, srclen, dstlen, forward = 1, c = 0; 1323 ips_stat_t ipsst, *ipsstp = &ipsst; 1324 int token_type = IPFGENITER_STATE; 1325 statetop_t *tstable = NULL, *tp; 1326 const char *errstr = ""; 1327 ipstate_t ips; 1328 ipfobj_t ipfo; 1329 struct timeval selecttimeout; 1330 char hostnm[HOSTNMLEN]; 1331 struct protoent *proto; 1332 fd_set readfd; 1333 time_t t; 1334 1335 /* install signal handlers */ 1336 signal(SIGINT, sig_break); 1337 signal(SIGQUIT, sig_break); 1338 signal(SIGTERM, sig_break); 1339 signal(SIGWINCH, sig_resize); 1340 1341 /* init ncurses stuff */ 1342 initscr(); 1343 cbreak(); 1344 noecho(); 1345 curs_set(0); 1346 timeout(0); 1347 getmaxyx(stdscr, maxy, maxx); 1348 1349 /* init hostname */ 1350 gethostname(hostnm, sizeof(hostnm) - 1); 1351 hostnm[sizeof(hostnm) - 1] = '\0'; 1352 1353 /* init ipfobj_t stuff */ 1354 bzero((caddr_t)&ipfo, sizeof(ipfo)); 1355 ipfo.ipfo_rev = IPFILTER_VERSION; 1356 ipfo.ipfo_type = IPFOBJ_STATESTAT; 1357 ipfo.ipfo_size = sizeof(*ipsstp); 1358 ipfo.ipfo_ptr = (void *)ipsstp; 1359 1360 /* repeat until user aborts */ 1361 while ( 1 ) { 1362 1363 /* get state table */ 1364 bzero((char *)&ipsst, sizeof(ipsst)); 1365 if ((ioctl(state_fd, SIOCGETFS, &ipfo) == -1)) { 1366 errstr = "ioctl(SIOCGETFS)"; 1367 ret = -1; 1368 goto out; 1369 } 1370 1371 /* clear the history */ 1372 tsentry = -1; 1373 1374 /* reset max str len */ 1375 srclen = dstlen = 0; 1376 1377 /* read the state table and store in tstable */ 1378 for (; ipsstp->iss_list; ipsstp->iss_list = ips.is_next) { 1379 1380 ipsstp->iss_list = fetchstate(ipsstp->iss_list, &ips); 1381 if (ipsstp->iss_list == NULL) 1382 break; 1383 1384 if (ips.is_v != ver) 1385 continue; 1386 1387 if ((filter != NULL) && 1388 (state_matcharray(&ips, filter) == 0)) 1389 continue; 1390 1391 /* check v4 src/dest addresses */ 1392 if (ips.is_v == 4) { 1393 if ((saddr.in4.s_addr != INADDR_ANY && 1394 saddr.in4.s_addr != ips.is_saddr) || 1395 (daddr.in4.s_addr != INADDR_ANY && 1396 daddr.in4.s_addr != ips.is_daddr)) 1397 continue; 1398 } 1399 #ifdef USE_INET6 1400 /* check v6 src/dest addresses */ 1401 if (ips.is_v == 6) { 1402 if ((IP6_NEQ(&saddr, &in6addr_any) && 1403 IP6_NEQ(&saddr, &ips.is_src)) || 1404 (IP6_NEQ(&daddr, &in6addr_any) && 1405 IP6_NEQ(&daddr, &ips.is_dst))) 1406 continue; 1407 } 1408 #endif 1409 /* check protocol */ 1410 if (protocol > 0 && protocol != ips.is_p) 1411 continue; 1412 1413 /* check ports if protocol is TCP or UDP */ 1414 if (((ips.is_p == IPPROTO_TCP) || 1415 (ips.is_p == IPPROTO_UDP)) && 1416 (((sport > 0) && (htons(sport) != ips.is_sport)) || 1417 ((dport > 0) && (htons(dport) != ips.is_dport)))) 1418 continue; 1419 1420 /* show closed TCP sessions ? */ 1421 if ((topclosed == 0) && (ips.is_p == IPPROTO_TCP) && 1422 (ips.is_state[0] >= IPF_TCPS_LAST_ACK) && 1423 (ips.is_state[1] >= IPF_TCPS_LAST_ACK)) 1424 continue; 1425 1426 /* 1427 * if necessary make room for this state 1428 * entry 1429 */ 1430 tsentry++; 1431 if (!maxtsentries || tsentry == maxtsentries) { 1432 maxtsentries += STGROWSIZE; 1433 tstable = realloc(tstable, 1434 maxtsentries * sizeof(statetop_t)); 1435 if (tstable == NULL) { 1436 perror("realloc"); 1437 exit(-1); 1438 } 1439 } 1440 1441 /* get max src/dest address string length */ 1442 len = strlen(getip(ips.is_v, &ips.is_src)); 1443 if (srclen < len) 1444 srclen = len; 1445 len = strlen(getip(ips.is_v, &ips.is_dst)); 1446 if (dstlen < len) 1447 dstlen = len; 1448 1449 /* fill structure */ 1450 tp = tstable + tsentry; 1451 tp->st_src = ips.is_src; 1452 tp->st_dst = ips.is_dst; 1453 tp->st_p = ips.is_p; 1454 tp->st_v = ips.is_v; 1455 tp->st_state[0] = ips.is_state[0]; 1456 tp->st_state[1] = ips.is_state[1]; 1457 if (forward) { 1458 tp->st_pkts = ips.is_pkts[0]+ips.is_pkts[1]; 1459 tp->st_bytes = ips.is_bytes[0]+ips.is_bytes[1]; 1460 } else { 1461 tp->st_pkts = ips.is_pkts[2]+ips.is_pkts[3]; 1462 tp->st_bytes = ips.is_bytes[2]+ips.is_bytes[3]; 1463 } 1464 tp->st_age = ips.is_die - ipsstp->iss_ticks; 1465 if ((ips.is_p == IPPROTO_TCP) || 1466 (ips.is_p == IPPROTO_UDP)) { 1467 tp->st_sport = ips.is_sport; 1468 tp->st_dport = ips.is_dport; 1469 } 1470 } 1471 1472 (void) ioctl(state_fd, SIOCIPFDELTOK, &token_type); 1473 1474 /* sort the array */ 1475 if (tsentry != -1) { 1476 switch (sorting) 1477 { 1478 case STSORT_PR: 1479 qsort(tstable, tsentry + 1, 1480 sizeof(statetop_t), sort_p); 1481 break; 1482 case STSORT_PKTS: 1483 qsort(tstable, tsentry + 1, 1484 sizeof(statetop_t), sort_pkts); 1485 break; 1486 case STSORT_BYTES: 1487 qsort(tstable, tsentry + 1, 1488 sizeof(statetop_t), sort_bytes); 1489 break; 1490 case STSORT_TTL: 1491 qsort(tstable, tsentry + 1, 1492 sizeof(statetop_t), sort_ttl); 1493 break; 1494 case STSORT_SRCIP: 1495 qsort(tstable, tsentry + 1, 1496 sizeof(statetop_t), sort_srcip); 1497 break; 1498 case STSORT_SRCPT: 1499 qsort(tstable, tsentry +1, 1500 sizeof(statetop_t), sort_srcpt); 1501 break; 1502 case STSORT_DSTIP: 1503 qsort(tstable, tsentry + 1, 1504 sizeof(statetop_t), sort_dstip); 1505 break; 1506 case STSORT_DSTPT: 1507 qsort(tstable, tsentry + 1, 1508 sizeof(statetop_t), sort_dstpt); 1509 break; 1510 default: 1511 break; 1512 } 1513 } 1514 1515 /* handle window resizes */ 1516 if (handle_resize) { 1517 endwin(); 1518 initscr(); 1519 cbreak(); 1520 noecho(); 1521 curs_set(0); 1522 timeout(0); 1523 getmaxyx(stdscr, maxy, maxx); 1524 redraw = 1; 1525 handle_resize = 0; 1526 } 1527 1528 /* stop program? */ 1529 if (handle_break) 1530 break; 1531 1532 /* print title */ 1533 erase(); 1534 attron(A_BOLD); 1535 winy = 0; 1536 move(winy,0); 1537 sprintf(str1, "%s - %s - state top", hostnm, IPL_VERSION); 1538 for (j = 0 ; j < (maxx - 8 - strlen(str1)) / 2; j++) 1539 printw(" "); 1540 printw("%s", str1); 1541 attroff(A_BOLD); 1542 1543 /* just for fun add a clock */ 1544 move(winy, maxx - 8); 1545 t = time(NULL); 1546 strftime(str1, 80, "%T", localtime(&t)); 1547 printw("%s\n", str1); 1548 1549 /* 1550 * print the display filters, this is placed in the loop, 1551 * because someday I might add code for changing these 1552 * while the programming is running :-) 1553 */ 1554 if (sport >= 0) 1555 sprintf(str1, "%s,%d", getip(ver, &saddr), sport); 1556 else 1557 sprintf(str1, "%s", getip(ver, &saddr)); 1558 1559 if (dport >= 0) 1560 sprintf(str2, "%s,%d", getip(ver, &daddr), dport); 1561 else 1562 sprintf(str2, "%s", getip(ver, &daddr)); 1563 1564 if (protocol < 0) 1565 strcpy(str3, "any"); 1566 else if ((proto = getprotobynumber(protocol)) != NULL) 1567 sprintf(str3, "%s", proto->p_name); 1568 else 1569 sprintf(str3, "%d", protocol); 1570 1571 switch (sorting) 1572 { 1573 case STSORT_PR: 1574 sprintf(str4, "proto"); 1575 break; 1576 case STSORT_PKTS: 1577 sprintf(str4, "# pkts"); 1578 break; 1579 case STSORT_BYTES: 1580 sprintf(str4, "# bytes"); 1581 break; 1582 case STSORT_TTL: 1583 sprintf(str4, "ttl"); 1584 break; 1585 case STSORT_SRCIP: 1586 sprintf(str4, "src ip"); 1587 break; 1588 case STSORT_SRCPT: 1589 sprintf(str4, "src port"); 1590 break; 1591 case STSORT_DSTIP: 1592 sprintf(str4, "dest ip"); 1593 break; 1594 case STSORT_DSTPT: 1595 sprintf(str4, "dest port"); 1596 break; 1597 default: 1598 sprintf(str4, "unknown"); 1599 break; 1600 } 1601 1602 if (reverse) 1603 strcat(str4, " (reverse)"); 1604 1605 winy += 2; 1606 move(winy,0); 1607 printw("Src: %s, Dest: %s, Proto: %s, Sorted by: %s\n\n", 1608 str1, str2, str3, str4); 1609 1610 /* 1611 * For an IPv4 IP address we need at most 15 characters, 1612 * 4 tuples of 3 digits, separated by 3 dots. Enforce this 1613 * length, so the colums do not change positions based 1614 * on the size of the IP address. This length makes the 1615 * output fit in a 80 column terminal. 1616 * We are lacking a good solution for IPv6 addresses (that 1617 * can be longer that 15 characters), so we do not enforce 1618 * a maximum on the IP field size. 1619 */ 1620 if (srclen < 15) 1621 srclen = 15; 1622 if (dstlen < 15) 1623 dstlen = 15; 1624 1625 /* print column description */ 1626 winy += 2; 1627 move(winy,0); 1628 attron(A_BOLD); 1629 printw("%-*s %-*s %3s %4s %7s %9s %9s\n", 1630 srclen + 6, "Source IP", dstlen + 6, "Destination IP", 1631 "ST", "PR", "#pkts", "#bytes", "ttl"); 1632 attroff(A_BOLD); 1633 1634 /* print all the entries */ 1635 tp = tstable; 1636 if (reverse) 1637 tp += tsentry; 1638 1639 if (tsentry > maxy - 6) 1640 tsentry = maxy - 6; 1641 for (i = 0; i <= tsentry; i++) { 1642 /* print src/dest and port */ 1643 if ((tp->st_p == IPPROTO_TCP) || 1644 (tp->st_p == IPPROTO_UDP)) { 1645 sprintf(str1, "%s,%hu", 1646 getip(tp->st_v, &tp->st_src), 1647 ntohs(tp->st_sport)); 1648 sprintf(str2, "%s,%hu", 1649 getip(tp->st_v, &tp->st_dst), 1650 ntohs(tp->st_dport)); 1651 } else { 1652 sprintf(str1, "%s", getip(tp->st_v, 1653 &tp->st_src)); 1654 sprintf(str2, "%s", getip(tp->st_v, 1655 &tp->st_dst)); 1656 } 1657 winy++; 1658 move(winy, 0); 1659 printw("%-*s %-*s", srclen + 6, str1, dstlen + 6, str2); 1660 1661 /* print state */ 1662 sprintf(str1, "%X/%X", tp->st_state[0], 1663 tp->st_state[1]); 1664 printw(" %3s", str1); 1665 1666 /* print protocol */ 1667 proto = getprotobynumber(tp->st_p); 1668 if (proto) { 1669 strncpy(str1, proto->p_name, 4); 1670 str1[4] = '\0'; 1671 } else { 1672 sprintf(str1, "%d", tp->st_p); 1673 } 1674 /* just print icmp for IPv6-ICMP */ 1675 if (tp->st_p == IPPROTO_ICMPV6) 1676 strcpy(str1, "icmp"); 1677 printw(" %4s", str1); 1678 1679 /* print #pkt/#bytes */ 1680 #ifdef USE_QUAD_T 1681 printw(" %7qu %9qu", (unsigned long long) tp->st_pkts, 1682 (unsigned long long) tp->st_bytes); 1683 #else 1684 printw(" %7lu %9lu", tp->st_pkts, tp->st_bytes); 1685 #endif 1686 printw(" %9s", ttl_to_string(tp->st_age)); 1687 1688 if (reverse) 1689 tp--; 1690 else 1691 tp++; 1692 } 1693 1694 /* screen data structure is filled, now update the screen */ 1695 if (redraw) 1696 clearok(stdscr,1); 1697 1698 if (refresh() == ERR) 1699 break; 1700 if (redraw) { 1701 clearok(stdscr,0); 1702 redraw = 0; 1703 } 1704 1705 /* wait for key press or a 1 second time out period */ 1706 selecttimeout.tv_sec = refreshtime; 1707 selecttimeout.tv_usec = 0; 1708 FD_ZERO(&readfd); 1709 FD_SET(0, &readfd); 1710 select(1, &readfd, NULL, NULL, &selecttimeout); 1711 1712 /* if key pressed, read all waiting keys */ 1713 if (FD_ISSET(0, &readfd)) { 1714 c = wgetch(stdscr); 1715 if (c == ERR) 1716 continue; 1717 1718 if (ISALPHA(c) && ISUPPER(c)) 1719 c = TOLOWER(c); 1720 if (c == 'l') { 1721 redraw = 1; 1722 } else if (c == 'q') { 1723 break; 1724 } else if (c == 'r') { 1725 reverse = !reverse; 1726 } else if (c == 'b') { 1727 forward = 0; 1728 } else if (c == 'f') { 1729 forward = 1; 1730 } else if (c == 's') { 1731 if (++sorting > STSORT_MAX) 1732 sorting = 0; 1733 } 1734 } 1735 } /* while */ 1736 1737 out: 1738 printw("\n"); 1739 curs_set(1); 1740 /* nocbreak(); XXX - endwin() should make this redundant */ 1741 endwin(); 1742 1743 free(tstable); 1744 if (ret != 0) 1745 perror(errstr); 1746 } 1747 #endif 1748 1749 1750 /* 1751 * Show fragment cache information that's held in the kernel. 1752 */ 1753 static void showfrstates(ifsp, ticks) 1754 ipfrstat_t *ifsp; 1755 u_long ticks; 1756 { 1757 struct ipfr *ipfrtab[IPFT_SIZE], ifr; 1758 int i; 1759 1760 /* 1761 * print out the numeric statistics 1762 */ 1763 PRINTF("IP fragment states:\n%lu\tnew\n%lu\texpired\n%lu\thits\n", 1764 ifsp->ifs_new, ifsp->ifs_expire, ifsp->ifs_hits); 1765 PRINTF("%lu\tretrans\n%lu\ttoo short\n", 1766 ifsp->ifs_retrans0, ifsp->ifs_short); 1767 PRINTF("%lu\tno memory\n%lu\talready exist\n", 1768 ifsp->ifs_nomem, ifsp->ifs_exists); 1769 PRINTF("%lu\tinuse\n", ifsp->ifs_inuse); 1770 PRINTF("\n"); 1771 1772 if (live_kernel == 0) { 1773 if (kmemcpy((char *)ipfrtab, (u_long)ifsp->ifs_table, 1774 sizeof(ipfrtab))) 1775 return; 1776 } 1777 1778 /* 1779 * Print out the contents (if any) of the fragment cache table. 1780 */ 1781 if (live_kernel == 1) { 1782 do { 1783 if (fetchfrag(ipf_fd, IPFGENITER_FRAG, &ifr) != 0) 1784 break; 1785 if (ifr.ipfr_ifp == NULL) 1786 break; 1787 ifr.ipfr_ttl -= ticks; 1788 printfraginfo("", &ifr); 1789 } while (ifr.ipfr_next != NULL); 1790 } else { 1791 for (i = 0; i < IPFT_SIZE; i++) 1792 while (ipfrtab[i] != NULL) { 1793 if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i], 1794 sizeof(ifr)) == -1) 1795 break; 1796 printfraginfo("", &ifr); 1797 ipfrtab[i] = ifr.ipfr_next; 1798 } 1799 } 1800 /* 1801 * Print out the contents (if any) of the NAT fragment cache table. 1802 */ 1803 1804 if (live_kernel == 0) { 1805 if (kmemcpy((char *)ipfrtab, (u_long)ifsp->ifs_nattab, 1806 sizeof(ipfrtab))) 1807 return; 1808 } 1809 1810 if (live_kernel == 1) { 1811 do { 1812 if (fetchfrag(nat_fd, IPFGENITER_NATFRAG, &ifr) != 0) 1813 break; 1814 if (ifr.ipfr_ifp == NULL) 1815 break; 1816 ifr.ipfr_ttl -= ticks; 1817 printfraginfo("NAT: ", &ifr); 1818 } while (ifr.ipfr_next != NULL); 1819 } else { 1820 for (i = 0; i < IPFT_SIZE; i++) 1821 while (ipfrtab[i] != NULL) { 1822 if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i], 1823 sizeof(ifr)) == -1) 1824 break; 1825 printfraginfo("NAT: ", &ifr); 1826 ipfrtab[i] = ifr.ipfr_next; 1827 } 1828 } 1829 } 1830 1831 1832 /* 1833 * Show stats on how auth within IPFilter has been used 1834 */ 1835 static void showauthstates(asp) 1836 ipf_authstat_t *asp; 1837 { 1838 frauthent_t *frap, fra; 1839 ipfgeniter_t auth; 1840 ipfobj_t obj; 1841 1842 obj.ipfo_rev = IPFILTER_VERSION; 1843 obj.ipfo_type = IPFOBJ_GENITER; 1844 obj.ipfo_size = sizeof(auth); 1845 obj.ipfo_ptr = &auth; 1846 1847 auth.igi_type = IPFGENITER_AUTH; 1848 auth.igi_nitems = 1; 1849 auth.igi_data = &fra; 1850 1851 #ifdef USE_QUAD_T 1852 printf("Authorisation hits: %llu\tmisses %llu\n", 1853 (unsigned long long) asp->fas_hits, 1854 (unsigned long long) asp->fas_miss); 1855 #else 1856 printf("Authorisation hits: %ld\tmisses %ld\n", asp->fas_hits, 1857 asp->fas_miss); 1858 #endif 1859 printf("nospace %ld\nadded %ld\nsendfail %ld\nsendok %ld\n", 1860 asp->fas_nospace, asp->fas_added, asp->fas_sendfail, 1861 asp->fas_sendok); 1862 printf("queok %ld\nquefail %ld\nexpire %ld\n", 1863 asp->fas_queok, asp->fas_quefail, asp->fas_expire); 1864 1865 frap = asp->fas_faelist; 1866 while (frap) { 1867 if (live_kernel == 1) { 1868 if (ioctl(auth_fd, SIOCGENITER, &obj)) 1869 break; 1870 } else { 1871 if (kmemcpy((char *)&fra, (u_long)frap, 1872 sizeof(fra)) == -1) 1873 break; 1874 } 1875 printf("age %ld\t", fra.fae_age); 1876 printfr(&fra.fae_fr, ioctl); 1877 frap = fra.fae_next; 1878 } 1879 } 1880 1881 1882 /* 1883 * Display groups used for each of filter rules, accounting rules and 1884 * authentication, separately. 1885 */ 1886 static void showgroups(fiop) 1887 struct friostat *fiop; 1888 { 1889 static char *gnames[3] = { "Filter", "Accounting", "Authentication" }; 1890 static int gnums[3] = { IPL_LOGIPF, IPL_LOGCOUNT, IPL_LOGAUTH }; 1891 frgroup_t *fp, grp; 1892 int on, off, i; 1893 1894 on = fiop->f_active; 1895 off = 1 - on; 1896 1897 for (i = 0; i < 3; i++) { 1898 printf("%s groups (active):\n", gnames[i]); 1899 for (fp = fiop->f_groups[gnums[i]][on]; fp != NULL; 1900 fp = grp.fg_next) 1901 if (kmemcpy((char *)&grp, (u_long)fp, sizeof(grp))) 1902 break; 1903 else 1904 printf("%s\n", grp.fg_name); 1905 printf("%s groups (inactive):\n", gnames[i]); 1906 for (fp = fiop->f_groups[gnums[i]][off]; fp != NULL; 1907 fp = grp.fg_next) 1908 if (kmemcpy((char *)&grp, (u_long)fp, sizeof(grp))) 1909 break; 1910 else 1911 printf("%s\n", grp.fg_name); 1912 } 1913 } 1914 1915 1916 static void parse_ipportstr(argument, ip, port) 1917 const char *argument; 1918 i6addr_t *ip; 1919 int *port; 1920 { 1921 char *s, *comma; 1922 int ok = 0; 1923 1924 /* make working copy of argument, Theoretically you must be able 1925 * to write to optarg, but that seems very ugly to me.... 1926 */ 1927 s = strdup(argument); 1928 if (s == NULL) 1929 return; 1930 1931 /* get port */ 1932 if ((comma = strchr(s, ',')) != NULL) { 1933 if (!strcasecmp(comma + 1, "any")) { 1934 *port = -1; 1935 } else if (!sscanf(comma + 1, "%d", port) || 1936 (*port < 0) || (*port > 65535)) { 1937 fprintf(stderr, "Invalid port specification in %s\n", 1938 argument); 1939 free(s); 1940 exit(-2); 1941 } 1942 *comma = '\0'; 1943 } 1944 1945 1946 /* get ip address */ 1947 if (!strcasecmp(s, "any")) { 1948 ip->in4.s_addr = INADDR_ANY; 1949 ok = 1; 1950 #ifdef USE_INET6 1951 ip->in6 = in6addr_any; 1952 } else if (use_inet6 && inet_pton(AF_INET6, s, &ip->in6)) { 1953 ok = 1; 1954 #endif 1955 } else if (inet_aton(s, &ip->in4)) 1956 ok = 1; 1957 1958 if (ok == 0) { 1959 fprintf(stderr, "Invalid IP address: %s\n", s); 1960 free(s); 1961 exit(-2); 1962 } 1963 1964 /* free allocated memory */ 1965 free(s); 1966 } 1967 1968 1969 #ifdef STATETOP 1970 static void sig_resize(s) 1971 int s; 1972 { 1973 handle_resize = 1; 1974 } 1975 1976 static void sig_break(s) 1977 int s; 1978 { 1979 handle_break = 1; 1980 } 1981 1982 static char *getip(v, addr) 1983 int v; 1984 i6addr_t *addr; 1985 { 1986 #ifdef USE_INET6 1987 static char hostbuf[MAXHOSTNAMELEN+1]; 1988 #endif 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 sprintf(ttlbuf, "%2d:%02d:%02d", hours, minutes, seconds); 2019 else 2020 sprintf(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) { 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) { 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