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