1 /* 2 * Copyright (C) 1993-2001, 2003 by Darren Reed. 3 * 4 * See the IPFILTER.LICENCE file for details on licencing. 5 * 6 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 7 * Use is subject to license terms. 8 */ 9 10 #pragma ident "%Z%%M% %I% %E% SMI" 11 12 #ifdef __FreeBSD__ 13 # ifndef __FreeBSD_cc_version 14 # include <osreldate.h> 15 # else 16 # if __FreeBSD_cc_version < 430000 17 # include <osreldate.h> 18 # endif 19 # endif 20 #endif 21 #include <sys/ioctl.h> 22 #include <fcntl.h> 23 #include <nlist.h> 24 #include <ctype.h> 25 #include <stddef.h> 26 #include "ipf.h" 27 #include "ipl.h" 28 #if defined(STATETOP) 29 # if defined(_BSDI_VERSION) 30 # undef STATETOP) 31 # endif 32 # if defined(__FreeBSD__) && \ 33 (!defined(__FreeBSD_version) || (__FreeBSD_version < 430000)) 34 # undef STATETOP 35 # endif 36 # if defined(__NetBSD_Version__) && (__NetBSD_Version__ < 105000000) 37 # undef STATETOP 38 # endif 39 # if defined(sun) 40 # if defined(__svr4__) || defined(__SVR4) 41 # include <sys/select.h> 42 # else 43 # undef STATETOP /* NOT supported on SunOS4 */ 44 # endif 45 # endif 46 #endif 47 #if defined(STATETOP) && !defined(linux) 48 # include <netinet/ip_var.h> 49 # include <netinet/tcp_fsm.h> 50 #endif 51 #ifdef STATETOP 52 #if SOLARIS2 >= 10 53 # include "ipl.h" 54 #else 55 # include "netinet/ipl.h" 56 #endif 57 # if SOLARIS || defined(__NetBSD__) || defined(_BSDI_VERSION) || \ 58 defined(__sgi) 59 # ifdef ERR 60 # undef ERR 61 # endif 62 # include <curses.h> 63 # else /* SOLARIS */ 64 # include <ncurses.h> 65 # endif /* SOLARIS */ 66 #endif /* STATETOP */ 67 #include "kmem.h" 68 #if defined(__NetBSD__) || (__OpenBSD__) 69 # include <paths.h> 70 #endif 71 72 #if !defined(lint) 73 static const char sccsid[] = "@(#)fils.c 1.21 4/20/96 (C) 1993-2000 Darren Reed"; 74 static const char rcsid[] = "@(#)$Id: ipfstat.c,v 1.28 2003/07/01 01:03:04 darrenr Exp $"; 75 #endif 76 77 #ifdef __hpux 78 # define nlist nlist64 79 #endif 80 81 extern char *optarg; 82 extern int optind; 83 84 #define PRINTF (void)printf 85 #define FPRINTF (void)fprintf 86 #define F_IN 0 87 #define F_OUT 1 88 #define F_ACIN 2 89 #define F_ACOUT 3 90 static char *filters[4] = { "ipfilter(in)", "ipfilter(out)", 91 "ipacct(in)", "ipacct(out)" }; 92 static int state_logging = -1; 93 94 int opts = 0; 95 int use_inet6 = 0; 96 int live_kernel = 1; 97 int state_fd = -1; 98 int ipf_fd = -1; 99 100 #ifdef STATETOP 101 #define STSTRSIZE 80 102 #define STGROWSIZE 16 103 #define HOSTNMLEN 40 104 105 #define STSORT_PR 0 106 #define STSORT_PKTS 1 107 #define STSORT_BYTES 2 108 #define STSORT_TTL 3 109 #define STSORT_SRCIP 4 110 #define STSORT_DSTIP 5 111 #define STSORT_MAX STSORT_DSTIP 112 #define STSORT_DEFAULT STSORT_BYTES 113 114 115 typedef struct statetop { 116 i6addr_t st_src; 117 i6addr_t st_dst; 118 u_short st_sport; 119 u_short st_dport; 120 u_char st_p; 121 u_char st_state[2]; 122 U_QUAD_T st_pkts; 123 U_QUAD_T st_bytes; 124 u_long st_age; 125 } statetop_t; 126 #endif 127 128 extern int main __P((int, char *[])); 129 static void showstats __P((friostat_t *, u_32_t)); 130 static void showfrstates __P((ipfrstat_t *)); 131 static void showlist __P((friostat_t *)); 132 static void showipstates __P((ips_stat_t *)); 133 static void showauthstates __P((fr_authstat_t *)); 134 static void showgroups __P((friostat_t *)); 135 static void Usage __P((char *)); 136 static void printlist __P((frentry_t *, char *)); 137 static void parse_ipportstr __P((const char *, struct in_addr *, int *)); 138 static void ipfstate_live __P((char *, friostat_t **, ips_stat_t **, 139 ipfrstat_t **, fr_authstat_t **, u_32_t *)); 140 static void ipfstate_dead __P((char *, friostat_t **, ips_stat_t **, 141 ipfrstat_t **, fr_authstat_t **, u_32_t *)); 142 #ifdef STATETOP 143 static void topipstates __P((struct in_addr, struct in_addr, int, int, int, int, int)); 144 static char *ttl_to_string __P((long)); 145 static int sort_p __P((const void *, const void *)); 146 static int sort_pkts __P((const void *, const void *)); 147 static int sort_bytes __P((const void *, const void *)); 148 static int sort_ttl __P((const void *, const void *)); 149 static int sort_srcip __P((const void *, const void *)); 150 static int sort_dstip __P((const void *, const void *)); 151 #endif 152 153 154 static void Usage(name) 155 char *name; 156 { 157 #ifdef USE_INET6 158 fprintf(stderr, "Usage: %s [-6aAfhIinosv] [-d <device>]\n", name); 159 #else 160 fprintf(stderr, "Usage: %s [-aAfhIinosv] [-d <device>]\n", name); 161 #endif 162 fprintf(stderr, "\t\t[-M corefile] [-N symbol-list]\n"); 163 fprintf(stderr, " %s -t [-S source address] [-D destination address] [-P protocol] [-T refreshtime] [-C] [-d <device>]\n", name); 164 exit(1); 165 } 166 167 168 int main(argc,argv) 169 int argc; 170 char *argv[]; 171 { 172 fr_authstat_t frauthst; 173 fr_authstat_t *frauthstp = &frauthst; 174 friostat_t fio; 175 friostat_t *fiop = &fio; 176 ips_stat_t ipsst; 177 ips_stat_t *ipsstp = &ipsst; 178 ipfrstat_t ifrst; 179 ipfrstat_t *ifrstp = &ifrst; 180 char *device = IPL_NAME, *memf = NULL; 181 char *kern = NULL; 182 int c, myoptind; 183 struct protoent *proto; 184 185 int protocol = -1; /* -1 = wild card for any protocol */ 186 int refreshtime = 1; /* default update time */ 187 int sport = -1; /* -1 = wild card for any source port */ 188 int dport = -1; /* -1 = wild card for any dest port */ 189 int topclosed = 0; /* do not show closed tcp sessions */ 190 struct in_addr saddr, daddr; 191 u_32_t frf; 192 193 saddr.s_addr = INADDR_ANY; /* default any source addr */ 194 daddr.s_addr = INADDR_ANY; /* default any dest addr */ 195 196 /* 197 * Parse these two arguments now lest there be any buffer overflows 198 * in the parsing of the rest. 199 */ 200 myoptind = optind; 201 while ((c = getopt(argc, argv, "6aACdfghIilnostvD:M:N:P:S:T:")) != -1) 202 switch (c) 203 { 204 case 'M' : 205 memf = optarg; 206 live_kernel = 0; 207 break; 208 case 'N' : 209 kern = optarg; 210 live_kernel = 0; 211 break; 212 } 213 optind = myoptind; 214 215 if (live_kernel == 1) { 216 if ((state_fd = open(IPSTATE_NAME, O_RDONLY)) == -1) { 217 perror("open"); 218 exit(-1); 219 } 220 if ((ipf_fd = open(device, O_RDONLY)) == -1) { 221 perror("open"); 222 exit(-1); 223 } 224 } 225 226 if (kern != NULL || memf != NULL) 227 { 228 (void)setgid(getgid()); 229 (void)setreuid(getuid(), getuid()); 230 } 231 232 if (openkmem(kern, memf) == -1) 233 exit(-1); 234 235 (void)setgid(getgid()); 236 (void)setreuid(getuid(), getuid()); 237 238 while ((c = getopt(argc, argv, "6aACdfghIilnostvD:M:N:P:S:T:")) != -1) 239 { 240 switch (c) 241 { 242 #ifdef USE_INET6 243 case '6' : 244 use_inet6 = 1; 245 break; 246 #endif 247 case 'a' : 248 opts |= OPT_ACCNT|OPT_SHOWLIST; 249 break; 250 case 'A' : 251 opts |= OPT_AUTHSTATS; 252 break; 253 case 'C' : 254 topclosed = 1; 255 break; 256 case 'd' : 257 opts |= OPT_DEBUG; 258 break; 259 case 'D' : 260 parse_ipportstr(optarg, &daddr, &dport); 261 break; 262 case 'f' : 263 opts |= OPT_FRSTATES; 264 break; 265 case 'g' : 266 opts |= OPT_GROUPS; 267 break; 268 case 'h' : 269 opts |= OPT_HITS; 270 break; 271 case 'i' : 272 opts |= OPT_INQUE|OPT_SHOWLIST; 273 break; 274 case 'I' : 275 opts |= OPT_INACTIVE; 276 break; 277 case 'l' : 278 opts |= OPT_SHOWLIST; 279 break; 280 case 'M' : 281 break; 282 case 'N' : 283 break; 284 case 'n' : 285 opts |= OPT_SHOWLINENO; 286 break; 287 case 'o' : 288 opts |= OPT_OUTQUE|OPT_SHOWLIST; 289 break; 290 case 'P' : 291 if ((proto = getprotobyname(optarg)) != NULL) { 292 protocol = proto->p_proto; 293 } else if (!sscanf(optarg, "%d", &protocol) || 294 (protocol < 0)) { 295 fprintf(stderr, "%s : Invalid protocol: %s\n", 296 argv[0], optarg); 297 exit(-2); 298 } 299 break; 300 case 's' : 301 opts |= OPT_IPSTATES; 302 break; 303 case 'S' : 304 parse_ipportstr(optarg, &saddr, &sport); 305 break; 306 case 't' : 307 #ifdef STATETOP 308 opts |= OPT_STATETOP; 309 break; 310 #else 311 fprintf(stderr, 312 "%s : state top facility not compiled in\n", 313 argv[0]); 314 exit(-2); 315 #endif 316 case 'T' : 317 if (!sscanf(optarg, "%d", &refreshtime) || 318 (refreshtime <= 0)) { 319 fprintf(stderr, 320 "%s : Invalid refreshtime < 1 : %s\n", 321 argv[0], optarg); 322 exit(-2); 323 } 324 break; 325 case 'v' : 326 opts |= OPT_VERBOSE; 327 opts |= OPT_UNDEF; 328 break; 329 default : 330 Usage(argv[0]); 331 break; 332 } 333 } 334 335 if (live_kernel == 1) { 336 bzero((char *)&fio, sizeof(fio)); 337 bzero((char *)&ipsst, sizeof(ipsst)); 338 bzero((char *)&ifrst, sizeof(ifrst)); 339 340 ipfstate_live(device, &fiop, &ipsstp, &ifrstp, 341 &frauthstp, &frf); 342 } else 343 ipfstate_dead(kern, &fiop, &ipsstp, &ifrstp, &frauthstp, &frf); 344 345 if (opts & OPT_IPSTATES) { 346 showipstates(ipsstp); 347 } else if (opts & OPT_SHOWLIST) { 348 showlist(fiop); 349 if ((opts & OPT_OUTQUE) && (opts & OPT_INQUE)){ 350 opts &= ~OPT_OUTQUE; 351 showlist(fiop); 352 } 353 } else { 354 if (opts & OPT_FRSTATES) 355 showfrstates(ifrstp); 356 #ifdef STATETOP 357 else if (opts & OPT_STATETOP) 358 topipstates(saddr, daddr, sport, dport, 359 protocol, refreshtime, topclosed); 360 #endif 361 else if (opts & OPT_AUTHSTATS) 362 showauthstates(frauthstp); 363 else if (opts & OPT_GROUPS) 364 showgroups(fiop); 365 else 366 showstats(fiop, frf); 367 } 368 return 0; 369 } 370 371 372 /* 373 * Fill in the stats structures from the live kernel, using a combination 374 * of ioctl's and copying directly from kernel memory. 375 */ 376 static void ipfstate_live(device, fiopp, ipsstpp, ifrstpp, frauthstpp, frfp) 377 char *device; 378 friostat_t **fiopp; 379 ips_stat_t **ipsstpp; 380 ipfrstat_t **ifrstpp; 381 fr_authstat_t **frauthstpp; 382 u_32_t *frfp; 383 { 384 ipfobj_t ipfo; 385 386 if (checkrev(device) == -1) { 387 fprintf(stderr, "User/kernel version check failed\n"); 388 exit(1); 389 } 390 391 if ((opts & OPT_AUTHSTATS) == 0) { 392 bzero((caddr_t)&ipfo, sizeof(ipfo)); 393 ipfo.ipfo_rev = IPFILTER_VERSION; 394 ipfo.ipfo_size = sizeof(friostat_t); 395 ipfo.ipfo_ptr = (void *)*fiopp; 396 ipfo.ipfo_type = IPFOBJ_IPFSTAT; 397 398 if (ioctl(ipf_fd, SIOCGETFS, &ipfo) == -1) { 399 perror("ioctl(ipf:SIOCGETFS)"); 400 exit(-1); 401 } 402 403 if (ioctl(ipf_fd, SIOCGETFF, frfp) == -1) 404 perror("ioctl(SIOCGETFF)"); 405 } 406 407 if ((opts & OPT_IPSTATES) != 0) { 408 409 bzero((caddr_t)&ipfo, sizeof(ipfo)); 410 ipfo.ipfo_rev = IPFILTER_VERSION; 411 ipfo.ipfo_size = sizeof(ips_stat_t); 412 ipfo.ipfo_ptr = (void *)*ipsstpp; 413 ipfo.ipfo_type = IPFOBJ_STATESTAT; 414 415 if ((ioctl(state_fd, SIOCGETFS, &ipfo) == -1)) { 416 perror("ioctl(state:SIOCGETFS)"); 417 exit(-1); 418 } 419 if (ioctl(state_fd, SIOCGETLG, &state_logging) == -1) { 420 perror("ioctl(state:SIOCGETLG)"); 421 exit(-1); 422 } 423 } 424 425 if ((opts & OPT_FRSTATES) != 0) { 426 bzero((caddr_t)&ipfo, sizeof(ipfo)); 427 ipfo.ipfo_rev = IPFILTER_VERSION; 428 ipfo.ipfo_size = sizeof(ipfrstat_t); 429 ipfo.ipfo_ptr = (void *)*ifrstpp; 430 ipfo.ipfo_type = IPFOBJ_FRAGSTAT; 431 432 if (ioctl(ipf_fd, SIOCGFRST, &ipfo) == -1) { 433 perror("ioctl(SIOCGFRST)"); 434 exit(-1); 435 } 436 } 437 438 if (opts & OPT_VERBOSE) 439 PRINTF("opts %#x name %s\n", opts, device); 440 441 if ((opts & OPT_AUTHSTATS) != 0) { 442 if (ipf_fd >= 0) { 443 close(ipf_fd); 444 ipf_fd = -1; 445 } 446 device = IPAUTH_NAME; 447 if ((ipf_fd = open(device, O_RDONLY)) == -1) { 448 perror("open"); 449 exit(-1); 450 } 451 452 bzero((caddr_t)&ipfo, sizeof(ipfo)); 453 ipfo.ipfo_rev = IPFILTER_VERSION; 454 ipfo.ipfo_size = sizeof(fr_authstat_t); 455 ipfo.ipfo_ptr = (void *)*frauthstpp; 456 ipfo.ipfo_type = IPFOBJ_AUTHSTAT; 457 458 if (ioctl(ipf_fd, SIOCATHST, &ipfo) == -1) { 459 perror("ioctl(SIOCATHST)"); 460 exit(-1); 461 } 462 } 463 } 464 465 466 /* 467 * Build up the stats structures from data held in the "core" memory. 468 * This is mainly useful when looking at data in crash dumps and ioctl's 469 * just won't work any more. 470 */ 471 static void ipfstate_dead(kernel, fiopp, ipsstpp, ifrstpp, frauthstpp, frfp) 472 char *kernel; 473 friostat_t **fiopp; 474 ips_stat_t **ipsstpp; 475 ipfrstat_t **ifrstpp; 476 fr_authstat_t **frauthstpp; 477 u_32_t *frfp; 478 { 479 static fr_authstat_t frauthst, *frauthstp; 480 static ips_stat_t ipsst, *ipsstp; 481 static ipfrstat_t ifrst, *ifrstp; 482 static friostat_t fio, *fiop; 483 int temp; 484 485 void *rules[2][2]; 486 struct nlist deadlist[43] = { 487 { "fr_authstats" }, /* 0 */ 488 { "fae_list" }, 489 { "ipauth" }, 490 { "fr_authlist" }, 491 { "fr_authstart" }, 492 { "fr_authend" }, /* 5 */ 493 { "fr_authnext" }, 494 { "fr_auth" }, 495 { "fr_authused" }, 496 { "fr_authsize" }, 497 { "fr_defaultauthage" }, /* 10 */ 498 { "fr_authpkts" }, 499 { "fr_auth_lock" }, 500 { "frstats" }, 501 { "ips_stats" }, 502 { "ips_num" }, /* 15 */ 503 { "ips_wild" }, 504 { "ips_list" }, 505 { "ips_table" }, 506 { "fr_statemax" }, 507 { "fr_statesize" }, /* 20 */ 508 { "fr_state_doflush" }, 509 { "fr_state_lock" }, 510 { "ipfr_heads" }, 511 { "ipfr_nattab" }, 512 { "ipfr_stats" }, /* 25 */ 513 { "ipfr_inuse" }, 514 { "fr_ipfrttl" }, 515 { "fr_frag_lock" }, 516 { "ipfr_timer_id" }, 517 { "fr_nat_lock" }, /* 30 */ 518 { "ipfilter" }, 519 { "ipfilter6" }, 520 { "ipacct" }, 521 { "ipacct6" }, 522 { "ipl_frouteok" }, /* 35 */ 523 { "fr_running" }, 524 { "ipfgroups" }, 525 { "fr_active" }, 526 { "fr_pass" }, 527 { "fr_flags" }, /* 40 */ 528 { "ipstate_logging" }, 529 { NULL } 530 }; 531 532 533 frauthstp = &frauthst; 534 ipsstp = &ipsst; 535 ifrstp = &ifrst; 536 fiop = &fio; 537 538 *frfp = 0; 539 *fiopp = fiop; 540 *ipsstpp = ipsstp; 541 *ifrstpp = ifrstp; 542 *frauthstpp = frauthstp; 543 544 bzero((char *)fiop, sizeof(*fiop)); 545 bzero((char *)ipsstp, sizeof(*ipsstp)); 546 bzero((char *)ifrstp, sizeof(*ifrstp)); 547 bzero((char *)frauthstp, sizeof(*frauthstp)); 548 549 if (nlist(kernel, deadlist) == -1) { 550 fprintf(stderr, "nlist error\n"); 551 return; 552 } 553 554 /* 555 * This is for SIOCGETFF. 556 */ 557 kmemcpy((char *)frfp, (u_long)deadlist[40].n_value, sizeof(*frfp)); 558 559 /* 560 * f_locks is a combination of the lock variable from each part of 561 * ipfilter (state, auth, nat, fragments). 562 */ 563 kmemcpy((char *)fiop, (u_long)deadlist[13].n_value, sizeof(*fiop)); 564 kmemcpy((char *)&fiop->f_locks[0], (u_long)deadlist[22].n_value, 565 sizeof(fiop->f_locks[0])); 566 kmemcpy((char *)&fiop->f_locks[0], (u_long)deadlist[30].n_value, 567 sizeof(fiop->f_locks[1])); 568 kmemcpy((char *)&fiop->f_locks[2], (u_long)deadlist[28].n_value, 569 sizeof(fiop->f_locks[2])); 570 kmemcpy((char *)&fiop->f_locks[3], (u_long)deadlist[12].n_value, 571 sizeof(fiop->f_locks[3])); 572 573 /* 574 * Get pointers to each list of rules (active, inactive, in, out) 575 */ 576 kmemcpy((char *)&rules, (u_long)deadlist[31].n_value, sizeof(rules)); 577 fiop->f_fin[0] = rules[0][0]; 578 fiop->f_fin[1] = rules[0][1]; 579 fiop->f_fout[0] = rules[1][0]; 580 fiop->f_fout[1] = rules[1][1]; 581 582 /* 583 * Same for IPv6, except make them null if support for it is not 584 * being compiled in. 585 */ 586 #ifdef USE_INET6 587 kmemcpy((char *)&rules, (u_long)deadlist[32].n_value, sizeof(rules)); 588 fiop->f_fin6[0] = rules[0][0]; 589 fiop->f_fin6[1] = rules[0][1]; 590 fiop->f_fout6[0] = rules[1][0]; 591 fiop->f_fout6[1] = rules[1][1]; 592 #else 593 fiop->f_fin6[0] = NULL; 594 fiop->f_fin6[1] = NULL; 595 fiop->f_fout6[0] = NULL; 596 fiop->f_fout6[1] = NULL; 597 #endif 598 599 /* 600 * Now get accounting rules pointers. 601 */ 602 kmemcpy((char *)&rules, (u_long)deadlist[33].n_value, sizeof(rules)); 603 fiop->f_acctin[0] = rules[0][0]; 604 fiop->f_acctin[1] = rules[0][1]; 605 fiop->f_acctout[0] = rules[1][0]; 606 fiop->f_acctout[1] = rules[1][1]; 607 608 #ifdef USE_INET6 609 kmemcpy((char *)&rules, (u_long)deadlist[34].n_value, sizeof(rules)); 610 fiop->f_acctin6[0] = rules[0][0]; 611 fiop->f_acctin6[1] = rules[0][1]; 612 fiop->f_acctout6[0] = rules[1][0]; 613 fiop->f_acctout6[1] = rules[1][1]; 614 #else 615 fiop->f_acctin6[0] = NULL; 616 fiop->f_acctin6[1] = NULL; 617 fiop->f_acctout6[0] = NULL; 618 fiop->f_acctout6[1] = NULL; 619 #endif 620 621 /* 622 * A collection of "global" variables used inside the kernel which 623 * are all collected in friostat_t via ioctl. 624 */ 625 kmemcpy((char *)&fiop->f_froute, (u_long)deadlist[35].n_value, 626 sizeof(fiop->f_froute)); 627 kmemcpy((char *)&fiop->f_running, (u_long)deadlist[36].n_value, 628 sizeof(fiop->f_running)); 629 kmemcpy((char *)&fiop->f_groups, (u_long)deadlist[37].n_value, 630 sizeof(fiop->f_groups)); 631 kmemcpy((char *)&fiop->f_active, (u_long)deadlist[38].n_value, 632 sizeof(fiop->f_active)); 633 kmemcpy((char *)&fiop->f_defpass, (u_long)deadlist[39].n_value, 634 sizeof(fiop->f_defpass)); 635 636 /* 637 * Build up the state information stats structure. 638 */ 639 kmemcpy((char *)ipsstp, (u_long)deadlist[14].n_value, sizeof(*ipsstp)); 640 kmemcpy((char *)&temp, (u_long)deadlist[15].n_value, sizeof(temp)); 641 ipsstp->iss_active = temp; 642 ipsstp->iss_table = (void *)deadlist[18].n_value; 643 ipsstp->iss_list = (void *)deadlist[17].n_value; 644 645 /* 646 * Build up the authentiation information stats structure. 647 */ 648 kmemcpy((char *)frauthstp, (u_long)deadlist[0].n_value, 649 sizeof(*frauthstp)); 650 frauthstp->fas_faelist = (void *)deadlist[1].n_value; 651 652 /* 653 * Build up the fragment information stats structure. 654 */ 655 kmemcpy((char *)ifrstp, (u_long)deadlist[25].n_value, 656 sizeof(*ifrstp)); 657 ifrstp->ifs_table = (void *)deadlist[23].n_value; 658 ifrstp->ifs_nattab = (void *)deadlist[24].n_value; 659 kmemcpy((char *)&ifrstp->ifs_inuse, (u_long)deadlist[26].n_value, 660 sizeof(ifrstp->ifs_inuse)); 661 662 /* 663 * Get logging on/off switches 664 */ 665 kmemcpy((char *)&state_logging, (u_long)deadlist[41].n_value, 666 sizeof(state_logging)); 667 } 668 669 670 /* 671 * Display the kernel stats for packets blocked and passed and other 672 * associated running totals which are kept. 673 */ 674 static void showstats(fp, frf) 675 struct friostat *fp; 676 u_32_t frf; 677 { 678 679 PRINTF("bad packets:\t\tin %lu\tout %lu\n", 680 fp->f_st[0].fr_bad, fp->f_st[1].fr_bad); 681 #ifdef USE_INET6 682 PRINTF(" IPv6 packets:\t\tin %lu out %lu\n", 683 fp->f_st[0].fr_ipv6, fp->f_st[1].fr_ipv6); 684 #endif 685 PRINTF(" input packets:\t\tblocked %lu passed %lu nomatch %lu", 686 fp->f_st[0].fr_block, fp->f_st[0].fr_pass, 687 fp->f_st[0].fr_nom); 688 PRINTF(" counted %lu short %lu\n", 689 fp->f_st[0].fr_acct, fp->f_st[0].fr_short); 690 PRINTF("output packets:\t\tblocked %lu passed %lu nomatch %lu", 691 fp->f_st[1].fr_block, fp->f_st[1].fr_pass, 692 fp->f_st[1].fr_nom); 693 PRINTF(" counted %lu short %lu\n", 694 fp->f_st[1].fr_acct, fp->f_st[1].fr_short); 695 PRINTF(" input packets logged:\tblocked %lu passed %lu\n", 696 fp->f_st[0].fr_bpkl, fp->f_st[0].fr_ppkl); 697 PRINTF("output packets logged:\tblocked %lu passed %lu\n", 698 fp->f_st[1].fr_bpkl, fp->f_st[1].fr_ppkl); 699 PRINTF(" packets logged:\tinput %lu output %lu\n", 700 fp->f_st[0].fr_pkl, fp->f_st[1].fr_pkl); 701 PRINTF(" log failures:\t\tinput %lu output %lu\n", 702 fp->f_st[0].fr_skip, fp->f_st[1].fr_skip); 703 PRINTF("fragment state(in):\tkept %lu\tlost %lu\n", 704 fp->f_st[0].fr_nfr, fp->f_st[0].fr_bnfr); 705 PRINTF("fragment state(out):\tkept %lu\tlost %lu\n", 706 fp->f_st[1].fr_nfr, fp->f_st[1].fr_bnfr); 707 PRINTF("packet state(in):\tkept %lu\tlost %lu\n", 708 fp->f_st[0].fr_ads, fp->f_st[0].fr_bads); 709 PRINTF("packet state(out):\tkept %lu\tlost %lu\n", 710 fp->f_st[1].fr_ads, fp->f_st[1].fr_bads); 711 PRINTF("ICMP replies:\t%lu\tTCP RSTs sent:\t%lu\n", 712 fp->f_st[0].fr_ret, fp->f_st[1].fr_ret); 713 PRINTF("Invalid source(in):\t%lu\n", fp->f_st[0].fr_badsrc); 714 PRINTF("Result cache hits(in):\t%lu\t(out):\t%lu\n", 715 fp->f_st[0].fr_chit, fp->f_st[1].fr_chit); 716 PRINTF("IN Pullups succeeded:\t%lu\tfailed:\t%lu\n", 717 fp->f_st[0].fr_pull[0], fp->f_st[0].fr_pull[1]); 718 PRINTF("OUT Pullups succeeded:\t%lu\tfailed:\t%lu\n", 719 fp->f_st[1].fr_pull[0], fp->f_st[1].fr_pull[1]); 720 PRINTF("Fastroute successes:\t%lu\tfailures:\t%lu\n", 721 fp->f_froute[0], fp->f_froute[1]); 722 PRINTF("TCP cksum fails(in):\t%lu\t(out):\t%lu\n", 723 fp->f_st[0].fr_tcpbad, fp->f_st[1].fr_tcpbad); 724 PRINTF("IPF Ticks:\t%lu\n", fp->f_ticks); 725 726 PRINTF("Packet log flags set: (%#x)\n", frf); 727 if (frf & FF_LOGPASS) 728 PRINTF("\tpackets passed through filter\n"); 729 if (frf & FF_LOGBLOCK) 730 PRINTF("\tpackets blocked by filter\n"); 731 if (frf & FF_LOGNOMATCH) 732 PRINTF("\tpackets not matched by filter\n"); 733 if (!frf) 734 PRINTF("\tnone\n"); 735 } 736 737 738 /* 739 * Print out a list of rules from the kernel, starting at the one passed. 740 */ 741 static void printlist(fp, comment) 742 frentry_t *fp; 743 char *comment; 744 { 745 struct frentry fb, *fg; 746 char *data; 747 u_32_t type; 748 int n; 749 750 for (n = 1; fp; n++) { 751 if (kmemcpy((char *)&fb, (u_long)fp, sizeof(fb)) == -1) { 752 perror("kmemcpy"); 753 return; 754 } 755 fp = &fb; 756 if (opts & (OPT_HITS|OPT_VERBOSE)) 757 #ifdef USE_QUAD_T 758 PRINTF("%qu ", (unsigned long long) fp->fr_hits); 759 #else 760 PRINTF("%lu ", fp->fr_hits); 761 #endif 762 if (opts & (OPT_ACCNT|OPT_VERBOSE)) 763 #ifdef USE_QUAD_T 764 PRINTF("%qu ", (unsigned long long) fp->fr_bytes); 765 #else 766 PRINTF("%lu ", fp->fr_bytes); 767 #endif 768 if (opts & OPT_SHOWLINENO) 769 PRINTF("@%d ", n); 770 data = NULL; 771 type = fp->fr_type & ~FR_T_BUILTIN; 772 if (type == FR_T_IPF || type == FR_T_BPFOPC) { 773 if (fp->fr_dsize) { 774 data = malloc(fp->fr_dsize); 775 if (data == NULL) { 776 perror("malloc"); 777 exit(1); 778 } 779 780 if (kmemcpy(data, (u_long)fp->fr_data, 781 fp->fr_dsize) == -1) { 782 perror("kmemcpy"); 783 return; 784 } 785 fp->fr_data = data; 786 } 787 } 788 789 printfr(fp, ioctl); 790 if (opts & OPT_VERBOSE) { 791 binprint(fp, sizeof(*fp)); 792 if (fp->fr_data != NULL && fp->fr_dsize > 0) 793 binprint(fp->fr_data, fp->fr_dsize); 794 } 795 if (data != NULL) 796 free(data); 797 if (fp->fr_grp != NULL) { 798 if (!kmemcpy((char *)&fg, (u_long)fp->fr_grp, 799 sizeof(fg))) 800 printlist(fg, comment); 801 } 802 if (type == FR_T_CALLFUNC) { 803 printlist(fp->fr_data, "# callfunc: "); 804 } 805 fp = fp->fr_next; 806 } 807 } 808 809 /* 810 * print out all of the asked for rule sets, using the stats struct as 811 * the base from which to get the pointers. 812 */ 813 static void showlist(fiop) 814 struct friostat *fiop; 815 { 816 struct frentry *fp = NULL; 817 int i, set; 818 819 set = fiop->f_active; 820 if (opts & OPT_INACTIVE) 821 set = 1 - set; 822 if (opts & OPT_ACCNT) { 823 #ifdef USE_INET6 824 if ((use_inet6) && (opts & OPT_OUTQUE)) { 825 i = F_ACOUT; 826 fp = (struct frentry *)fiop->f_acctout6[set]; 827 } else if ((use_inet6) && (opts & OPT_INQUE)) { 828 i = F_ACIN; 829 fp = (struct frentry *)fiop->f_acctin6[set]; 830 } else 831 #endif 832 if (opts & OPT_OUTQUE) { 833 i = F_ACOUT; 834 fp = (struct frentry *)fiop->f_acctout[set]; 835 } else if (opts & OPT_INQUE) { 836 i = F_ACIN; 837 fp = (struct frentry *)fiop->f_acctin[set]; 838 } else { 839 FPRINTF(stderr, "No -i or -o given with -a\n"); 840 return; 841 } 842 } else { 843 #ifdef USE_INET6 844 if ((use_inet6) && (opts & OPT_OUTQUE)) { 845 i = F_OUT; 846 fp = (struct frentry *)fiop->f_fout6[set]; 847 } else if ((use_inet6) && (opts & OPT_INQUE)) { 848 i = F_IN; 849 fp = (struct frentry *)fiop->f_fin6[set]; 850 } else 851 #endif 852 if (opts & OPT_OUTQUE) { 853 i = F_OUT; 854 fp = (struct frentry *)fiop->f_fout[set]; 855 } else if (opts & OPT_INQUE) { 856 i = F_IN; 857 fp = (struct frentry *)fiop->f_fin[set]; 858 } else 859 return; 860 } 861 if (opts & OPT_VERBOSE) 862 FPRINTF(stderr, "showlist:opts %#x i %d\n", opts, i); 863 864 if (opts & OPT_VERBOSE) 865 PRINTF("fp %p set %d\n", fp, set); 866 if (!fp) { 867 FPRINTF(stderr, "empty list for %s%s\n", 868 (opts & OPT_INACTIVE) ? "inactive " : "", filters[i]); 869 return; 870 } 871 printlist(fp, NULL); 872 } 873 874 875 /* 876 * Display ipfilter stateful filtering information 877 */ 878 static void showipstates(ipsp) 879 ips_stat_t *ipsp; 880 { 881 u_long minlen, maxlen, totallen, *buckets; 882 int i, sz; 883 884 sz = sizeof(*buckets) * ipsp->iss_statesize; 885 buckets = (u_long *)malloc(sz); 886 if (buckets == NULL) { 887 perror("malloc"); 888 exit(1); 889 } 890 if (kmemcpy((char *)buckets, (u_long)ipsp->iss_bucketlen, sz)) { 891 free(buckets); 892 return; 893 } 894 895 /* 896 * If a list of states hasn't been asked for, only print out stats 897 */ 898 if (!(opts & OPT_SHOWLIST)) { 899 PRINTF("IP states added:\n\t%lu TCP\n\t%lu UDP\n\t%lu ICMP\n", 900 ipsp->iss_tcp, ipsp->iss_udp, ipsp->iss_icmp); 901 PRINTF("\t%lu hits\n\t%lu misses\n", ipsp->iss_hits, 902 ipsp->iss_miss); 903 PRINTF("\t%lu maximum\n\t%lu no memory\n\t%lu max bucket\n", 904 ipsp->iss_max, ipsp->iss_nomem, ipsp->iss_bucketfull); 905 PRINTF("\t%lu active\n\t%lu expired\n\t%lu closed\n", 906 ipsp->iss_active, ipsp->iss_expire, ipsp->iss_fin); 907 908 PRINTF("State logging %sabled\n", 909 state_logging ? "en" : "dis"); 910 911 PRINTF("\nState table bucket statistics:\n"); 912 PRINTF("\t%lu in use\t\n", ipsp->iss_inuse); 913 914 minlen = ipsp->iss_max; 915 totallen = 0; 916 maxlen = 0; 917 918 for (i = 0; i < ipsp->iss_statesize; i++) { 919 if (buckets[i] > maxlen) 920 maxlen = buckets[i]; 921 if (buckets[i] < minlen) 922 minlen = buckets[i]; 923 totallen += buckets[i]; 924 } 925 926 PRINTF("\t%2.2f%% bucket usage\n\t%lu minimal length\n", 927 ((float)ipsp->iss_inuse / ipsp->iss_statesize) * 100.0, 928 minlen); 929 PRINTF("\t%lu maximal length\n\t%.3f average length\n", 930 maxlen, 931 ipsp->iss_inuse ? (float) totallen/ ipsp->iss_inuse : 932 0.0); 933 934 #define ENTRIES_PER_LINE 5 935 936 if (opts & OPT_VERBOSE) { 937 PRINTF("\nCurrent bucket sizes :\n"); 938 for (i = 0; i < ipsp->iss_statesize; i++) { 939 if ((i % ENTRIES_PER_LINE) == 0) 940 PRINTF("\t"); 941 PRINTF("%4d -> %4lu", i, buckets[i]); 942 if ((i % ENTRIES_PER_LINE) == 943 (ENTRIES_PER_LINE - 1)) 944 PRINTF("\n"); 945 else 946 PRINTF(" "); 947 } 948 PRINTF("\n"); 949 } 950 PRINTF("\n"); 951 952 free(buckets); 953 return; 954 } 955 956 /* 957 * Print out all the state information currently held in the kernel. 958 */ 959 while (ipsp->iss_list != NULL) { 960 ipsp->iss_list = printstate(ipsp->iss_list, opts); 961 } 962 963 free(buckets); 964 } 965 966 967 #ifdef STATETOP 968 static void topipstates(saddr, daddr, sport, dport, protocol, 969 refreshtime, topclosed) 970 struct in_addr saddr; 971 struct in_addr daddr; 972 int sport; 973 int dport; 974 int protocol; 975 int refreshtime; 976 int topclosed; 977 { 978 char str1[STSTRSIZE], str2[STSTRSIZE], str3[STSTRSIZE], str4[STSTRSIZE]; 979 int maxtsentries = 0, reverse = 0, sorting = STSORT_DEFAULT; 980 int i, j, winx, tsentry, maxx, maxy, redraw = 0; 981 ips_stat_t ipsst, *ipsstp = &ipsst; 982 statetop_t *tstable = NULL, *tp; 983 ipstate_t ips; 984 ipfobj_t ipfo; 985 struct timeval selecttimeout; 986 char hostnm[HOSTNMLEN]; 987 struct protoent *proto; 988 fd_set readfd; 989 int c = 0; 990 time_t t; 991 992 /* init ncurses stuff */ 993 initscr(); 994 cbreak(); 995 noecho(); 996 997 /* init hostname */ 998 gethostname(hostnm, sizeof(hostnm) - 1); 999 hostnm[sizeof(hostnm) - 1] = '\0'; 1000 1001 /* init ipfobj_t stuff */ 1002 bzero((caddr_t)&ipfo, sizeof(ipfo)); 1003 ipfo.ipfo_rev = IPFILTER_VERSION; 1004 ipfo.ipfo_size = sizeof(*ipsstp); 1005 ipfo.ipfo_ptr = (void *)ipsstp; 1006 ipfo.ipfo_type = IPFOBJ_STATESTAT; 1007 1008 /* repeat until user aborts */ 1009 while ( 1 ) { 1010 1011 /* get state table */ 1012 bzero((char *)&ipsst, sizeof(ipsst)); 1013 if ((ioctl(state_fd, SIOCGETFS, &ipfo) == -1)) { 1014 perror("ioctl(SIOCGETFS)"); 1015 break; 1016 } 1017 1018 /* clear the history */ 1019 tsentry = -1; 1020 1021 /* read the state table and store in tstable */ 1022 while (ipsstp->iss_list) { 1023 if (kmemcpy((char *)&ips, (u_long)ipsstp->iss_list, 1024 sizeof(ips))) 1025 break; 1026 ipsstp->iss_list = ips.is_next; 1027 1028 if (((saddr.s_addr == INADDR_ANY) || 1029 (saddr.s_addr == ips.is_saddr)) && 1030 ((daddr.s_addr == INADDR_ANY) || 1031 (daddr.s_addr == ips.is_daddr)) && 1032 ((protocol < 0) || (protocol == ips.is_p)) && 1033 (((ips.is_p != IPPROTO_TCP) && 1034 (ips.is_p != IPPROTO_UDP)) || 1035 (((sport < 0) || 1036 (htons(sport) == ips.is_sport)) && 1037 ((dport < 0) || 1038 (htons(dport) == ips.is_dport)))) && 1039 (topclosed || (ips.is_p != IPPROTO_TCP) || 1040 (ips.is_state[0] < TCPS_LAST_ACK) || 1041 (ips.is_state[1] < TCPS_LAST_ACK))) { 1042 /* 1043 * if necessary make room for this state 1044 * entry 1045 */ 1046 tsentry++; 1047 if (!maxtsentries || 1048 (tsentry == maxtsentries)) { 1049 1050 maxtsentries += STGROWSIZE; 1051 tstable = realloc(tstable, maxtsentries * sizeof(statetop_t)); 1052 if (!tstable) { 1053 perror("malloc"); 1054 goto breakout; 1055 } 1056 } 1057 1058 /* fill structure */ 1059 tp = tstable + tsentry; 1060 tp->st_src = ips.is_src; 1061 tp->st_dst = ips.is_dst; 1062 tp->st_p = ips.is_p; 1063 tp->st_state[0] = ips.is_state[0]; 1064 tp->st_state[1] = ips.is_state[1]; 1065 tp->st_pkts = ips.is_pkts[0] + ips.is_pkts[1]; 1066 tp->st_bytes = ips.is_bytes[0] + 1067 ips.is_bytes[1]; 1068 tp->st_age = ips.is_die - ipsstp->iss_ticks; 1069 if ((ips.is_p == IPPROTO_TCP) || 1070 (ips.is_p == IPPROTO_UDP)) { 1071 tp->st_sport = ips.is_sport; 1072 tp->st_dport = ips.is_dport; 1073 } 1074 1075 } 1076 } 1077 1078 1079 /* sort the array */ 1080 if (tsentry != -1) 1081 switch (sorting) 1082 { 1083 case STSORT_PR: 1084 qsort(tstable, tsentry + 1, 1085 sizeof(statetop_t), sort_p); 1086 break; 1087 case STSORT_PKTS: 1088 qsort(tstable, tsentry + 1, 1089 sizeof(statetop_t), sort_pkts); 1090 break; 1091 case STSORT_BYTES: 1092 qsort(tstable, tsentry + 1, 1093 sizeof(statetop_t), sort_bytes); 1094 break; 1095 case STSORT_TTL: 1096 qsort(tstable, tsentry + 1, 1097 sizeof(statetop_t), sort_ttl); 1098 break; 1099 case STSORT_SRCIP: 1100 qsort(tstable, tsentry + 1, 1101 sizeof(statetop_t), sort_srcip); 1102 break; 1103 case STSORT_DSTIP: 1104 qsort(tstable, tsentry + 1, 1105 sizeof(statetop_t), sort_dstip); 1106 break; 1107 default: 1108 break; 1109 } 1110 1111 /* print title */ 1112 erase(); 1113 getmaxyx(stdscr, maxy, maxx); 1114 attron(A_BOLD); 1115 winx = 0; 1116 move(winx,0); 1117 sprintf(str1, "%s - %s - state top", hostnm, IPL_VERSION); 1118 for (j = 0 ; j < (maxx - 8 - strlen(str1)) / 2; j++) 1119 printw(" "); 1120 printw("%s", str1); 1121 attroff(A_BOLD); 1122 1123 /* just for fun add a clock */ 1124 move(winx, maxx - 8); 1125 t = time(NULL); 1126 strftime(str1, 80, "%T", localtime(&t)); 1127 printw("%s\n", str1); 1128 1129 /* 1130 * print the display filters, this is placed in the loop, 1131 * because someday I might add code for changing these 1132 * while the programming is running :-) 1133 */ 1134 if (sport >= 0) 1135 sprintf(str1, "%s,%d", inet_ntoa(saddr), sport); 1136 else 1137 sprintf(str1, "%s", inet_ntoa(saddr)); 1138 1139 if (dport >= 0) 1140 sprintf(str2, "%s,%d", inet_ntoa(daddr), dport); 1141 else 1142 sprintf(str2, "%s", inet_ntoa(daddr)); 1143 1144 if (protocol < 0) 1145 strcpy(str3, "any"); 1146 else if ((proto = getprotobynumber(protocol)) != NULL) 1147 sprintf(str3, "%s", proto->p_name); 1148 else 1149 sprintf(str3, "%d", protocol); 1150 1151 switch (sorting) 1152 { 1153 case STSORT_PR: 1154 sprintf(str4, "proto"); 1155 break; 1156 case STSORT_PKTS: 1157 sprintf(str4, "# pkts"); 1158 break; 1159 case STSORT_BYTES: 1160 sprintf(str4, "# bytes"); 1161 break; 1162 case STSORT_TTL: 1163 sprintf(str4, "ttl"); 1164 break; 1165 case STSORT_SRCIP: 1166 sprintf(str4, "srcip"); 1167 break; 1168 case STSORT_DSTIP: 1169 sprintf(str4, "dstip"); 1170 break; 1171 default: 1172 sprintf(str4, "unknown"); 1173 break; 1174 } 1175 1176 if (reverse) 1177 strcat(str4, " (reverse)"); 1178 1179 winx += 2; 1180 move(winx,0); 1181 printw("Src = %s Dest = %s Proto = %s Sorted by = %s\n\n", 1182 str1, str2, str3, str4); 1183 1184 /* print column description */ 1185 winx += 2; 1186 move(winx,0); 1187 attron(A_BOLD); 1188 printw("%-21s %-21s %3s %4s %7s %9s %9s\n", "Source IP", 1189 "Destination IP", "ST", "PR", "#pkts", "#bytes", "ttl"); 1190 attroff(A_BOLD); 1191 1192 /* print all the entries */ 1193 tp = tstable; 1194 if (reverse) 1195 tp += tsentry; 1196 1197 if (tsentry > maxy - 6) 1198 tsentry = maxy - 6; 1199 for (i = 0; i <= tsentry; i++) { 1200 /* print src/dest and port */ 1201 if ((tp->st_p == IPPROTO_TCP) || 1202 (tp->st_p == IPPROTO_UDP)) { 1203 sprintf(str1, "%s,%hu", 1204 inet_ntoa(tp->st_src.in4), 1205 ntohs(tp->st_sport)); 1206 sprintf(str2, "%s,%hu", 1207 inet_ntoa(tp->st_dst.in4), 1208 ntohs(tp->st_dport)); 1209 } else { 1210 sprintf(str1, "%s", inet_ntoa(tp->st_src.in4)); 1211 sprintf(str2, "%s", inet_ntoa(tp->st_dst.in4)); 1212 } 1213 winx++; 1214 move(winx, 0); 1215 printw("%-21s %-21s", str1, str2); 1216 1217 /* print state */ 1218 sprintf(str1, "%X/%X", tp->st_state[0], 1219 tp->st_state[1]); 1220 printw(" %3s", str1); 1221 1222 /* print proto */ 1223 proto = getprotobynumber(tp->st_p); 1224 if (proto) { 1225 strncpy(str1, proto->p_name, 4); 1226 str1[4] = '\0'; 1227 } else { 1228 sprintf(str1, "%d", tp->st_p); 1229 } 1230 printw(" %4s", str1); 1231 /* print #pkt/#bytes */ 1232 #ifdef USE_QUAD_T 1233 printw(" %7qu %9qu", (unsigned long long) tp->st_pkts, 1234 (unsigned long long) tp->st_bytes); 1235 #else 1236 printw(" %7lu %9lu", tp->st_pkts, tp->st_bytes); 1237 #endif 1238 printw(" %9s", ttl_to_string(tp->st_age)); 1239 1240 if (reverse) 1241 tp--; 1242 else 1243 tp++; 1244 } 1245 1246 /* screen data structure is filled, now update the screen */ 1247 if (redraw) 1248 clearok(stdscr,1); 1249 1250 refresh(); 1251 if (redraw) { 1252 clearok(stdscr,0); 1253 redraw = 0; 1254 } 1255 1256 /* wait for key press or a 1 second time out period */ 1257 selecttimeout.tv_sec = refreshtime; 1258 selecttimeout.tv_usec = 0; 1259 FD_ZERO(&readfd); 1260 FD_SET(0, &readfd); 1261 select(1, &readfd, NULL, NULL, &selecttimeout); 1262 1263 /* if key pressed, read all waiting keys */ 1264 if (FD_ISSET(0, &readfd)) { 1265 c = wgetch(stdscr); 1266 if (c == ERR) 1267 continue; 1268 1269 if (tolower(c) == 'l') { 1270 redraw = 1; 1271 } else if (tolower(c) == 'q') { 1272 break; 1273 } else if (tolower(c) == 'r') { 1274 reverse = !reverse; 1275 } else if (tolower(c) == 's') { 1276 sorting++; 1277 if (sorting > STSORT_MAX) 1278 sorting = 0; 1279 } 1280 } 1281 } /* while */ 1282 1283 breakout: 1284 printw("\n"); 1285 nocbreak(); 1286 endwin(); 1287 1288 if (tstable != NULL) 1289 free(tstable); 1290 } 1291 #endif 1292 1293 1294 /* 1295 * Show fragment cache information that's held in the kernel. 1296 */ 1297 static void showfrstates(ifsp) 1298 ipfrstat_t *ifsp; 1299 { 1300 struct ipfr *ipfrtab[IPFT_SIZE], ifr; 1301 frentry_t fr; 1302 int i; 1303 1304 /* 1305 * print out the numeric statistics 1306 */ 1307 PRINTF("IP fragment states:\n\t%lu new\n\t%lu expired\n\t%lu hits\n", 1308 ifsp->ifs_new, ifsp->ifs_expire, ifsp->ifs_hits); 1309 PRINTF("\t%lu retrans\n\t%lu too short\n", ifsp->ifs_retrans0, ifsp->ifs_short); 1310 PRINTF("\t%lu no memory\n\t%lu already exist\n", 1311 ifsp->ifs_nomem, ifsp->ifs_exists); 1312 PRINTF("\t%lu inuse\n", ifsp->ifs_inuse); 1313 if (kmemcpy((char *)ipfrtab, (u_long)ifsp->ifs_table, sizeof(ipfrtab))) 1314 return; 1315 1316 /* 1317 * Print out the contents (if any) of the fragment cache table. 1318 */ 1319 for (i = 0; i < IPFT_SIZE; i++) 1320 while (ipfrtab[i]) { 1321 if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i], 1322 sizeof(ifr)) == -1) 1323 break; 1324 PRINTF("%s -> ", hostname(4, &ifr.ipfr_src)); 1325 if (kmemcpy((char *)&fr, (u_long)ifr.ipfr_rule, 1326 sizeof(fr)) == -1) 1327 break; 1328 PRINTF("%s %d %d %d %#02x = %#x\n", 1329 hostname(4, &ifr.ipfr_dst), ifr.ipfr_id, 1330 ifr.ipfr_ttl, ifr.ipfr_p, ifr.ipfr_tos, 1331 fr.fr_flags); 1332 ipfrtab[i] = ifr.ipfr_next; 1333 } 1334 if (kmemcpy((char *)ipfrtab, (u_long)ifsp->ifs_nattab,sizeof(ipfrtab))) 1335 return; 1336 for (i = 0; i < IPFT_SIZE; i++) 1337 while (ipfrtab[i]) { 1338 if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i], 1339 sizeof(ifr)) == -1) 1340 break; 1341 PRINTF("NAT: %s -> ", hostname(4, &ifr.ipfr_src)); 1342 if (kmemcpy((char *)&fr, (u_long)ifr.ipfr_rule, 1343 sizeof(fr)) == -1) 1344 break; 1345 PRINTF("%s %d %d %d %#02x = %#x\n", 1346 hostname(4, &ifr.ipfr_dst), ifr.ipfr_id, 1347 ifr.ipfr_ttl, ifr.ipfr_p, ifr.ipfr_tos, 1348 fr.fr_flags); 1349 ipfrtab[i] = ifr.ipfr_next; 1350 } 1351 } 1352 1353 1354 /* 1355 * Show stats on how auth within IPFilter has been used 1356 */ 1357 static void showauthstates(asp) 1358 fr_authstat_t *asp; 1359 { 1360 frauthent_t *frap, fra; 1361 1362 #ifdef USE_QUAD_T 1363 printf("Authorisation hits: %qu\tmisses %qu\n", 1364 (unsigned long long) asp->fas_hits, 1365 (unsigned long long) asp->fas_miss); 1366 #else 1367 printf("Authorisation hits: %ld\tmisses %ld\n", asp->fas_hits, 1368 asp->fas_miss); 1369 #endif 1370 printf("nospace %ld\nadded %ld\nsendfail %ld\nsendok %ld\n", 1371 asp->fas_nospace, asp->fas_added, asp->fas_sendfail, 1372 asp->fas_sendok); 1373 printf("queok %ld\nquefail %ld\nexpire %ld\n", 1374 asp->fas_queok, asp->fas_quefail, asp->fas_expire); 1375 1376 frap = asp->fas_faelist; 1377 while (frap) { 1378 if (kmemcpy((char *)&fra, (u_long)frap, sizeof(fra)) == -1) 1379 break; 1380 1381 printf("age %ld\t", fra.fae_age); 1382 printfr(&fra.fae_fr, ioctl); 1383 frap = fra.fae_next; 1384 } 1385 } 1386 1387 1388 /* 1389 * Display groups used for each of filter rules, accounting rules and 1390 * authentication, separately. 1391 */ 1392 static void showgroups(fiop) 1393 struct friostat *fiop; 1394 { 1395 static char *gnames[3] = { "Filter", "Accounting", "Authentication" }; 1396 frgroup_t *fp, grp; 1397 int on, off, i; 1398 1399 on = fiop->f_active; 1400 off = 1 - on; 1401 1402 for (i = 0; i < 3; i++) { 1403 printf("%s groups (active):\n", gnames[i]); 1404 for (fp = fiop->f_groups[i][on]; fp; fp = grp.fg_next) 1405 if (kmemcpy((char *)&grp, (u_long)fp, sizeof(grp))) 1406 break; 1407 else 1408 printf("%s\n", grp.fg_name); 1409 printf("%s groups (inactive):\n", gnames[i]); 1410 for (fp = fiop->f_groups[i][off]; fp; fp = grp.fg_next) 1411 if (kmemcpy((char *)&grp, (u_long)fp, sizeof(grp))) 1412 break; 1413 else 1414 printf("%s\n", grp.fg_name); 1415 } 1416 } 1417 1418 static void parse_ipportstr(argument, ip, port) 1419 const char *argument; 1420 struct in_addr *ip; 1421 int *port; 1422 { 1423 1424 char *s, *comma; 1425 1426 /* make working copy of argument, Theoretically you must be able 1427 * to write to optarg, but that seems very ugly to me.... 1428 */ 1429 s = strdup(argument); 1430 if (s == NULL) 1431 return; 1432 1433 /* get port */ 1434 if ((comma = strchr(s, ',')) != NULL) { 1435 if (!strcasecmp(comma + 1, "any")) { 1436 *port = -1; 1437 } else if (!sscanf(comma + 1, "%d", port) || 1438 (*port < 0) || (*port > 65535)) { 1439 fprintf(stderr, "Invalid port specfication in %s\n", 1440 argument); 1441 free(s); 1442 exit(-2); 1443 } 1444 *comma = '\0'; 1445 } 1446 1447 1448 /* get ip address */ 1449 if (!strcasecmp(s, "any")) { 1450 ip->s_addr = INADDR_ANY; 1451 } else if (!inet_aton(s, ip)) { 1452 fprintf(stderr, "Invalid IP address: %s\n", s); 1453 free(s); 1454 exit(-2); 1455 } 1456 1457 /* free allocated memory */ 1458 free(s); 1459 } 1460 1461 1462 #ifdef STATETOP 1463 static char ttlbuf[STSTRSIZE]; 1464 1465 static char *ttl_to_string(ttl) 1466 long int ttl; 1467 { 1468 1469 int hours, minutes, seconds; 1470 1471 /* ttl is in half seconds */ 1472 ttl /= 2; 1473 1474 hours = ttl / 3600; 1475 ttl = ttl % 3600; 1476 minutes = ttl / 60; 1477 seconds = ttl % 60; 1478 1479 if (hours > 0 ) 1480 sprintf(ttlbuf, "%2d:%02d:%02d", hours, minutes, seconds); 1481 else 1482 sprintf(ttlbuf, "%2d:%02d", minutes, seconds); 1483 return ttlbuf; 1484 } 1485 1486 1487 static int sort_pkts(a, b) 1488 const void *a; 1489 const void *b; 1490 { 1491 1492 register const statetop_t *ap = a; 1493 register const statetop_t *bp = b; 1494 1495 if (ap->st_pkts == bp->st_pkts) 1496 return 0; 1497 else if (ap->st_pkts < bp->st_pkts) 1498 return 1; 1499 return -1; 1500 } 1501 1502 1503 static int sort_bytes(a, b) 1504 const void *a; 1505 const void *b; 1506 { 1507 register const statetop_t *ap = a; 1508 register const statetop_t *bp = b; 1509 1510 if (ap->st_bytes == bp->st_bytes) 1511 return 0; 1512 else if (ap->st_bytes < bp->st_bytes) 1513 return 1; 1514 return -1; 1515 } 1516 1517 1518 static int sort_p(a, b) 1519 const void *a; 1520 const void *b; 1521 { 1522 register const statetop_t *ap = a; 1523 register const statetop_t *bp = b; 1524 1525 if (ap->st_p == bp->st_p) 1526 return 0; 1527 else if (ap->st_p < bp->st_p) 1528 return 1; 1529 return -1; 1530 } 1531 1532 1533 static int sort_ttl(a, b) 1534 const void *a; 1535 const void *b; 1536 { 1537 register const statetop_t *ap = a; 1538 register const statetop_t *bp = b; 1539 1540 if (ap->st_age == bp->st_age) 1541 return 0; 1542 else if (ap->st_age < bp->st_age) 1543 return 1; 1544 return -1; 1545 } 1546 1547 static int sort_srcip(a, b) 1548 const void *a; 1549 const void *b; 1550 { 1551 register const statetop_t *ap = a; 1552 register const statetop_t *bp = b; 1553 1554 if (ntohl(ap->st_src.in4.s_addr) == ntohl(bp->st_src.in4.s_addr)) 1555 return 0; 1556 else if (ntohl(ap->st_src.in4.s_addr) > ntohl(bp->st_src.in4.s_addr)) 1557 return 1; 1558 return -1; 1559 } 1560 1561 static int sort_dstip(a, b) 1562 const void *a; 1563 const void *b; 1564 { 1565 register const statetop_t *ap = a; 1566 register const statetop_t *bp = b; 1567 1568 if (ntohl(ap->st_dst.in4.s_addr) == ntohl(bp->st_dst.in4.s_addr)) 1569 return 0; 1570 else if (ntohl(ap->st_dst.in4.s_addr) > ntohl(bp->st_dst.in4.s_addr)) 1571 return 1; 1572 return -1; 1573 } 1574 #endif 1575