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