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