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 776 if (kmemcpy(data, (u_long)fp->fr_data, 777 fp->fr_dsize) == -1) { 778 perror("kmemcpy"); 779 return; 780 } 781 fp->fr_data = data; 782 } 783 } 784 785 printfr(fp, ioctl); 786 if (opts & OPT_VERBOSE) { 787 binprint(fp, sizeof(*fp)); 788 if (fp->fr_data != NULL && fp->fr_dsize > 0) 789 binprint(fp->fr_data, fp->fr_dsize); 790 } 791 if (data != NULL) 792 free(data); 793 if (fp->fr_grp != NULL) { 794 if (!kmemcpy((char *)&fg, (u_long)fp->fr_grp, 795 sizeof(fg))) 796 printlist(fg, comment); 797 } 798 if (type == FR_T_CALLFUNC) { 799 printlist(fp->fr_data, "# callfunc: "); 800 } 801 fp = fp->fr_next; 802 } 803 } 804 805 /* 806 * print out all of the asked for rule sets, using the stats struct as 807 * the base from which to get the pointers. 808 */ 809 static void showlist(fiop) 810 struct friostat *fiop; 811 { 812 struct frentry *fp = NULL; 813 int i, set; 814 815 set = fiop->f_active; 816 if (opts & OPT_INACTIVE) 817 set = 1 - set; 818 if (opts & OPT_ACCNT) { 819 #ifdef USE_INET6 820 if ((use_inet6) && (opts & OPT_OUTQUE)) { 821 i = F_ACOUT; 822 fp = (struct frentry *)fiop->f_acctout6[set]; 823 } else if ((use_inet6) && (opts & OPT_INQUE)) { 824 i = F_ACIN; 825 fp = (struct frentry *)fiop->f_acctin6[set]; 826 } else 827 #endif 828 if (opts & OPT_OUTQUE) { 829 i = F_ACOUT; 830 fp = (struct frentry *)fiop->f_acctout[set]; 831 } else if (opts & OPT_INQUE) { 832 i = F_ACIN; 833 fp = (struct frentry *)fiop->f_acctin[set]; 834 } else { 835 FPRINTF(stderr, "No -i or -o given with -a\n"); 836 return; 837 } 838 } else { 839 #ifdef USE_INET6 840 if ((use_inet6) && (opts & OPT_OUTQUE)) { 841 i = F_OUT; 842 fp = (struct frentry *)fiop->f_fout6[set]; 843 } else if ((use_inet6) && (opts & OPT_INQUE)) { 844 i = F_IN; 845 fp = (struct frentry *)fiop->f_fin6[set]; 846 } else 847 #endif 848 if (opts & OPT_OUTQUE) { 849 i = F_OUT; 850 fp = (struct frentry *)fiop->f_fout[set]; 851 } else if (opts & OPT_INQUE) { 852 i = F_IN; 853 fp = (struct frentry *)fiop->f_fin[set]; 854 } else 855 return; 856 } 857 if (opts & OPT_VERBOSE) 858 FPRINTF(stderr, "showlist:opts %#x i %d\n", opts, i); 859 860 if (opts & OPT_VERBOSE) 861 PRINTF("fp %p set %d\n", fp, set); 862 if (!fp) { 863 FPRINTF(stderr, "empty list for %s%s\n", 864 (opts & OPT_INACTIVE) ? "inactive " : "", filters[i]); 865 return; 866 } 867 printlist(fp, NULL); 868 } 869 870 871 /* 872 * Display ipfilter stateful filtering information 873 */ 874 static void showipstates(ipsp) 875 ips_stat_t *ipsp; 876 { 877 u_long minlen, maxlen, totallen, *buckets; 878 int i, sz; 879 880 sz = sizeof(*buckets) * ipsp->iss_statesize; 881 buckets = (u_long *)malloc(sz); 882 if (kmemcpy((char *)buckets, (u_long)ipsp->iss_bucketlen, sz)) { 883 free(buckets); 884 return; 885 } 886 887 /* 888 * If a list of states hasn't been asked for, only print out stats 889 */ 890 if (!(opts & OPT_SHOWLIST)) { 891 PRINTF("IP states added:\n\t%lu TCP\n\t%lu UDP\n\t%lu ICMP\n", 892 ipsp->iss_tcp, ipsp->iss_udp, ipsp->iss_icmp); 893 PRINTF("\t%lu hits\n\t%lu misses\n", ipsp->iss_hits, 894 ipsp->iss_miss); 895 PRINTF("\t%lu maximum\n\t%lu no memory\n\t%lu max bucket\n", 896 ipsp->iss_max, ipsp->iss_nomem, ipsp->iss_bucketfull); 897 PRINTF("\t%lu active\n\t%lu expired\n\t%lu closed\n", 898 ipsp->iss_active, ipsp->iss_expire, ipsp->iss_fin); 899 900 PRINTF("State logging %sabled\n", 901 state_logging ? "en" : "dis"); 902 903 PRINTF("\nState table bucket statistics:\n"); 904 PRINTF("\t%lu in use\t\n", ipsp->iss_inuse); 905 906 minlen = ipsp->iss_max; 907 totallen = 0; 908 maxlen = 0; 909 910 for (i = 0; i < ipsp->iss_statesize; i++) { 911 if (buckets[i] > maxlen) 912 maxlen = buckets[i]; 913 if (buckets[i] < minlen) 914 minlen = buckets[i]; 915 totallen += buckets[i]; 916 } 917 918 PRINTF("\t%2.2f%% bucket usage\n\t%lu minimal length\n", 919 ((float)ipsp->iss_inuse / ipsp->iss_statesize) * 100.0, 920 minlen); 921 PRINTF("\t%lu maximal length\n\t%.3f average length\n", 922 maxlen, 923 ipsp->iss_inuse ? (float) totallen/ ipsp->iss_inuse : 924 0.0); 925 926 #define ENTRIES_PER_LINE 5 927 928 if (opts & OPT_VERBOSE) { 929 PRINTF("\nCurrent bucket sizes :\n"); 930 for (i = 0; i < ipsp->iss_statesize; i++) { 931 if ((i % ENTRIES_PER_LINE) == 0) 932 PRINTF("\t"); 933 PRINTF("%4d -> %4lu", i, buckets[i]); 934 if ((i % ENTRIES_PER_LINE) == 935 (ENTRIES_PER_LINE - 1)) 936 PRINTF("\n"); 937 else 938 PRINTF(" "); 939 } 940 PRINTF("\n"); 941 } 942 PRINTF("\n"); 943 944 free(buckets); 945 return; 946 } 947 948 /* 949 * Print out all the state information currently held in the kernel. 950 */ 951 while (ipsp->iss_list != NULL) { 952 ipsp->iss_list = printstate(ipsp->iss_list, opts); 953 } 954 955 free(buckets); 956 } 957 958 959 #ifdef STATETOP 960 static void topipstates(saddr, daddr, sport, dport, protocol, 961 refreshtime, topclosed) 962 struct in_addr saddr; 963 struct in_addr daddr; 964 int sport; 965 int dport; 966 int protocol; 967 int refreshtime; 968 int topclosed; 969 { 970 char str1[STSTRSIZE], str2[STSTRSIZE], str3[STSTRSIZE], str4[STSTRSIZE]; 971 int maxtsentries = 0, reverse = 0, sorting = STSORT_DEFAULT; 972 int i, j, winx, tsentry, maxx, maxy, redraw = 0; 973 ips_stat_t ipsst, *ipsstp = &ipsst; 974 statetop_t *tstable = NULL, *tp; 975 ipstate_t ips; 976 ipfobj_t ipfo; 977 struct timeval selecttimeout; 978 char hostnm[HOSTNMLEN]; 979 struct protoent *proto; 980 fd_set readfd; 981 int c = 0; 982 time_t t; 983 984 /* init ncurses stuff */ 985 initscr(); 986 cbreak(); 987 noecho(); 988 989 /* init hostname */ 990 gethostname(hostnm, sizeof(hostnm) - 1); 991 hostnm[sizeof(hostnm) - 1] = '\0'; 992 993 /* init ipfobj_t stuff */ 994 bzero((caddr_t)&ipfo, sizeof(ipfo)); 995 ipfo.ipfo_rev = IPFILTER_VERSION; 996 ipfo.ipfo_size = sizeof(*ipsstp); 997 ipfo.ipfo_ptr = (void *)ipsstp; 998 ipfo.ipfo_type = IPFOBJ_STATESTAT; 999 1000 /* repeat until user aborts */ 1001 while ( 1 ) { 1002 1003 /* get state table */ 1004 bzero((char *)&ipsst, sizeof(ipsst)); 1005 if ((ioctl(state_fd, SIOCGETFS, &ipfo) == -1)) { 1006 perror("ioctl(SIOCGETFS)"); 1007 exit(-1); 1008 } 1009 1010 /* clear the history */ 1011 tsentry = -1; 1012 1013 /* read the state table and store in tstable */ 1014 while (ipsstp->iss_list) { 1015 if (kmemcpy((char *)&ips, (u_long)ipsstp->iss_list, 1016 sizeof(ips))) 1017 break; 1018 ipsstp->iss_list = ips.is_next; 1019 1020 if (((saddr.s_addr == INADDR_ANY) || 1021 (saddr.s_addr == ips.is_saddr)) && 1022 ((daddr.s_addr == INADDR_ANY) || 1023 (daddr.s_addr == ips.is_daddr)) && 1024 ((protocol < 0) || (protocol == ips.is_p)) && 1025 (((ips.is_p != IPPROTO_TCP) && 1026 (ips.is_p != IPPROTO_UDP)) || 1027 (((sport < 0) || 1028 (htons(sport) == ips.is_sport)) && 1029 ((dport < 0) || 1030 (htons(dport) == ips.is_dport)))) && 1031 (topclosed || (ips.is_p != IPPROTO_TCP) || 1032 (ips.is_state[0] < TCPS_LAST_ACK) || 1033 (ips.is_state[1] < TCPS_LAST_ACK))) { 1034 /* 1035 * if necessary make room for this state 1036 * entry 1037 */ 1038 tsentry++; 1039 if (!maxtsentries || 1040 (tsentry == maxtsentries)) { 1041 1042 maxtsentries += STGROWSIZE; 1043 tstable = realloc(tstable, maxtsentries * sizeof(statetop_t)); 1044 if (!tstable) { 1045 perror("malloc"); 1046 exit(-1); 1047 } 1048 } 1049 1050 /* fill structure */ 1051 tp = tstable + tsentry; 1052 tp->st_src = ips.is_src; 1053 tp->st_dst = ips.is_dst; 1054 tp->st_p = ips.is_p; 1055 tp->st_state[0] = ips.is_state[0]; 1056 tp->st_state[1] = ips.is_state[1]; 1057 tp->st_pkts = ips.is_pkts[0] + ips.is_pkts[1]; 1058 tp->st_bytes = ips.is_bytes[0] + 1059 ips.is_bytes[1]; 1060 tp->st_age = ips.is_die - ipsstp->iss_ticks; 1061 if ((ips.is_p == IPPROTO_TCP) || 1062 (ips.is_p == IPPROTO_UDP)) { 1063 tp->st_sport = ips.is_sport; 1064 tp->st_dport = ips.is_dport; 1065 } 1066 1067 } 1068 } 1069 1070 1071 /* sort the array */ 1072 if (tsentry != -1) 1073 switch (sorting) 1074 { 1075 case STSORT_PR: 1076 qsort(tstable, tsentry + 1, 1077 sizeof(statetop_t), sort_p); 1078 break; 1079 case STSORT_PKTS: 1080 qsort(tstable, tsentry + 1, 1081 sizeof(statetop_t), sort_pkts); 1082 break; 1083 case STSORT_BYTES: 1084 qsort(tstable, tsentry + 1, 1085 sizeof(statetop_t), sort_bytes); 1086 break; 1087 case STSORT_TTL: 1088 qsort(tstable, tsentry + 1, 1089 sizeof(statetop_t), sort_ttl); 1090 break; 1091 case STSORT_SRCIP: 1092 qsort(tstable, tsentry + 1, 1093 sizeof(statetop_t), sort_srcip); 1094 break; 1095 case STSORT_DSTIP: 1096 qsort(tstable, tsentry + 1, 1097 sizeof(statetop_t), sort_dstip); 1098 break; 1099 default: 1100 break; 1101 } 1102 1103 /* print title */ 1104 erase(); 1105 getmaxyx(stdscr, maxy, maxx); 1106 attron(A_BOLD); 1107 winx = 0; 1108 move(winx,0); 1109 sprintf(str1, "%s - %s - state top", hostnm, IPL_VERSION); 1110 for (j = 0 ; j < (maxx - 8 - strlen(str1)) / 2; j++) 1111 printw(" "); 1112 printw("%s", str1); 1113 attroff(A_BOLD); 1114 1115 /* just for fun add a clock */ 1116 move(winx, maxx - 8); 1117 t = time(NULL); 1118 strftime(str1, 80, "%T", localtime(&t)); 1119 printw("%s\n", str1); 1120 1121 /* 1122 * print the display filters, this is placed in the loop, 1123 * because someday I might add code for changing these 1124 * while the programming is running :-) 1125 */ 1126 if (sport >= 0) 1127 sprintf(str1, "%s,%d", inet_ntoa(saddr), sport); 1128 else 1129 sprintf(str1, "%s", inet_ntoa(saddr)); 1130 1131 if (dport >= 0) 1132 sprintf(str2, "%s,%d", inet_ntoa(daddr), dport); 1133 else 1134 sprintf(str2, "%s", inet_ntoa(daddr)); 1135 1136 if (protocol < 0) 1137 strcpy(str3, "any"); 1138 else if ((proto = getprotobynumber(protocol)) != NULL) 1139 sprintf(str3, "%s", proto->p_name); 1140 else 1141 sprintf(str3, "%d", protocol); 1142 1143 switch (sorting) 1144 { 1145 case STSORT_PR: 1146 sprintf(str4, "proto"); 1147 break; 1148 case STSORT_PKTS: 1149 sprintf(str4, "# pkts"); 1150 break; 1151 case STSORT_BYTES: 1152 sprintf(str4, "# bytes"); 1153 break; 1154 case STSORT_TTL: 1155 sprintf(str4, "ttl"); 1156 break; 1157 case STSORT_SRCIP: 1158 sprintf(str4, "srcip"); 1159 break; 1160 case STSORT_DSTIP: 1161 sprintf(str4, "dstip"); 1162 break; 1163 default: 1164 sprintf(str4, "unknown"); 1165 break; 1166 } 1167 1168 if (reverse) 1169 strcat(str4, " (reverse)"); 1170 1171 winx += 2; 1172 move(winx,0); 1173 printw("Src = %s Dest = %s Proto = %s Sorted by = %s\n\n", 1174 str1, str2, str3, str4); 1175 1176 /* print column description */ 1177 winx += 2; 1178 move(winx,0); 1179 attron(A_BOLD); 1180 printw("%-21s %-21s %3s %4s %7s %9s %9s\n", "Source IP", 1181 "Destination IP", "ST", "PR", "#pkts", "#bytes", "ttl"); 1182 attroff(A_BOLD); 1183 1184 /* print all the entries */ 1185 tp = tstable; 1186 if (reverse) 1187 tp += tsentry; 1188 1189 if (tsentry > maxy - 6) 1190 tsentry = maxy - 6; 1191 for (i = 0; i <= tsentry; i++) { 1192 /* print src/dest and port */ 1193 if ((tp->st_p == IPPROTO_TCP) || 1194 (tp->st_p == IPPROTO_UDP)) { 1195 sprintf(str1, "%s,%hu", 1196 inet_ntoa(tp->st_src.in4), 1197 ntohs(tp->st_sport)); 1198 sprintf(str2, "%s,%hu", 1199 inet_ntoa(tp->st_dst.in4), 1200 ntohs(tp->st_dport)); 1201 } else { 1202 sprintf(str1, "%s", inet_ntoa(tp->st_src.in4)); 1203 sprintf(str2, "%s", inet_ntoa(tp->st_dst.in4)); 1204 } 1205 winx++; 1206 move(winx, 0); 1207 printw("%-21s %-21s", str1, str2); 1208 1209 /* print state */ 1210 sprintf(str1, "%X/%X", tp->st_state[0], 1211 tp->st_state[1]); 1212 printw(" %3s", str1); 1213 1214 /* print proto */ 1215 proto = getprotobynumber(tp->st_p); 1216 if (proto) { 1217 strncpy(str1, proto->p_name, 4); 1218 str1[4] = '\0'; 1219 } else { 1220 sprintf(str1, "%d", tp->st_p); 1221 } 1222 printw(" %4s", str1); 1223 /* print #pkt/#bytes */ 1224 #ifdef USE_QUAD_T 1225 printw(" %7qu %9qu", (unsigned long long) tp->st_pkts, 1226 (unsigned long long) tp->st_bytes); 1227 #else 1228 printw(" %7lu %9lu", tp->st_pkts, tp->st_bytes); 1229 #endif 1230 printw(" %9s", ttl_to_string(tp->st_age)); 1231 1232 if (reverse) 1233 tp--; 1234 else 1235 tp++; 1236 } 1237 1238 /* screen data structure is filled, now update the screen */ 1239 if (redraw) 1240 clearok(stdscr,1); 1241 1242 refresh(); 1243 if (redraw) { 1244 clearok(stdscr,0); 1245 redraw = 0; 1246 } 1247 1248 /* wait for key press or a 1 second time out period */ 1249 selecttimeout.tv_sec = refreshtime; 1250 selecttimeout.tv_usec = 0; 1251 FD_ZERO(&readfd); 1252 FD_SET(0, &readfd); 1253 select(1, &readfd, NULL, NULL, &selecttimeout); 1254 1255 /* if key pressed, read all waiting keys */ 1256 if (FD_ISSET(0, &readfd)) { 1257 c = wgetch(stdscr); 1258 if (c == ERR) 1259 continue; 1260 1261 if (tolower(c) == 'l') { 1262 redraw = 1; 1263 } else if (tolower(c) == 'q') { 1264 nocbreak(); 1265 endwin(); 1266 exit(0); 1267 } else if (tolower(c) == 'r') { 1268 reverse = !reverse; 1269 } else if (tolower(c) == 's') { 1270 sorting++; 1271 if (sorting > STSORT_MAX) 1272 sorting = 0; 1273 } 1274 } 1275 } /* while */ 1276 1277 printw("\n"); 1278 nocbreak(); 1279 endwin(); 1280 1281 free(tstable); 1282 } 1283 #endif 1284 1285 1286 /* 1287 * Show fragment cache information that's held in the kernel. 1288 */ 1289 static void showfrstates(ifsp) 1290 ipfrstat_t *ifsp; 1291 { 1292 struct ipfr *ipfrtab[IPFT_SIZE], ifr; 1293 frentry_t fr; 1294 int i; 1295 1296 /* 1297 * print out the numeric statistics 1298 */ 1299 PRINTF("IP fragment states:\n\t%lu new\n\t%lu expired\n\t%lu hits\n", 1300 ifsp->ifs_new, ifsp->ifs_expire, ifsp->ifs_hits); 1301 PRINTF("\t%lu retrans\n\t%lu too short\n", ifsp->ifs_retrans0, ifsp->ifs_short); 1302 PRINTF("\t%lu no memory\n\t%lu already exist\n", 1303 ifsp->ifs_nomem, ifsp->ifs_exists); 1304 PRINTF("\t%lu inuse\n", ifsp->ifs_inuse); 1305 if (kmemcpy((char *)ipfrtab, (u_long)ifsp->ifs_table, sizeof(ipfrtab))) 1306 return; 1307 1308 /* 1309 * Print out the contents (if any) of the fragment cache table. 1310 */ 1311 for (i = 0; i < IPFT_SIZE; i++) 1312 while (ipfrtab[i]) { 1313 if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i], 1314 sizeof(ifr)) == -1) 1315 break; 1316 PRINTF("%s -> ", hostname(4, &ifr.ipfr_src)); 1317 if (kmemcpy((char *)&fr, (u_long)ifr.ipfr_rule, 1318 sizeof(fr)) == -1) 1319 break; 1320 PRINTF("%s %d %d %d %#02x = %#x\n", 1321 hostname(4, &ifr.ipfr_dst), ifr.ipfr_id, 1322 ifr.ipfr_ttl, ifr.ipfr_p, ifr.ipfr_tos, 1323 fr.fr_flags); 1324 ipfrtab[i] = ifr.ipfr_next; 1325 } 1326 if (kmemcpy((char *)ipfrtab, (u_long)ifsp->ifs_nattab,sizeof(ipfrtab))) 1327 return; 1328 for (i = 0; i < IPFT_SIZE; i++) 1329 while (ipfrtab[i]) { 1330 if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i], 1331 sizeof(ifr)) == -1) 1332 break; 1333 PRINTF("NAT: %s -> ", hostname(4, &ifr.ipfr_src)); 1334 if (kmemcpy((char *)&fr, (u_long)ifr.ipfr_rule, 1335 sizeof(fr)) == -1) 1336 break; 1337 PRINTF("%s %d %d %d %#02x = %#x\n", 1338 hostname(4, &ifr.ipfr_dst), ifr.ipfr_id, 1339 ifr.ipfr_ttl, ifr.ipfr_p, ifr.ipfr_tos, 1340 fr.fr_flags); 1341 ipfrtab[i] = ifr.ipfr_next; 1342 } 1343 } 1344 1345 1346 /* 1347 * Show stats on how auth within IPFilter has been used 1348 */ 1349 static void showauthstates(asp) 1350 fr_authstat_t *asp; 1351 { 1352 frauthent_t *frap, fra; 1353 1354 #ifdef USE_QUAD_T 1355 printf("Authorisation hits: %qu\tmisses %qu\n", 1356 (unsigned long long) asp->fas_hits, 1357 (unsigned long long) asp->fas_miss); 1358 #else 1359 printf("Authorisation hits: %ld\tmisses %ld\n", asp->fas_hits, 1360 asp->fas_miss); 1361 #endif 1362 printf("nospace %ld\nadded %ld\nsendfail %ld\nsendok %ld\n", 1363 asp->fas_nospace, asp->fas_added, asp->fas_sendfail, 1364 asp->fas_sendok); 1365 printf("queok %ld\nquefail %ld\nexpire %ld\n", 1366 asp->fas_queok, asp->fas_quefail, asp->fas_expire); 1367 1368 frap = asp->fas_faelist; 1369 while (frap) { 1370 if (kmemcpy((char *)&fra, (u_long)frap, sizeof(fra)) == -1) 1371 break; 1372 1373 printf("age %ld\t", fra.fae_age); 1374 printfr(&fra.fae_fr, ioctl); 1375 frap = fra.fae_next; 1376 } 1377 } 1378 1379 1380 /* 1381 * Display groups used for each of filter rules, accounting rules and 1382 * authentication, separately. 1383 */ 1384 static void showgroups(fiop) 1385 struct friostat *fiop; 1386 { 1387 static char *gnames[3] = { "Filter", "Accounting", "Authentication" }; 1388 frgroup_t *fp, grp; 1389 int on, off, i; 1390 1391 on = fiop->f_active; 1392 off = 1 - on; 1393 1394 for (i = 0; i < 3; i++) { 1395 printf("%s groups (active):\n", gnames[i]); 1396 for (fp = fiop->f_groups[i][on]; fp; fp = grp.fg_next) 1397 if (kmemcpy((char *)&grp, (u_long)fp, sizeof(grp))) 1398 break; 1399 else 1400 printf("%s\n", grp.fg_name); 1401 printf("%s groups (inactive):\n", gnames[i]); 1402 for (fp = fiop->f_groups[i][off]; fp; fp = grp.fg_next) 1403 if (kmemcpy((char *)&grp, (u_long)fp, sizeof(grp))) 1404 break; 1405 else 1406 printf("%s\n", grp.fg_name); 1407 } 1408 } 1409 1410 static void parse_ipportstr(argument, ip, port) 1411 const char *argument; 1412 struct in_addr *ip; 1413 int *port; 1414 { 1415 1416 char *s, *comma; 1417 1418 /* make working copy of argument, Theoretically you must be able 1419 * to write to optarg, but that seems very ugly to me.... 1420 */ 1421 s = strdup(argument); 1422 if (s == NULL) 1423 return; 1424 1425 /* get port */ 1426 if ((comma = strchr(s, ',')) != NULL) { 1427 if (!strcasecmp(comma + 1, "any")) { 1428 *port = -1; 1429 } else if (!sscanf(comma + 1, "%d", port) || 1430 (*port < 0) || (*port > 65535)) { 1431 fprintf(stderr, "Invalid port specfication in %s\n", 1432 argument); 1433 free(s); 1434 exit(-2); 1435 } 1436 *comma = '\0'; 1437 } 1438 1439 1440 /* get ip address */ 1441 if (!strcasecmp(s, "any")) { 1442 ip->s_addr = INADDR_ANY; 1443 } else if (!inet_aton(s, ip)) { 1444 fprintf(stderr, "Invalid IP address: %s\n", s); 1445 free(s); 1446 exit(-2); 1447 } 1448 1449 /* free allocated memory */ 1450 free(s); 1451 } 1452 1453 1454 #ifdef STATETOP 1455 static char ttlbuf[STSTRSIZE]; 1456 1457 static char *ttl_to_string(ttl) 1458 long int ttl; 1459 { 1460 1461 int hours, minutes, seconds; 1462 1463 /* ttl is in half seconds */ 1464 ttl /= 2; 1465 1466 hours = ttl / 3600; 1467 ttl = ttl % 3600; 1468 minutes = ttl / 60; 1469 seconds = ttl % 60; 1470 1471 if (hours > 0 ) 1472 sprintf(ttlbuf, "%2d:%02d:%02d", hours, minutes, seconds); 1473 else 1474 sprintf(ttlbuf, "%2d:%02d", minutes, seconds); 1475 return ttlbuf; 1476 } 1477 1478 1479 static int sort_pkts(a, b) 1480 const void *a; 1481 const void *b; 1482 { 1483 1484 register const statetop_t *ap = a; 1485 register const statetop_t *bp = b; 1486 1487 if (ap->st_pkts == bp->st_pkts) 1488 return 0; 1489 else if (ap->st_pkts < bp->st_pkts) 1490 return 1; 1491 return -1; 1492 } 1493 1494 1495 static int sort_bytes(a, b) 1496 const void *a; 1497 const void *b; 1498 { 1499 register const statetop_t *ap = a; 1500 register const statetop_t *bp = b; 1501 1502 if (ap->st_bytes == bp->st_bytes) 1503 return 0; 1504 else if (ap->st_bytes < bp->st_bytes) 1505 return 1; 1506 return -1; 1507 } 1508 1509 1510 static int sort_p(a, b) 1511 const void *a; 1512 const void *b; 1513 { 1514 register const statetop_t *ap = a; 1515 register const statetop_t *bp = b; 1516 1517 if (ap->st_p == bp->st_p) 1518 return 0; 1519 else if (ap->st_p < bp->st_p) 1520 return 1; 1521 return -1; 1522 } 1523 1524 1525 static int sort_ttl(a, b) 1526 const void *a; 1527 const void *b; 1528 { 1529 register const statetop_t *ap = a; 1530 register const statetop_t *bp = b; 1531 1532 if (ap->st_age == bp->st_age) 1533 return 0; 1534 else if (ap->st_age < bp->st_age) 1535 return 1; 1536 return -1; 1537 } 1538 1539 static int sort_srcip(a, b) 1540 const void *a; 1541 const void *b; 1542 { 1543 register const statetop_t *ap = a; 1544 register const statetop_t *bp = b; 1545 1546 if (ntohl(ap->st_src.in4.s_addr) == ntohl(bp->st_src.in4.s_addr)) 1547 return 0; 1548 else if (ntohl(ap->st_src.in4.s_addr) > ntohl(bp->st_src.in4.s_addr)) 1549 return 1; 1550 return -1; 1551 } 1552 1553 static int sort_dstip(a, b) 1554 const void *a; 1555 const void *b; 1556 { 1557 register const statetop_t *ap = a; 1558 register const statetop_t *bp = b; 1559 1560 if (ntohl(ap->st_dst.in4.s_addr) == ntohl(bp->st_dst.in4.s_addr)) 1561 return 0; 1562 else if (ntohl(ap->st_dst.in4.s_addr) > ntohl(bp->st_dst.in4.s_addr)) 1563 return 1; 1564 return -1; 1565 } 1566 #endif 1567