ipfstat.c revision 145519
1238104Sdes/* $FreeBSD: head/contrib/ipfilter/tools/ipfstat.c 145519 2005-04-25 18:20:15Z darrenr $ */ 2238104Sdes 3238104Sdes/* 4238104Sdes * Copyright (C) 1993-2001, 2003 by Darren Reed. 5238104Sdes * 6238104Sdes * See the IPFILTER.LICENCE file for details on licencing. 7238104Sdes */ 8238104Sdes#ifdef __FreeBSD__ 9238104Sdes# ifndef __FreeBSD_cc_version 10238104Sdes# include <osreldate.h> 11238104Sdes# else 12238104Sdes# if __FreeBSD_cc_version < 430000 13238104Sdes# include <osreldate.h> 14238104Sdes# endif 15238104Sdes# endif 16238104Sdes#endif 17238104Sdes#include <sys/ioctl.h> 18238104Sdes#include <fcntl.h> 19238104Sdes#ifdef linux 20238104Sdes# include <linux/a.out.h> 21238104Sdes#else 22238104Sdes# include <nlist.h> 23238104Sdes#endif 24238104Sdes#include <ctype.h> 25238104Sdes#if defined(sun) && (defined(__svr4__) || defined(__SVR4)) 26238104Sdes# include <stddef.h> 27238104Sdes#endif 28238104Sdes#include "ipf.h" 29238104Sdes#include "netinet/ipl.h" 30238104Sdes#if defined(STATETOP) 31238104Sdes# if defined(_BSDI_VERSION) 32238104Sdes# undef STATETOP 33238104Sdes# endif 34238104Sdes# if defined(__FreeBSD__) && \ 35238104Sdes (!defined(__FreeBSD_version) || (__FreeBSD_version < 430000)) 36238104Sdes# undef STATETOP 37238104Sdes# endif 38238104Sdes# if defined(__NetBSD_Version__) && (__NetBSD_Version__ < 105000000) 39238104Sdes# undef STATETOP 40238104Sdes# endif 41238104Sdes# if defined(sun) 42238104Sdes# if defined(__svr4__) || defined(__SVR4) 43238104Sdes# include <sys/select.h> 44238104Sdes# else 45238104Sdes# undef STATETOP /* NOT supported on SunOS4 */ 46238104Sdes# endif 47238104Sdes# endif 48238104Sdes#endif 49238104Sdes#if defined(STATETOP) && !defined(linux) 50238104Sdes# include <netinet/ip_var.h> 51238104Sdes# include <netinet/tcp_fsm.h> 52238104Sdes#endif 53238104Sdes#ifdef STATETOP 54238104Sdes# include <ctype.h> 55238104Sdes# include <signal.h> 56238104Sdes# if SOLARIS || defined(__NetBSD__) || defined(_BSDI_VERSION) || \ 57238104Sdes defined(__sgi) 58238104Sdes# ifdef ERR 59238104Sdes# undef ERR 60238104Sdes# endif 61238104Sdes# include <curses.h> 62238104Sdes# else /* SOLARIS */ 63238104Sdes# include <ncurses.h> 64238104Sdes# endif /* SOLARIS */ 65238104Sdes#endif /* STATETOP */ 66238104Sdes#include "kmem.h" 67238104Sdes#if defined(__NetBSD__) || (__OpenBSD__) 68238104Sdes# include <paths.h> 69238104Sdes#endif 70238104Sdes 71238104Sdes#if !defined(lint) 72238104Sdesstatic const char sccsid[] = "@(#)fils.c 1.21 4/20/96 (C) 1993-2000 Darren Reed"; 73238104Sdesstatic const char rcsid[] = "@(#)Id: ipfstat.c,v 1.44.2.11 2005/03/30 14:09:57 darrenr Exp"; 74238104Sdes#endif 75238104Sdes 76238104Sdes#ifdef __hpux 77238104Sdes# define nlist nlist64 78238104Sdes#endif 79238104Sdes 80238104Sdesextern char *optarg; 81238104Sdesextern int optind; 82238104Sdesextern int opterr; 83238104Sdes 84238104Sdes#define PRINTF (void)printf 85238104Sdes#define FPRINTF (void)fprintf 86238104Sdes#define F_IN 0 87238104Sdes#define F_OUT 1 88238104Sdes#define F_ACIN 2 89238104Sdes#define F_ACOUT 3 90238104Sdesstatic char *filters[4] = { "ipfilter(in)", "ipfilter(out)", 91238104Sdes "ipacct(in)", "ipacct(out)" }; 92238104Sdesstatic int state_logging = -1; 93238104Sdes 94238104Sdesint opts = 0; 95238104Sdesint use_inet6 = 0; 96238104Sdesint live_kernel = 1; 97238104Sdesint state_fd = -1; 98238104Sdesint ipf_fd = -1; 99246854Sdes 100238104Sdes#ifdef STATETOP 101238104Sdes#define STSTRSIZE 80 102238104Sdes#define STGROWSIZE 16 103238104Sdes#define HOSTNMLEN 40 104238104Sdes 105238104Sdes#define STSORT_PR 0 106238104Sdes#define STSORT_PKTS 1 107238104Sdes#define STSORT_BYTES 2 108238104Sdes#define STSORT_TTL 3 109238104Sdes#define STSORT_SRCIP 4 110238104Sdes#define STSORT_SRCPT 5 111238104Sdes#define STSORT_DSTIP 6 112238104Sdes#define STSORT_DSTPT 7 113238104Sdes#define STSORT_MAX STSORT_DSTPT 114238104Sdes#define STSORT_DEFAULT STSORT_BYTES 115238104Sdes 116238104Sdes 117238104Sdestypedef struct statetop { 118238104Sdes i6addr_t st_src; 119238104Sdes i6addr_t st_dst; 120238104Sdes u_short st_sport; 121238104Sdes u_short st_dport; 122238104Sdes u_char st_p; 123238104Sdes u_char st_v; 124238104Sdes u_char st_state[2]; 125238104Sdes U_QUAD_T st_pkts; 126238104Sdes U_QUAD_T st_bytes; 127238104Sdes u_long st_age; 128238104Sdes} statetop_t; 129238104Sdes#endif 130238104Sdes 131238104Sdesint main __P((int, char *[])); 132238104Sdes 133238104Sdesstatic void showstats __P((friostat_t *, u_32_t)); 134238104Sdesstatic void showfrstates __P((ipfrstat_t *)); 135238104Sdesstatic void showlist __P((friostat_t *)); 136238104Sdesstatic void showipstates __P((ips_stat_t *)); 137238104Sdesstatic void showauthstates __P((fr_authstat_t *)); 138238104Sdesstatic void showgroups __P((friostat_t *)); 139238104Sdesstatic void usage __P((char *)); 140238104Sdesstatic void printlist __P((frentry_t *, char *)); 141238104Sdesstatic void parse_ipportstr __P((const char *, i6addr_t *, int *)); 142238104Sdesstatic void ipfstate_live __P((char *, friostat_t **, ips_stat_t **, 143238104Sdes ipfrstat_t **, fr_authstat_t **, u_32_t *)); 144238104Sdesstatic void ipfstate_dead __P((char *, friostat_t **, ips_stat_t **, 145238104Sdes ipfrstat_t **, fr_authstat_t **, u_32_t *)); 146238104Sdes#ifdef STATETOP 147238104Sdesstatic void topipstates __P((i6addr_t, i6addr_t, int, int, int, 148238104Sdes int, int, int)); 149238104Sdesstatic void sig_break __P((int)); 150238104Sdesstatic void sig_resize __P((int)); 151238104Sdesstatic char *getip __P((int, i6addr_t *)); 152238104Sdesstatic char *ttl_to_string __P((long)); 153238104Sdesstatic int sort_p __P((const void *, const void *)); 154238104Sdesstatic int sort_pkts __P((const void *, const void *)); 155238104Sdesstatic int sort_bytes __P((const void *, const void *)); 156238104Sdesstatic int sort_ttl __P((const void *, const void *)); 157238104Sdesstatic int sort_srcip __P((const void *, const void *)); 158238104Sdesstatic int sort_srcpt __P((const void *, const void *)); 159238104Sdesstatic int sort_dstip __P((const void *, const void *)); 160238104Sdesstatic int sort_dstpt __P((const void *, const void *)); 161238104Sdes#endif 162238104Sdes 163238104Sdes 164238104Sdesstatic void usage(name) 165238104Sdeschar *name; 166238104Sdes{ 167238104Sdes#ifdef USE_INET6 168238104Sdes fprintf(stderr, "Usage: %s [-6aAdfghIilnoRsv]\n", name); 169238104Sdes#else 170238104Sdes fprintf(stderr, "Usage: %s [-aAdfghIilnoRsv]\n", name); 171238104Sdes#endif 172238104Sdes fprintf(stderr, " %s [-M corefile] [-N symbol-list]\n", name); 173238104Sdes#ifdef USE_INET6 174238104Sdes fprintf(stderr, " %s -t [-6C] ", name); 175238104Sdes#else 176238104Sdes fprintf(stderr, " %s -t [-C] ", name); 177238104Sdes#endif 178238104Sdes fprintf(stderr, "[-D destination address] [-P protocol] [-S source address] [-T refresh time]\n"); 179238104Sdes exit(1); 180238104Sdes} 181238104Sdes 182238104Sdes 183238104Sdesint main(argc,argv) 184238104Sdesint argc; 185238104Sdeschar *argv[]; 186238104Sdes{ 187238104Sdes fr_authstat_t frauthst; 188238104Sdes fr_authstat_t *frauthstp = &frauthst; 189238104Sdes friostat_t fio; 190238104Sdes friostat_t *fiop = &fio; 191238104Sdes ips_stat_t ipsst; 192238104Sdes ips_stat_t *ipsstp = &ipsst; 193238104Sdes ipfrstat_t ifrst; 194238104Sdes ipfrstat_t *ifrstp = &ifrst; 195238104Sdes char *device = IPL_NAME, *memf = NULL; 196238104Sdes char *options, *kern = NULL; 197238104Sdes int c, myoptind; 198238104Sdes 199238104Sdes int protocol = -1; /* -1 = wild card for any protocol */ 200238104Sdes int refreshtime = 1; /* default update time */ 201238104Sdes int sport = -1; /* -1 = wild card for any source port */ 202238104Sdes int dport = -1; /* -1 = wild card for any dest port */ 203238104Sdes int topclosed = 0; /* do not show closed tcp sessions */ 204238104Sdes i6addr_t saddr, daddr; 205238104Sdes u_32_t frf; 206238104Sdes 207238104Sdes#ifdef USE_INET6 208238104Sdes options = "6aACdfghIilnostvD:M:N:P:RS:T:"; 209238104Sdes#else 210238104Sdes options = "aACdfghIilnostvD:M:N:P:RS:T:"; 211238104Sdes#endif 212238104Sdes 213238104Sdes saddr.in4.s_addr = INADDR_ANY; /* default any v4 source addr */ 214238104Sdes daddr.in4.s_addr = INADDR_ANY; /* default any v4 dest addr */ 215238104Sdes#ifdef USE_INET6 216238104Sdes saddr.in6 = in6addr_any; /* default any v6 source addr */ 217238104Sdes daddr.in6 = in6addr_any; /* default any v6 dest addr */ 218238104Sdes#endif 219238104Sdes 220238104Sdes /* Don't warn about invalid flags when we run getopt for the 1st time */ 221238104Sdes opterr = 0; 222238104Sdes 223238104Sdes /* 224238104Sdes * Parse these two arguments now lest there be any buffer overflows 225238104Sdes * in the parsing of the rest. 226238104Sdes */ 227238104Sdes myoptind = optind; 228238104Sdes while ((c = getopt(argc, argv, options)) != -1) { 229238104Sdes switch (c) 230238104Sdes { 231238104Sdes case 'M' : 232238104Sdes memf = optarg; 233238104Sdes live_kernel = 0; 234238104Sdes break; 235238104Sdes case 'N' : 236238104Sdes kern = optarg; 237238104Sdes live_kernel = 0; 238238104Sdes break; 239238104Sdes } 240238104Sdes } 241238104Sdes optind = myoptind; 242238104Sdes 243238104Sdes if (live_kernel == 1) { 244238104Sdes if ((state_fd = open(IPSTATE_NAME, O_RDONLY)) == -1) { 245238104Sdes perror("open(IPSTATE_NAME)"); 246238104Sdes exit(-1); 247238104Sdes } 248238104Sdes if ((ipf_fd = open(device, O_RDONLY)) == -1) { 249238104Sdes fprintf(stderr, "open(%s)", device); 250238104Sdes perror(""); 251238104Sdes exit(-1); 252238104Sdes } 253238104Sdes } 254238104Sdes 255238104Sdes if (kern != NULL || memf != NULL) { 256238104Sdes (void)setgid(getgid()); 257238104Sdes (void)setuid(getuid()); 258238104Sdes } 259238104Sdes 260238104Sdes if (live_kernel == 1) 261238104Sdes (void) checkrev(device); 262238104Sdes if (openkmem(kern, memf) == -1) 263238104Sdes exit(-1); 264238104Sdes 265238104Sdes (void)setgid(getgid()); 266238104Sdes (void)setuid(getuid()); 267238104Sdes 268238104Sdes opterr = 1; 269238104Sdes 270238104Sdes while ((c = getopt(argc, argv, options)) != -1) 271238104Sdes { 272238104Sdes switch (c) 273238104Sdes { 274238104Sdes#ifdef USE_INET6 275238104Sdes case '6' : 276238104Sdes use_inet6 = 1; 277238104Sdes break; 278238104Sdes#endif 279238104Sdes case 'a' : 280238104Sdes opts |= OPT_ACCNT|OPT_SHOWLIST; 281238104Sdes break; 282238104Sdes case 'A' : 283238104Sdes opts |= OPT_AUTHSTATS; 284238104Sdes break; 285238104Sdes case 'C' : 286238104Sdes topclosed = 1; 287238104Sdes break; 288238104Sdes case 'd' : 289238104Sdes opts |= OPT_DEBUG; 290238104Sdes break; 291238104Sdes case 'D' : 292238104Sdes parse_ipportstr(optarg, &daddr, &dport); 293238104Sdes break; 294238104Sdes case 'f' : 295238104Sdes opts |= OPT_FRSTATES; 296238104Sdes break; 297238104Sdes case 'g' : 298238104Sdes opts |= OPT_GROUPS; 299238104Sdes break; 300238104Sdes case 'h' : 301238104Sdes opts |= OPT_HITS; 302238104Sdes break; 303238104Sdes case 'i' : 304238104Sdes opts |= OPT_INQUE|OPT_SHOWLIST; 305238104Sdes break; 306238104Sdes case 'I' : 307238104Sdes opts |= OPT_INACTIVE; 308238104Sdes break; 309238104Sdes case 'l' : 310238104Sdes opts |= OPT_SHOWLIST; 311238104Sdes break; 312238104Sdes case 'M' : 313238104Sdes break; 314238104Sdes case 'N' : 315238104Sdes break; 316238104Sdes case 'n' : 317238104Sdes opts |= OPT_SHOWLINENO; 318238104Sdes break; 319238104Sdes case 'o' : 320238104Sdes opts |= OPT_OUTQUE|OPT_SHOWLIST; 321238104Sdes break; 322238104Sdes case 'P' : 323238104Sdes protocol = getproto(optarg); 324238104Sdes if (protocol == -1) { 325238104Sdes fprintf(stderr, "%s: Invalid protocol: %s\n", 326238104Sdes argv[0], optarg); 327238104Sdes exit(-2); 328238104Sdes } 329238104Sdes break; 330238104Sdes case 'R' : 331238104Sdes opts |= OPT_NORESOLVE; 332238104Sdes break; 333238104Sdes case 's' : 334238104Sdes opts |= OPT_IPSTATES; 335238104Sdes break; 336238104Sdes case 'S' : 337238104Sdes parse_ipportstr(optarg, &saddr, &sport); 338238104Sdes break; 339238104Sdes case 't' : 340238104Sdes#ifdef STATETOP 341238104Sdes opts |= OPT_STATETOP; 342238104Sdes break; 343238104Sdes#else 344238104Sdes fprintf(stderr, 345238104Sdes "%s: state top facility not compiled in\n", 346238104Sdes argv[0]); 347238104Sdes exit(-2); 348238104Sdes#endif 349238104Sdes case 'T' : 350238104Sdes if (!sscanf(optarg, "%d", &refreshtime) || 351238104Sdes (refreshtime <= 0)) { 352238104Sdes fprintf(stderr, 353238104Sdes "%s: Invalid refreshtime < 1 : %s\n", 354238104Sdes argv[0], optarg); 355238104Sdes exit(-2); 356238104Sdes } 357238104Sdes break; 358238104Sdes case 'v' : 359238104Sdes opts |= OPT_VERBOSE; 360238104Sdes break; 361238104Sdes default : 362238104Sdes usage(argv[0]); 363238104Sdes break; 364238104Sdes } 365238104Sdes } 366238104Sdes 367238104Sdes if (live_kernel == 1) { 368238104Sdes bzero((char *)&fio, sizeof(fio)); 369238104Sdes bzero((char *)&ipsst, sizeof(ipsst)); 370238104Sdes bzero((char *)&ifrst, sizeof(ifrst)); 371238104Sdes 372238104Sdes ipfstate_live(device, &fiop, &ipsstp, &ifrstp, 373238104Sdes &frauthstp, &frf); 374238104Sdes } else 375238104Sdes ipfstate_dead(kern, &fiop, &ipsstp, &ifrstp, &frauthstp, &frf); 376238104Sdes 377238104Sdes if (opts & OPT_IPSTATES) { 378238104Sdes showipstates(ipsstp); 379238104Sdes } else if (opts & OPT_SHOWLIST) { 380238104Sdes showlist(fiop); 381238104Sdes if ((opts & OPT_OUTQUE) && (opts & OPT_INQUE)){ 382238104Sdes opts &= ~OPT_OUTQUE; 383238104Sdes showlist(fiop); 384238104Sdes } 385238104Sdes } else if (opts & OPT_FRSTATES) 386238104Sdes showfrstates(ifrstp); 387238104Sdes#ifdef STATETOP 388238104Sdes else if (opts & OPT_STATETOP) 389238104Sdes topipstates(saddr, daddr, sport, dport, protocol, 390238104Sdes use_inet6 ? 6 : 4, refreshtime, topclosed); 391238104Sdes#endif 392238104Sdes else if (opts & OPT_AUTHSTATS) 393238104Sdes showauthstates(frauthstp); 394238104Sdes else if (opts & OPT_GROUPS) 395238104Sdes showgroups(fiop); 396238104Sdes else 397238104Sdes showstats(fiop, frf); 398238104Sdes 399238104Sdes return 0; 400238104Sdes} 401238104Sdes 402238104Sdes 403238104Sdes/* 404238104Sdes * Fill in the stats structures from the live kernel, using a combination 405238104Sdes * of ioctl's and copying directly from kernel memory. 406238104Sdes */ 407238104Sdesstatic void ipfstate_live(device, fiopp, ipsstpp, ifrstpp, frauthstpp, frfp) 408238104Sdeschar *device; 409238104Sdesfriostat_t **fiopp; 410238104Sdesips_stat_t **ipsstpp; 411238104Sdesipfrstat_t **ifrstpp; 412238104Sdesfr_authstat_t **frauthstpp; 413238104Sdesu_32_t *frfp; 414238104Sdes{ 415238104Sdes ipfobj_t ipfo; 416238104Sdes 417238104Sdes if (checkrev(device) == -1) { 418238104Sdes fprintf(stderr, "User/kernel version check failed\n"); 419238104Sdes exit(1); 420238104Sdes } 421238104Sdes 422238104Sdes if ((opts & OPT_AUTHSTATS) == 0) { 423238104Sdes bzero((caddr_t)&ipfo, sizeof(ipfo)); 424238104Sdes ipfo.ipfo_rev = IPFILTER_VERSION; 425238104Sdes ipfo.ipfo_size = sizeof(friostat_t); 426238104Sdes ipfo.ipfo_ptr = (void *)*fiopp; 427238104Sdes ipfo.ipfo_type = IPFOBJ_IPFSTAT; 428238104Sdes 429238104Sdes if (ioctl(ipf_fd, SIOCGETFS, &ipfo) == -1) { 430238104Sdes perror("ioctl(ipf:SIOCGETFS)"); 431238104Sdes exit(-1); 432238104Sdes } 433238104Sdes 434238104Sdes if (ioctl(ipf_fd, SIOCGETFF, frfp) == -1) 435238104Sdes perror("ioctl(SIOCGETFF)"); 436238104Sdes } 437238104Sdes 438238104Sdes if ((opts & OPT_IPSTATES) != 0) { 439238104Sdes 440238104Sdes bzero((caddr_t)&ipfo, sizeof(ipfo)); 441238104Sdes ipfo.ipfo_rev = IPFILTER_VERSION; 442238104Sdes ipfo.ipfo_size = sizeof(ips_stat_t); 443238104Sdes ipfo.ipfo_ptr = (void *)*ipsstpp; 444238104Sdes ipfo.ipfo_type = IPFOBJ_STATESTAT; 445238104Sdes 446238104Sdes if ((ioctl(state_fd, SIOCGETFS, &ipfo) == -1)) { 447238104Sdes perror("ioctl(state:SIOCGETFS)"); 448238104Sdes exit(-1); 449238104Sdes } 450238104Sdes if (ioctl(state_fd, SIOCGETLG, &state_logging) == -1) { 451238104Sdes perror("ioctl(state:SIOCGETLG)"); 452238104Sdes exit(-1); 453238104Sdes } 454238104Sdes } 455238104Sdes 456238104Sdes if ((opts & OPT_FRSTATES) != 0) { 457238104Sdes bzero((caddr_t)&ipfo, sizeof(ipfo)); 458238104Sdes ipfo.ipfo_rev = IPFILTER_VERSION; 459238104Sdes ipfo.ipfo_size = sizeof(ipfrstat_t); 460238104Sdes ipfo.ipfo_ptr = (void *)*ifrstpp; 461238104Sdes ipfo.ipfo_type = IPFOBJ_FRAGSTAT; 462238104Sdes 463238104Sdes if (ioctl(ipf_fd, SIOCGFRST, &ipfo) == -1) { 464238104Sdes perror("ioctl(SIOCGFRST)"); 465238104Sdes exit(-1); 466238104Sdes } 467238104Sdes } 468238104Sdes 469238104Sdes if (opts & OPT_VERBOSE) 470238104Sdes PRINTF("opts %#x name %s\n", opts, device); 471238104Sdes 472238104Sdes if ((opts & OPT_AUTHSTATS) != 0) { 473238104Sdes if (ipf_fd >= 0) { 474238104Sdes close(ipf_fd); 475238104Sdes ipf_fd = -1; 476238104Sdes } 477238104Sdes device = IPAUTH_NAME; 478238104Sdes if ((ipf_fd = open(device, O_RDONLY)) == -1) { 479238104Sdes perror("open"); 480238104Sdes exit(-1); 481238104Sdes } 482238104Sdes 483238104Sdes bzero((caddr_t)&ipfo, sizeof(ipfo)); 484238104Sdes ipfo.ipfo_rev = IPFILTER_VERSION; 485238104Sdes ipfo.ipfo_size = sizeof(fr_authstat_t); 486238104Sdes ipfo.ipfo_ptr = (void *)*frauthstpp; 487238104Sdes ipfo.ipfo_type = IPFOBJ_AUTHSTAT; 488238104Sdes 489238104Sdes if (ioctl(ipf_fd, SIOCATHST, &ipfo) == -1) { 490238104Sdes perror("ioctl(SIOCATHST)"); 491238104Sdes exit(-1); 492238104Sdes } 493238104Sdes } 494238104Sdes} 495238104Sdes 496238104Sdes 497238104Sdes/* 498238104Sdes * Build up the stats structures from data held in the "core" memory. 499238104Sdes * This is mainly useful when looking at data in crash dumps and ioctl's 500238104Sdes * just won't work any more. 501238104Sdes */ 502238104Sdesstatic void ipfstate_dead(kernel, fiopp, ipsstpp, ifrstpp, frauthstpp, frfp) 503238104Sdeschar *kernel; 504238104Sdesfriostat_t **fiopp; 505238104Sdesips_stat_t **ipsstpp; 506238104Sdesipfrstat_t **ifrstpp; 507238104Sdesfr_authstat_t **frauthstpp; 508238104Sdesu_32_t *frfp; 509238104Sdes{ 510238104Sdes static fr_authstat_t frauthst, *frauthstp; 511238104Sdes static ips_stat_t ipsst, *ipsstp; 512238104Sdes static ipfrstat_t ifrst, *ifrstp; 513238104Sdes static friostat_t fio, *fiop; 514238104Sdes int temp; 515238104Sdes 516238104Sdes void *rules[2][2]; 517238104Sdes struct nlist deadlist[43] = { 518238104Sdes { "fr_authstats" }, /* 0 */ 519238104Sdes { "fae_list" }, 520238104Sdes { "ipauth" }, 521238104Sdes { "fr_authlist" }, 522238104Sdes { "fr_authstart" }, 523238104Sdes { "fr_authend" }, /* 5 */ 524238104Sdes { "fr_authnext" }, 525238104Sdes { "fr_auth" }, 526238104Sdes { "fr_authused" }, 527238104Sdes { "fr_authsize" }, 528238104Sdes { "fr_defaultauthage" }, /* 10 */ 529238104Sdes { "fr_authpkts" }, 530238104Sdes { "fr_auth_lock" }, 531238104Sdes { "frstats" }, 532238104Sdes { "ips_stats" }, 533238104Sdes { "ips_num" }, /* 15 */ 534238104Sdes { "ips_wild" }, 535238104Sdes { "ips_list" }, 536238104Sdes { "ips_table" }, 537246854Sdes { "fr_statemax" }, 538238104Sdes { "fr_statesize" }, /* 20 */ 539238104Sdes { "fr_state_doflush" }, 540238104Sdes { "fr_state_lock" }, 541238104Sdes { "ipfr_heads" }, 542238104Sdes { "ipfr_nattab" }, 543238104Sdes { "ipfr_stats" }, /* 25 */ 544238104Sdes { "ipfr_inuse" }, 545238104Sdes { "fr_ipfrttl" }, 546238104Sdes { "fr_frag_lock" }, 547238104Sdes { "ipfr_timer_id" }, 548238104Sdes { "fr_nat_lock" }, /* 30 */ 549238104Sdes { "ipfilter" }, 550238104Sdes { "ipfilter6" }, 551238104Sdes { "ipacct" }, 552238104Sdes { "ipacct6" }, 553238104Sdes { "ipl_frouteok" }, /* 35 */ 554238104Sdes { "fr_running" }, 555238104Sdes { "ipfgroups" }, 556238104Sdes { "fr_active" }, 557238104Sdes { "fr_pass" }, 558238104Sdes { "fr_flags" }, /* 40 */ 559238104Sdes { "ipstate_logging" }, 560238104Sdes { NULL } 561238104Sdes }; 562238104Sdes 563238104Sdes 564238104Sdes frauthstp = &frauthst; 565238104Sdes ipsstp = &ipsst; 566238104Sdes ifrstp = &ifrst; 567238104Sdes fiop = &fio; 568238104Sdes 569238104Sdes *frfp = 0; 570238104Sdes *fiopp = fiop; 571238104Sdes *ipsstpp = ipsstp; 572238104Sdes *ifrstpp = ifrstp; 573238104Sdes *frauthstpp = frauthstp; 574238104Sdes 575238104Sdes bzero((char *)fiop, sizeof(*fiop)); 576238104Sdes bzero((char *)ipsstp, sizeof(*ipsstp)); 577238104Sdes bzero((char *)ifrstp, sizeof(*ifrstp)); 578238104Sdes bzero((char *)frauthstp, sizeof(*frauthstp)); 579238104Sdes 580238104Sdes if (nlist(kernel, deadlist) == -1) { 581238104Sdes fprintf(stderr, "nlist error\n"); 582238104Sdes return; 583238104Sdes } 584238104Sdes 585238104Sdes /* 586238104Sdes * This is for SIOCGETFF. 587238104Sdes */ 588238104Sdes kmemcpy((char *)frfp, (u_long)deadlist[40].n_value, sizeof(*frfp)); 589238104Sdes 590238104Sdes /* 591238104Sdes * f_locks is a combination of the lock variable from each part of 592238104Sdes * ipfilter (state, auth, nat, fragments). 593238104Sdes */ 594238104Sdes kmemcpy((char *)fiop, (u_long)deadlist[13].n_value, sizeof(*fiop)); 595238104Sdes kmemcpy((char *)&fiop->f_locks[0], (u_long)deadlist[22].n_value, 596238104Sdes sizeof(fiop->f_locks[0])); 597238104Sdes kmemcpy((char *)&fiop->f_locks[0], (u_long)deadlist[30].n_value, 598238104Sdes sizeof(fiop->f_locks[1])); 599238104Sdes kmemcpy((char *)&fiop->f_locks[2], (u_long)deadlist[28].n_value, 600238104Sdes sizeof(fiop->f_locks[2])); 601238104Sdes kmemcpy((char *)&fiop->f_locks[3], (u_long)deadlist[12].n_value, 602238104Sdes sizeof(fiop->f_locks[3])); 603238104Sdes 604238104Sdes /* 605238104Sdes * Get pointers to each list of rules (active, inactive, in, out) 606238104Sdes */ 607238104Sdes kmemcpy((char *)&rules, (u_long)deadlist[31].n_value, sizeof(rules)); 608238104Sdes fiop->f_fin[0] = rules[0][0]; 609238104Sdes fiop->f_fin[1] = rules[0][1]; 610238104Sdes fiop->f_fout[0] = rules[1][0]; 611238104Sdes fiop->f_fout[1] = rules[1][1]; 612238104Sdes 613238104Sdes /* 614238104Sdes * Same for IPv6, except make them null if support for it is not 615238104Sdes * being compiled in. 616238104Sdes */ 617238104Sdes#ifdef USE_INET6 618238104Sdes kmemcpy((char *)&rules, (u_long)deadlist[32].n_value, sizeof(rules)); 619238104Sdes fiop->f_fin6[0] = rules[0][0]; 620238104Sdes fiop->f_fin6[1] = rules[0][1]; 621238104Sdes fiop->f_fout6[0] = rules[1][0]; 622238104Sdes fiop->f_fout6[1] = rules[1][1]; 623238104Sdes#else 624238104Sdes fiop->f_fin6[0] = NULL; 625238104Sdes fiop->f_fin6[1] = NULL; 626238104Sdes fiop->f_fout6[0] = NULL; 627238104Sdes fiop->f_fout6[1] = NULL; 628238104Sdes#endif 629238104Sdes 630238104Sdes /* 631238104Sdes * Now get accounting rules pointers. 632238104Sdes */ 633238104Sdes kmemcpy((char *)&rules, (u_long)deadlist[33].n_value, sizeof(rules)); 634238104Sdes fiop->f_acctin[0] = rules[0][0]; 635238104Sdes fiop->f_acctin[1] = rules[0][1]; 636238104Sdes fiop->f_acctout[0] = rules[1][0]; 637238104Sdes fiop->f_acctout[1] = rules[1][1]; 638238104Sdes 639238104Sdes#ifdef USE_INET6 640238104Sdes kmemcpy((char *)&rules, (u_long)deadlist[34].n_value, sizeof(rules)); 641238104Sdes fiop->f_acctin6[0] = rules[0][0]; 642238104Sdes fiop->f_acctin6[1] = rules[0][1]; 643238104Sdes fiop->f_acctout6[0] = rules[1][0]; 644238104Sdes fiop->f_acctout6[1] = rules[1][1]; 645238104Sdes#else 646238104Sdes fiop->f_acctin6[0] = NULL; 647238104Sdes fiop->f_acctin6[1] = NULL; 648238104Sdes fiop->f_acctout6[0] = NULL; 649238104Sdes fiop->f_acctout6[1] = NULL; 650238104Sdes#endif 651238104Sdes 652238104Sdes /* 653238104Sdes * A collection of "global" variables used inside the kernel which 654238104Sdes * are all collected in friostat_t via ioctl. 655238104Sdes */ 656238104Sdes kmemcpy((char *)&fiop->f_froute, (u_long)deadlist[35].n_value, 657238104Sdes sizeof(fiop->f_froute)); 658238104Sdes kmemcpy((char *)&fiop->f_running, (u_long)deadlist[36].n_value, 659238104Sdes sizeof(fiop->f_running)); 660238104Sdes kmemcpy((char *)&fiop->f_groups, (u_long)deadlist[37].n_value, 661238104Sdes sizeof(fiop->f_groups)); 662238104Sdes kmemcpy((char *)&fiop->f_active, (u_long)deadlist[38].n_value, 663238104Sdes sizeof(fiop->f_active)); 664238104Sdes kmemcpy((char *)&fiop->f_defpass, (u_long)deadlist[39].n_value, 665238104Sdes sizeof(fiop->f_defpass)); 666238104Sdes 667238104Sdes /* 668238104Sdes * Build up the state information stats structure. 669238104Sdes */ 670238104Sdes kmemcpy((char *)ipsstp, (u_long)deadlist[14].n_value, sizeof(*ipsstp)); 671238104Sdes kmemcpy((char *)&temp, (u_long)deadlist[15].n_value, sizeof(temp)); 672238104Sdes ipsstp->iss_active = temp; 673238104Sdes ipsstp->iss_table = (void *)deadlist[18].n_value; 674238104Sdes ipsstp->iss_list = (void *)deadlist[17].n_value; 675238104Sdes 676238104Sdes /* 677238104Sdes * Build up the authentiation information stats structure. 678238104Sdes */ 679238104Sdes kmemcpy((char *)frauthstp, (u_long)deadlist[0].n_value, 680238104Sdes sizeof(*frauthstp)); 681238104Sdes frauthstp->fas_faelist = (void *)deadlist[1].n_value; 682238104Sdes 683238104Sdes /* 684238104Sdes * Build up the fragment information stats structure. 685238104Sdes */ 686238104Sdes kmemcpy((char *)ifrstp, (u_long)deadlist[25].n_value, 687238104Sdes sizeof(*ifrstp)); 688238104Sdes ifrstp->ifs_table = (void *)deadlist[23].n_value; 689238104Sdes ifrstp->ifs_nattab = (void *)deadlist[24].n_value; 690238104Sdes kmemcpy((char *)&ifrstp->ifs_inuse, (u_long)deadlist[26].n_value, 691238104Sdes sizeof(ifrstp->ifs_inuse)); 692238104Sdes 693238104Sdes /* 694238104Sdes * Get logging on/off switches 695238104Sdes */ 696238104Sdes kmemcpy((char *)&state_logging, (u_long)deadlist[41].n_value, 697238104Sdes sizeof(state_logging)); 698238104Sdes} 699238104Sdes 700238104Sdes 701238104Sdes/* 702238104Sdes * Display the kernel stats for packets blocked and passed and other 703238104Sdes * associated running totals which are kept. 704238104Sdes */ 705238104Sdesstatic void showstats(fp, frf) 706238104Sdesstruct friostat *fp; 707238104Sdesu_32_t frf; 708238104Sdes{ 709238104Sdes 710238104Sdes PRINTF("bad packets:\t\tin %lu\tout %lu\n", 711238104Sdes fp->f_st[0].fr_bad, fp->f_st[1].fr_bad); 712238104Sdes#ifdef USE_INET6 713238104Sdes PRINTF(" IPv6 packets:\t\tin %lu out %lu\n", 714238104Sdes fp->f_st[0].fr_ipv6, fp->f_st[1].fr_ipv6); 715238104Sdes#endif 716238104Sdes PRINTF(" input packets:\t\tblocked %lu passed %lu nomatch %lu", 717238104Sdes fp->f_st[0].fr_block, fp->f_st[0].fr_pass, 718238104Sdes fp->f_st[0].fr_nom); 719238104Sdes PRINTF(" counted %lu short %lu\n", 720238104Sdes fp->f_st[0].fr_acct, fp->f_st[0].fr_short); 721238104Sdes PRINTF("output packets:\t\tblocked %lu passed %lu nomatch %lu", 722238104Sdes fp->f_st[1].fr_block, fp->f_st[1].fr_pass, 723238104Sdes fp->f_st[1].fr_nom); 724238104Sdes PRINTF(" counted %lu short %lu\n", 725238104Sdes fp->f_st[1].fr_acct, fp->f_st[1].fr_short); 726238104Sdes PRINTF(" input packets logged:\tblocked %lu passed %lu\n", 727238104Sdes fp->f_st[0].fr_bpkl, fp->f_st[0].fr_ppkl); 728238104Sdes PRINTF("output packets logged:\tblocked %lu passed %lu\n", 729238104Sdes fp->f_st[1].fr_bpkl, fp->f_st[1].fr_ppkl); 730238104Sdes PRINTF(" packets logged:\tinput %lu output %lu\n", 731238104Sdes fp->f_st[0].fr_pkl, fp->f_st[1].fr_pkl); 732238104Sdes PRINTF(" log failures:\t\tinput %lu output %lu\n", 733238104Sdes fp->f_st[0].fr_skip, fp->f_st[1].fr_skip); 734238104Sdes PRINTF("fragment state(in):\tkept %lu\tlost %lu\tnot fragmented %lu\n", 735238104Sdes fp->f_st[0].fr_nfr, fp->f_st[0].fr_bnfr, 736238104Sdes fp->f_st[0].fr_cfr); 737238104Sdes PRINTF("fragment state(out):\tkept %lu\tlost %lu\tnot fragmented %lu\n", 738238104Sdes fp->f_st[1].fr_nfr, fp->f_st[1].fr_bnfr, 739238104Sdes fp->f_st[0].fr_cfr); 740238104Sdes PRINTF("packet state(in):\tkept %lu\tlost %lu\n", 741238104Sdes fp->f_st[0].fr_ads, fp->f_st[0].fr_bads); 742238104Sdes PRINTF("packet state(out):\tkept %lu\tlost %lu\n", 743238104Sdes fp->f_st[1].fr_ads, fp->f_st[1].fr_bads); 744238104Sdes PRINTF("ICMP replies:\t%lu\tTCP RSTs sent:\t%lu\n", 745238104Sdes fp->f_st[0].fr_ret, fp->f_st[1].fr_ret); 746238104Sdes PRINTF("Invalid source(in):\t%lu\n", fp->f_st[0].fr_badsrc); 747238104Sdes PRINTF("Result cache hits(in):\t%lu\t(out):\t%lu\n", 748238104Sdes fp->f_st[0].fr_chit, fp->f_st[1].fr_chit); 749238104Sdes PRINTF("IN Pullups succeeded:\t%lu\tfailed:\t%lu\n", 750238104Sdes fp->f_st[0].fr_pull[0], fp->f_st[0].fr_pull[1]); 751238104Sdes PRINTF("OUT Pullups succeeded:\t%lu\tfailed:\t%lu\n", 752238104Sdes fp->f_st[1].fr_pull[0], fp->f_st[1].fr_pull[1]); 753238104Sdes PRINTF("Fastroute successes:\t%lu\tfailures:\t%lu\n", 754238104Sdes fp->f_froute[0], fp->f_froute[1]); 755238104Sdes PRINTF("TCP cksum fails(in):\t%lu\t(out):\t%lu\n", 756238104Sdes fp->f_st[0].fr_tcpbad, fp->f_st[1].fr_tcpbad); 757238104Sdes PRINTF("IPF Ticks:\t%lu\n", fp->f_ticks); 758238104Sdes 759238104Sdes PRINTF("Packet log flags set: (%#x)\n", frf); 760238104Sdes if (frf & FF_LOGPASS) 761238104Sdes PRINTF("\tpackets passed through filter\n"); 762238104Sdes if (frf & FF_LOGBLOCK) 763238104Sdes PRINTF("\tpackets blocked by filter\n"); 764238104Sdes if (frf & FF_LOGNOMATCH) 765238104Sdes PRINTF("\tpackets not matched by filter\n"); 766238104Sdes if (!frf) 767238104Sdes PRINTF("\tnone\n"); 768238104Sdes} 769238104Sdes 770238104Sdes 771238104Sdes/* 772238104Sdes * Print out a list of rules from the kernel, starting at the one passed. 773238104Sdes */ 774238104Sdesstatic void printlist(fp, comment) 775238104Sdesfrentry_t *fp; 776238104Sdeschar *comment; 777238104Sdes{ 778238104Sdes struct frentry fb, *fg; 779238104Sdes char *data; 780238104Sdes u_32_t type; 781238104Sdes int n; 782238104Sdes 783238104Sdes for (n = 1; fp; n++) { 784238104Sdes if (kmemcpy((char *)&fb, (u_long)fp, sizeof(fb)) == -1) { 785238104Sdes perror("kmemcpy"); 786238104Sdes return; 787238104Sdes } 788238104Sdes fp = &fb; 789238104Sdes if (opts & (OPT_HITS|OPT_VERBOSE)) 790238104Sdes#ifdef USE_QUAD_T 791238104Sdes PRINTF("%qu ", (unsigned long long) fp->fr_hits); 792238104Sdes#else 793238104Sdes PRINTF("%lu ", fp->fr_hits); 794238104Sdes#endif 795238104Sdes if (opts & (OPT_ACCNT|OPT_VERBOSE)) 796238104Sdes#ifdef USE_QUAD_T 797238104Sdes PRINTF("%qu ", (unsigned long long) fp->fr_bytes); 798238104Sdes#else 799238104Sdes PRINTF("%lu ", fp->fr_bytes); 800238104Sdes#endif 801238104Sdes if (opts & OPT_SHOWLINENO) 802238104Sdes PRINTF("@%d ", n); 803238104Sdes data = NULL; 804238104Sdes type = fp->fr_type & ~FR_T_BUILTIN; 805238104Sdes if (type == FR_T_IPF || type == FR_T_BPFOPC) { 806238104Sdes if (fp->fr_dsize) { 807238104Sdes data = malloc(fp->fr_dsize); 808238104Sdes 809238104Sdes if (kmemcpy(data, (u_long)fp->fr_data, 810238104Sdes fp->fr_dsize) == -1) { 811238104Sdes perror("kmemcpy"); 812238104Sdes return; 813238104Sdes } 814238104Sdes fp->fr_data = data; 815238104Sdes } 816238104Sdes } 817238104Sdes 818238104Sdes printfr(fp, ioctl); 819238104Sdes if (opts & OPT_DEBUG) { 820238104Sdes binprint(fp, sizeof(*fp)); 821238104Sdes if (fp->fr_data != NULL && fp->fr_dsize > 0) 822238104Sdes binprint(fp->fr_data, fp->fr_dsize); 823238104Sdes } 824238104Sdes if (data != NULL) 825238104Sdes free(data); 826238104Sdes if (fp->fr_grp != NULL) { 827238104Sdes if (!kmemcpy((char *)&fg, (u_long)fp->fr_grp, 828238104Sdes sizeof(fg))) 829238104Sdes printlist(fg, comment); 830238104Sdes } 831238104Sdes if (type == FR_T_CALLFUNC) { 832238104Sdes printlist(fp->fr_data, "# callfunc: "); 833238104Sdes } 834238104Sdes fp = fp->fr_next; 835238104Sdes } 836238104Sdes} 837238104Sdes 838238104Sdes/* 839238104Sdes * print out all of the asked for rule sets, using the stats struct as 840238104Sdes * the base from which to get the pointers. 841238104Sdes */ 842238104Sdesstatic void showlist(fiop) 843238104Sdesstruct friostat *fiop; 844238104Sdes{ 845238104Sdes struct frentry *fp = NULL; 846238104Sdes int i, set; 847238104Sdes 848238104Sdes set = fiop->f_active; 849238104Sdes if (opts & OPT_INACTIVE) 850238104Sdes set = 1 - set; 851238104Sdes if (opts & OPT_ACCNT) { 852238104Sdes#ifdef USE_INET6 853238104Sdes if ((use_inet6) && (opts & OPT_OUTQUE)) { 854238104Sdes i = F_ACOUT; 855238104Sdes fp = (struct frentry *)fiop->f_acctout6[set]; 856238104Sdes } else if ((use_inet6) && (opts & OPT_INQUE)) { 857238104Sdes i = F_ACIN; 858238104Sdes fp = (struct frentry *)fiop->f_acctin6[set]; 859238104Sdes } else 860238104Sdes#endif 861238104Sdes if (opts & OPT_OUTQUE) { 862238104Sdes i = F_ACOUT; 863238104Sdes fp = (struct frentry *)fiop->f_acctout[set]; 864238104Sdes } else if (opts & OPT_INQUE) { 865238104Sdes i = F_ACIN; 866238104Sdes fp = (struct frentry *)fiop->f_acctin[set]; 867238104Sdes } else { 868238104Sdes FPRINTF(stderr, "No -i or -o given with -a\n"); 869238104Sdes return; 870238104Sdes } 871238104Sdes } else { 872238104Sdes#ifdef USE_INET6 873238104Sdes if ((use_inet6) && (opts & OPT_OUTQUE)) { 874238104Sdes i = F_OUT; 875238104Sdes fp = (struct frentry *)fiop->f_fout6[set]; 876238104Sdes } else if ((use_inet6) && (opts & OPT_INQUE)) { 877238104Sdes i = F_IN; 878238104Sdes fp = (struct frentry *)fiop->f_fin6[set]; 879238104Sdes } else 880238104Sdes#endif 881238104Sdes if (opts & OPT_OUTQUE) { 882238104Sdes i = F_OUT; 883238104Sdes fp = (struct frentry *)fiop->f_fout[set]; 884238104Sdes } else if (opts & OPT_INQUE) { 885238104Sdes i = F_IN; 886238104Sdes fp = (struct frentry *)fiop->f_fin[set]; 887238104Sdes } else 888238104Sdes return; 889238104Sdes } 890238104Sdes if (opts & OPT_VERBOSE) 891238104Sdes FPRINTF(stderr, "showlist:opts %#x i %d\n", opts, i); 892238104Sdes 893238104Sdes if (opts & OPT_VERBOSE) 894238104Sdes PRINTF("fp %p set %d\n", fp, set); 895238104Sdes if (!fp) { 896238104Sdes FPRINTF(stderr, "empty list for %s%s\n", 897238104Sdes (opts & OPT_INACTIVE) ? "inactive " : "", filters[i]); 898238104Sdes return; 899238104Sdes } 900238104Sdes printlist(fp, NULL); 901238104Sdes} 902238104Sdes 903238104Sdes 904238104Sdes/* 905238104Sdes * Display ipfilter stateful filtering information 906238104Sdes */ 907238104Sdesstatic void showipstates(ipsp) 908238104Sdesips_stat_t *ipsp; 909238104Sdes{ 910238104Sdes u_long minlen, maxlen, totallen, *buckets; 911238104Sdes int i, sz; 912238104Sdes 913238104Sdes sz = sizeof(*buckets) * ipsp->iss_statesize; 914238104Sdes buckets = (u_long *)malloc(sz); 915238104Sdes if (kmemcpy((char *)buckets, (u_long)ipsp->iss_bucketlen, sz)) { 916238104Sdes free(buckets); 917238104Sdes return; 918238104Sdes } 919238104Sdes 920238104Sdes /* 921238104Sdes * If a list of states hasn't been asked for, only print out stats 922238104Sdes */ 923238104Sdes if (!(opts & OPT_SHOWLIST)) { 924238104Sdes PRINTF("IP states added:\n\t%lu TCP\n\t%lu UDP\n\t%lu ICMP\n", 925238104Sdes ipsp->iss_tcp, ipsp->iss_udp, ipsp->iss_icmp); 926238104Sdes PRINTF("\t%lu hits\n\t%lu misses\n", ipsp->iss_hits, 927238104Sdes ipsp->iss_miss); 928238104Sdes PRINTF("\t%lu maximum\n\t%lu no memory\n\t%lu max bucket\n", 929238104Sdes ipsp->iss_max, ipsp->iss_nomem, ipsp->iss_bucketfull); 930238104Sdes PRINTF("\t%lu maximum\n\t%lu no memory\n\t%lu bkts in use\n", 931238104Sdes ipsp->iss_max, ipsp->iss_nomem, ipsp->iss_inuse); 932238104Sdes PRINTF("\t%lu active\n\t%lu expired\n\t%lu closed\n", 933238104Sdes ipsp->iss_active, ipsp->iss_expire, ipsp->iss_fin); 934238104Sdes 935238104Sdes PRINTF("State logging %sabled\n", 936238104Sdes state_logging ? "en" : "dis"); 937238104Sdes 938238104Sdes PRINTF("\nState table bucket statistics:\n"); 939238104Sdes PRINTF("\t%lu in use\t\n", ipsp->iss_inuse); 940238104Sdes 941238104Sdes minlen = ipsp->iss_max; 942238104Sdes totallen = 0; 943238104Sdes maxlen = 0; 944238104Sdes 945238104Sdes for (i = 0; i < ipsp->iss_statesize; i++) { 946238104Sdes if (buckets[i] > maxlen) 947238104Sdes maxlen = buckets[i]; 948238104Sdes if (buckets[i] < minlen) 949238104Sdes minlen = buckets[i]; 950238104Sdes totallen += buckets[i]; 951238104Sdes } 952238104Sdes 953238104Sdes PRINTF("\t%2.2f%% bucket usage\n\t%lu minimal length\n", 954238104Sdes ((float)ipsp->iss_inuse / ipsp->iss_statesize) * 100.0, 955238104Sdes minlen); 956238104Sdes PRINTF("\t%lu maximal length\n\t%.3f average length\n", 957238104Sdes maxlen, 958238104Sdes ipsp->iss_inuse ? (float) totallen/ ipsp->iss_inuse : 959238104Sdes 0.0); 960238104Sdes 961238104Sdes#define ENTRIES_PER_LINE 5 962238104Sdes 963238104Sdes if (opts & OPT_VERBOSE) { 964238104Sdes PRINTF("\nCurrent bucket sizes :\n"); 965238104Sdes for (i = 0; i < ipsp->iss_statesize; i++) { 966238104Sdes if ((i % ENTRIES_PER_LINE) == 0) 967238104Sdes PRINTF("\t"); 968238104Sdes PRINTF("%4d -> %4lu", i, buckets[i]); 969238104Sdes if ((i % ENTRIES_PER_LINE) == 970238104Sdes (ENTRIES_PER_LINE - 1)) 971238104Sdes PRINTF("\n"); 972238104Sdes else 973238104Sdes PRINTF(" "); 974238104Sdes } 975238104Sdes PRINTF("\n"); 976238104Sdes } 977238104Sdes PRINTF("\n"); 978238104Sdes 979238104Sdes free(buckets); 980238104Sdes return; 981238104Sdes } 982238104Sdes 983238104Sdes /* 984238104Sdes * Print out all the state information currently held in the kernel. 985238104Sdes */ 986238104Sdes while (ipsp->iss_list != NULL) { 987238104Sdes ipsp->iss_list = printstate(ipsp->iss_list, opts, 988238104Sdes ipsp->iss_ticks); 989238104Sdes } 990238104Sdes 991238104Sdes free(buckets); 992238104Sdes} 993238104Sdes 994238104Sdes 995238104Sdes#ifdef STATETOP 996238104Sdesstatic int handle_resize = 0, handle_break = 0; 997238104Sdes 998238104Sdesstatic void topipstates(saddr, daddr, sport, dport, protocol, ver, 999238104Sdes refreshtime, topclosed) 1000238104Sdesi6addr_t saddr; 1001238104Sdesi6addr_t daddr; 1002238104Sdesint sport; 1003238104Sdesint dport; 1004238104Sdesint protocol; 1005238104Sdesint ver; 1006238104Sdesint refreshtime; 1007238104Sdesint topclosed; 1008238104Sdes{ 1009238104Sdes char str1[STSTRSIZE], str2[STSTRSIZE], str3[STSTRSIZE], str4[STSTRSIZE]; 1010238104Sdes int maxtsentries = 0, reverse = 0, sorting = STSORT_DEFAULT; 1011238104Sdes int i, j, winy, tsentry, maxx, maxy, redraw = 0; 1012238104Sdes int len, srclen, dstlen, forward = 1, c = 0; 1013238104Sdes ips_stat_t ipsst, *ipsstp = &ipsst; 1014238104Sdes statetop_t *tstable = NULL, *tp; 1015238104Sdes ipstate_t ips; 1016238104Sdes ipfobj_t ipfo; 1017238104Sdes struct timeval selecttimeout; 1018238104Sdes char hostnm[HOSTNMLEN]; 1019238104Sdes struct protoent *proto; 1020238104Sdes fd_set readfd; 1021238104Sdes time_t t; 1022238104Sdes 1023238104Sdes /* install signal handlers */ 1024238104Sdes signal(SIGINT, sig_break); 1025238104Sdes signal(SIGQUIT, sig_break); 1026238104Sdes signal(SIGTERM, sig_break); 1027238104Sdes signal(SIGWINCH, sig_resize); 1028238104Sdes 1029238104Sdes /* init ncurses stuff */ 1030238104Sdes initscr(); 1031238104Sdes cbreak(); 1032238104Sdes noecho(); 1033238104Sdes curs_set(0); 1034238104Sdes timeout(0); 1035238104Sdes getmaxyx(stdscr, maxy, maxx); 1036238104Sdes 1037238104Sdes /* init hostname */ 1038238104Sdes gethostname(hostnm, sizeof(hostnm) - 1); 1039238104Sdes hostnm[sizeof(hostnm) - 1] = '\0'; 1040238104Sdes 1041238104Sdes /* init ipfobj_t stuff */ 1042238104Sdes bzero((caddr_t)&ipfo, sizeof(ipfo)); 1043238104Sdes ipfo.ipfo_rev = IPFILTER_VERSION; 1044238104Sdes ipfo.ipfo_size = sizeof(*ipsstp); 1045238104Sdes ipfo.ipfo_ptr = (void *)ipsstp; 1046238104Sdes ipfo.ipfo_type = IPFOBJ_STATESTAT; 1047238104Sdes 1048238104Sdes /* repeat until user aborts */ 1049238104Sdes while ( 1 ) { 1050238104Sdes 1051238104Sdes /* get state table */ 1052238104Sdes bzero((char *)&ipsst, sizeof(ipsst)); 1053238104Sdes if ((ioctl(state_fd, SIOCGETFS, &ipfo) == -1)) { 1054238104Sdes perror("ioctl(SIOCGETFS)"); 1055238104Sdes exit(-1); 1056238104Sdes } 1057238104Sdes 1058238104Sdes /* clear the history */ 1059238104Sdes tsentry = -1; 1060238104Sdes 1061238104Sdes /* reset max str len */ 1062238104Sdes srclen = dstlen = 0; 1063238104Sdes 1064238104Sdes /* read the state table and store in tstable */ 1065238104Sdes for (; ipsstp->iss_list; ipsstp->iss_list = ips.is_next) { 1066238104Sdes 1067238104Sdes if (kmemcpy((char *)&ips, (u_long)ipsstp->iss_list, 1068238104Sdes sizeof(ips))) 1069238104Sdes break; 1070238104Sdes 1071238104Sdes if (ips.is_v != ver) 1072238104Sdes continue; 1073238104Sdes 1074238104Sdes /* check v4 src/dest addresses */ 1075238104Sdes if (ips.is_v == 4) { 1076238104Sdes if ((saddr.in4.s_addr != INADDR_ANY && 1077238104Sdes saddr.in4.s_addr != ips.is_saddr) || 1078238104Sdes (daddr.in4.s_addr != INADDR_ANY && 1079238104Sdes daddr.in4.s_addr != ips.is_daddr)) 1080238104Sdes continue; 1081238104Sdes } 1082238104Sdes#ifdef USE_INET6 1083238104Sdes /* check v6 src/dest addresses */ 1084238104Sdes if (ips.is_v == 6) { 1085238104Sdes if ((IP6_NEQ(&saddr, &in6addr_any) && 1086238104Sdes IP6_NEQ(&saddr, &ips.is_src)) || 1087238104Sdes (IP6_NEQ(&daddr, &in6addr_any) && 1088238104Sdes IP6_NEQ(&daddr, &ips.is_dst))) 1089238104Sdes continue; 1090238104Sdes } 1091238104Sdes#endif 1092238104Sdes /* check protocol */ 1093238104Sdes if (protocol > 0 && protocol != ips.is_p) 1094238104Sdes continue; 1095238104Sdes 1096238104Sdes /* check ports if protocol is TCP or UDP */ 1097238104Sdes if (((ips.is_p == IPPROTO_TCP) || 1098238104Sdes (ips.is_p == IPPROTO_UDP)) && 1099238104Sdes (((sport > 0) && (htons(sport) != ips.is_sport)) || 1100238104Sdes ((dport > 0) && (htons(dport) != ips.is_dport)))) 1101238104Sdes continue; 1102238104Sdes 1103238104Sdes /* show closed TCP sessions ? */ 1104238104Sdes if ((topclosed == 0) && (ips.is_p == IPPROTO_TCP) && 1105238104Sdes (ips.is_state[0] >= IPF_TCPS_LAST_ACK) && 1106238104Sdes (ips.is_state[1] >= IPF_TCPS_LAST_ACK)) 1107238104Sdes continue; 1108238104Sdes 1109238104Sdes /* 1110238104Sdes * if necessary make room for this state 1111238104Sdes * entry 1112238104Sdes */ 1113238104Sdes tsentry++; 1114238104Sdes if (!maxtsentries || tsentry == maxtsentries) { 1115238104Sdes maxtsentries += STGROWSIZE; 1116238104Sdes tstable = realloc(tstable, 1117238104Sdes maxtsentries * sizeof(statetop_t)); 1118238104Sdes if (tstable == NULL) { 1119238104Sdes perror("realloc"); 1120238104Sdes exit(-1); 1121238104Sdes } 1122238104Sdes } 1123238104Sdes 1124238104Sdes /* get max src/dest address string length */ 1125238104Sdes len = strlen(getip(ips.is_v, &ips.is_src)); 1126238104Sdes if (srclen < len) 1127238104Sdes srclen = len; 1128238104Sdes len = strlen(getip(ips.is_v, &ips.is_dst)); 1129238104Sdes if (dstlen < len) 1130238104Sdes dstlen = len; 1131238104Sdes 1132238104Sdes /* fill structure */ 1133238104Sdes tp = tstable + tsentry; 1134238104Sdes tp->st_src = ips.is_src; 1135238104Sdes tp->st_dst = ips.is_dst; 1136238104Sdes tp->st_p = ips.is_p; 1137238104Sdes tp->st_v = ips.is_v; 1138238104Sdes tp->st_state[0] = ips.is_state[0]; 1139238104Sdes tp->st_state[1] = ips.is_state[1]; 1140238104Sdes if (forward) { 1141238104Sdes tp->st_pkts = ips.is_pkts[0]+ips.is_pkts[1]; 1142238104Sdes tp->st_bytes = ips.is_bytes[0]+ips.is_bytes[1]; 1143238104Sdes } else { 1144238104Sdes tp->st_pkts = ips.is_pkts[2]+ips.is_pkts[3]; 1145238104Sdes tp->st_bytes = ips.is_bytes[2]+ips.is_bytes[3]; 1146238104Sdes } 1147238104Sdes tp->st_age = ips.is_die - ipsstp->iss_ticks; 1148238104Sdes if ((ips.is_p == IPPROTO_TCP) || 1149238104Sdes (ips.is_p == IPPROTO_UDP)) { 1150238104Sdes tp->st_sport = ips.is_sport; 1151238104Sdes tp->st_dport = ips.is_dport; 1152238104Sdes } 1153238104Sdes } 1154238104Sdes 1155238104Sdes 1156238104Sdes /* sort the array */ 1157238104Sdes if (tsentry != -1) { 1158238104Sdes switch (sorting) 1159238104Sdes { 1160238104Sdes case STSORT_PR: 1161238104Sdes qsort(tstable, tsentry + 1, 1162238104Sdes sizeof(statetop_t), sort_p); 1163238104Sdes break; 1164238104Sdes case STSORT_PKTS: 1165238104Sdes qsort(tstable, tsentry + 1, 1166238104Sdes sizeof(statetop_t), sort_pkts); 1167238104Sdes break; 1168238104Sdes case STSORT_BYTES: 1169238104Sdes qsort(tstable, tsentry + 1, 1170238104Sdes sizeof(statetop_t), sort_bytes); 1171238104Sdes break; 1172238104Sdes case STSORT_TTL: 1173238104Sdes qsort(tstable, tsentry + 1, 1174238104Sdes sizeof(statetop_t), sort_ttl); 1175238104Sdes break; 1176238104Sdes case STSORT_SRCIP: 1177238104Sdes qsort(tstable, tsentry + 1, 1178238104Sdes sizeof(statetop_t), sort_srcip); 1179238104Sdes break; 1180238104Sdes case STSORT_SRCPT: 1181238104Sdes qsort(tstable, tsentry +1, 1182238104Sdes sizeof(statetop_t), sort_srcpt); 1183238104Sdes break; 1184238104Sdes case STSORT_DSTIP: 1185238104Sdes qsort(tstable, tsentry + 1, 1186238104Sdes sizeof(statetop_t), sort_dstip); 1187238104Sdes break; 1188238104Sdes case STSORT_DSTPT: 1189238104Sdes qsort(tstable, tsentry + 1, 1190238104Sdes sizeof(statetop_t), sort_dstpt); 1191238104Sdes break; 1192238104Sdes default: 1193238104Sdes break; 1194238104Sdes } 1195238104Sdes } 1196238104Sdes 1197238104Sdes /* handle window resizes */ 1198238104Sdes if (handle_resize) { 1199238104Sdes endwin(); 1200238104Sdes initscr(); 1201238104Sdes cbreak(); 1202238104Sdes noecho(); 1203238104Sdes curs_set(0); 1204238104Sdes timeout(0); 1205238104Sdes getmaxyx(stdscr, maxy, maxx); 1206238104Sdes redraw = 1; 1207238104Sdes handle_resize = 0; 1208238104Sdes } 1209238104Sdes 1210238104Sdes /* stop program? */ 1211238104Sdes if (handle_break) 1212238104Sdes break; 1213238104Sdes 1214238104Sdes /* print title */ 1215238104Sdes erase(); 1216238104Sdes attron(A_BOLD); 1217238104Sdes winy = 0; 1218238104Sdes move(winy,0); 1219238104Sdes sprintf(str1, "%s - %s - state top", hostnm, IPL_VERSION); 1220238104Sdes for (j = 0 ; j < (maxx - 8 - strlen(str1)) / 2; j++) 1221238104Sdes printw(" "); 1222238104Sdes printw("%s", str1); 1223238104Sdes attroff(A_BOLD); 1224238104Sdes 1225238104Sdes /* just for fun add a clock */ 1226238104Sdes move(winy, maxx - 8); 1227238104Sdes t = time(NULL); 1228238104Sdes strftime(str1, 80, "%T", localtime(&t)); 1229238104Sdes printw("%s\n", str1); 1230238104Sdes 1231238104Sdes /* 1232238104Sdes * print the display filters, this is placed in the loop, 1233238104Sdes * because someday I might add code for changing these 1234238104Sdes * while the programming is running :-) 1235238104Sdes */ 1236238104Sdes if (sport >= 0) 1237238104Sdes sprintf(str1, "%s,%d", getip(ver, &saddr), sport); 1238238104Sdes else 1239238104Sdes sprintf(str1, "%s", getip(ver, &saddr)); 1240238104Sdes 1241238104Sdes if (dport >= 0) 1242238104Sdes sprintf(str2, "%s,%d", getip(ver, &daddr), dport); 1243238104Sdes else 1244238104Sdes sprintf(str2, "%s", getip(ver, &daddr)); 1245238104Sdes 1246238104Sdes if (protocol < 0) 1247238104Sdes strcpy(str3, "any"); 1248238104Sdes else if ((proto = getprotobynumber(protocol)) != NULL) 1249238104Sdes sprintf(str3, "%s", proto->p_name); 1250238104Sdes else 1251238104Sdes sprintf(str3, "%d", protocol); 1252238104Sdes 1253238104Sdes switch (sorting) 1254238104Sdes { 1255238104Sdes case STSORT_PR: 1256238104Sdes sprintf(str4, "proto"); 1257238104Sdes break; 1258238104Sdes case STSORT_PKTS: 1259238104Sdes sprintf(str4, "# pkts"); 1260238104Sdes break; 1261238104Sdes case STSORT_BYTES: 1262238104Sdes sprintf(str4, "# bytes"); 1263238104Sdes break; 1264238104Sdes case STSORT_TTL: 1265238104Sdes sprintf(str4, "ttl"); 1266238104Sdes break; 1267238104Sdes case STSORT_SRCIP: 1268238104Sdes sprintf(str4, "src ip"); 1269238104Sdes break; 1270238104Sdes case STSORT_SRCPT: 1271238104Sdes sprintf(str4, "src port"); 1272238104Sdes break; 1273238104Sdes case STSORT_DSTIP: 1274238104Sdes sprintf(str4, "dest ip"); 1275238104Sdes break; 1276238104Sdes case STSORT_DSTPT: 1277238104Sdes sprintf(str4, "dest port"); 1278238104Sdes break; 1279238104Sdes default: 1280238104Sdes sprintf(str4, "unknown"); 1281238104Sdes break; 1282238104Sdes } 1283238104Sdes 1284238104Sdes if (reverse) 1285238104Sdes strcat(str4, " (reverse)"); 1286238104Sdes 1287238104Sdes winy += 2; 1288238104Sdes move(winy,0); 1289238104Sdes printw("Src: %s, Dest: %s, Proto: %s, Sorted by: %s\n\n", 1290238104Sdes str1, str2, str3, str4); 1291238104Sdes 1292238104Sdes /* 1293238104Sdes * For an IPv4 IP address we need at most 15 characters, 1294238104Sdes * 4 tuples of 3 digits, separated by 3 dots. Enforce this 1295238104Sdes * length, so the colums do not change positions based 1296238104Sdes * on the size of the IP address. This length makes the 1297238104Sdes * output fit in a 80 column terminal. 1298238104Sdes * We are lacking a good solution for IPv6 addresses (that 1299238104Sdes * can be longer that 15 characters), so we do not enforce 1300238104Sdes * a maximum on the IP field size. 1301238104Sdes */ 1302238104Sdes if (srclen < 15) 1303238104Sdes srclen = 15; 1304238104Sdes if (dstlen < 15) 1305238104Sdes dstlen = 15; 1306238104Sdes 1307238104Sdes /* print column description */ 1308238104Sdes winy += 2; 1309238104Sdes move(winy,0); 1310238104Sdes attron(A_BOLD); 1311238104Sdes printw("%-*s %-*s %3s %4s %7s %9s %9s\n", 1312238104Sdes srclen + 6, "Source IP", dstlen + 6, "Destination IP", 1313238104Sdes "ST", "PR", "#pkts", "#bytes", "ttl"); 1314238104Sdes attroff(A_BOLD); 1315238104Sdes 1316238104Sdes /* print all the entries */ 1317238104Sdes tp = tstable; 1318238104Sdes if (reverse) 1319238104Sdes tp += tsentry; 1320 1321 if (tsentry > maxy - 6) 1322 tsentry = maxy - 6; 1323 for (i = 0; i <= tsentry; i++) { 1324 /* print src/dest and port */ 1325 if ((tp->st_p == IPPROTO_TCP) || 1326 (tp->st_p == IPPROTO_UDP)) { 1327 sprintf(str1, "%s,%hu", 1328 getip(tp->st_v, &tp->st_src), 1329 ntohs(tp->st_sport)); 1330 sprintf(str2, "%s,%hu", 1331 getip(tp->st_v, &tp->st_dst), 1332 ntohs(tp->st_dport)); 1333 } else { 1334 sprintf(str1, "%s", getip(tp->st_v, 1335 &tp->st_src)); 1336 sprintf(str2, "%s", getip(tp->st_v, 1337 &tp->st_dst)); 1338 } 1339 winy++; 1340 move(winy, 0); 1341 printw("%-*s %-*s", srclen + 6, str1, dstlen + 6, str2); 1342 1343 /* print state */ 1344 sprintf(str1, "%X/%X", tp->st_state[0], 1345 tp->st_state[1]); 1346 printw(" %3s", str1); 1347 1348 /* print protocol */ 1349 proto = getprotobynumber(tp->st_p); 1350 if (proto) { 1351 strncpy(str1, proto->p_name, 4); 1352 str1[4] = '\0'; 1353 } else { 1354 sprintf(str1, "%d", tp->st_p); 1355 } 1356 /* just print icmp for IPv6-ICMP */ 1357 if (tp->st_p == IPPROTO_ICMPV6) 1358 strcpy(str1, "icmp"); 1359 printw(" %4s", str1); 1360 1361 /* print #pkt/#bytes */ 1362#ifdef USE_QUAD_T 1363 printw(" %7qu %9qu", (unsigned long long) tp->st_pkts, 1364 (unsigned long long) tp->st_bytes); 1365#else 1366 printw(" %7lu %9lu", tp->st_pkts, tp->st_bytes); 1367#endif 1368 printw(" %9s", ttl_to_string(tp->st_age)); 1369 1370 if (reverse) 1371 tp--; 1372 else 1373 tp++; 1374 } 1375 1376 /* screen data structure is filled, now update the screen */ 1377 if (redraw) 1378 clearok(stdscr,1); 1379 1380 if (refresh() == ERR) 1381 break; 1382 if (redraw) { 1383 clearok(stdscr,0); 1384 redraw = 0; 1385 } 1386 1387 /* wait for key press or a 1 second time out period */ 1388 selecttimeout.tv_sec = refreshtime; 1389 selecttimeout.tv_usec = 0; 1390 FD_ZERO(&readfd); 1391 FD_SET(0, &readfd); 1392 select(1, &readfd, NULL, NULL, &selecttimeout); 1393 1394 /* if key pressed, read all waiting keys */ 1395 if (FD_ISSET(0, &readfd)) { 1396 c = wgetch(stdscr); 1397 if (c == ERR) 1398 continue; 1399 1400 if (ISALPHA(c) && ISUPPER(c)) 1401 c = TOLOWER(c); 1402 if (c == 'l') { 1403 redraw = 1; 1404 } else if (c == 'q') { 1405 break; 1406 } else if (c == 'r') { 1407 reverse = !reverse; 1408 } else if (c == 'b') { 1409 forward = 0; 1410 } else if (c == 'f') { 1411 forward = 1; 1412 } else if (c == 's') { 1413 if (++sorting > STSORT_MAX) 1414 sorting = 0; 1415 } 1416 } 1417 } /* while */ 1418 1419 printw("\n"); 1420 curs_set(1); 1421 nocbreak(); 1422 endwin(); 1423 1424 free(tstable); 1425} 1426#endif 1427 1428 1429/* 1430 * Show fragment cache information that's held in the kernel. 1431 */ 1432static void showfrstates(ifsp) 1433ipfrstat_t *ifsp; 1434{ 1435 struct ipfr *ipfrtab[IPFT_SIZE], ifr; 1436 int i; 1437 1438 /* 1439 * print out the numeric statistics 1440 */ 1441 PRINTF("IP fragment states:\n\t%lu new\n\t%lu expired\n\t%lu hits\n", 1442 ifsp->ifs_new, ifsp->ifs_expire, ifsp->ifs_hits); 1443 PRINTF("\t%lu retrans\n\t%lu too short\n", 1444 ifsp->ifs_retrans0, ifsp->ifs_short); 1445 PRINTF("\t%lu no memory\n\t%lu already exist\n", 1446 ifsp->ifs_nomem, ifsp->ifs_exists); 1447 PRINTF("\t%lu inuse\n", ifsp->ifs_inuse); 1448 if (kmemcpy((char *)ipfrtab, (u_long)ifsp->ifs_table, sizeof(ipfrtab))) 1449 return; 1450 1451 /* 1452 * Print out the contents (if any) of the fragment cache table. 1453 */ 1454 PRINTF("\n"); 1455 for (i = 0; i < IPFT_SIZE; i++) 1456 while (ipfrtab[i] != NULL) { 1457 if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i], 1458 sizeof(ifr)) == -1) 1459 break; 1460 printfraginfo("", &ifr); 1461 ipfrtab[i] = ifr.ipfr_next; 1462 } 1463 /* 1464 * Print out the contents (if any) of the NAT fragment cache table. 1465 */ 1466 if (kmemcpy((char *)ipfrtab, (u_long)ifsp->ifs_nattab,sizeof(ipfrtab))) 1467 return; 1468 for (i = 0; i < IPFT_SIZE; i++) 1469 while (ipfrtab[i] != NULL) { 1470 if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i], 1471 sizeof(ifr)) == -1) 1472 break; 1473 printfraginfo("NAT: ", &ifr); 1474 ipfrtab[i] = ifr.ipfr_next; 1475 } 1476} 1477 1478 1479/* 1480 * Show stats on how auth within IPFilter has been used 1481 */ 1482static void showauthstates(asp) 1483fr_authstat_t *asp; 1484{ 1485 frauthent_t *frap, fra; 1486 1487#ifdef USE_QUAD_T 1488 printf("Authorisation hits: %qu\tmisses %qu\n", 1489 (unsigned long long) asp->fas_hits, 1490 (unsigned long long) asp->fas_miss); 1491#else 1492 printf("Authorisation hits: %ld\tmisses %ld\n", asp->fas_hits, 1493 asp->fas_miss); 1494#endif 1495 printf("nospace %ld\nadded %ld\nsendfail %ld\nsendok %ld\n", 1496 asp->fas_nospace, asp->fas_added, asp->fas_sendfail, 1497 asp->fas_sendok); 1498 printf("queok %ld\nquefail %ld\nexpire %ld\n", 1499 asp->fas_queok, asp->fas_quefail, asp->fas_expire); 1500 1501 frap = asp->fas_faelist; 1502 while (frap) { 1503 if (kmemcpy((char *)&fra, (u_long)frap, sizeof(fra)) == -1) 1504 break; 1505 1506 printf("age %ld\t", fra.fae_age); 1507 printfr(&fra.fae_fr, ioctl); 1508 frap = fra.fae_next; 1509 } 1510} 1511 1512 1513/* 1514 * Display groups used for each of filter rules, accounting rules and 1515 * authentication, separately. 1516 */ 1517static void showgroups(fiop) 1518struct friostat *fiop; 1519{ 1520 static char *gnames[3] = { "Filter", "Accounting", "Authentication" }; 1521 static int gnums[3] = { IPL_LOGIPF, IPL_LOGCOUNT, IPL_LOGAUTH }; 1522 frgroup_t *fp, grp; 1523 int on, off, i; 1524 1525 on = fiop->f_active; 1526 off = 1 - on; 1527 1528 for (i = 0; i < 3; i++) { 1529 printf("%s groups (active):\n", gnames[i]); 1530 for (fp = fiop->f_groups[gnums[i]][on]; fp != NULL; 1531 fp = grp.fg_next) 1532 if (kmemcpy((char *)&grp, (u_long)fp, sizeof(grp))) 1533 break; 1534 else 1535 printf("%s\n", grp.fg_name); 1536 printf("%s groups (inactive):\n", gnames[i]); 1537 for (fp = fiop->f_groups[gnums[i]][off]; fp != NULL; 1538 fp = grp.fg_next) 1539 if (kmemcpy((char *)&grp, (u_long)fp, sizeof(grp))) 1540 break; 1541 else 1542 printf("%s\n", grp.fg_name); 1543 } 1544} 1545 1546static void parse_ipportstr(argument, ip, port) 1547const char *argument; 1548i6addr_t *ip; 1549int *port; 1550{ 1551 char *s, *comma; 1552 int ok = 0; 1553 1554 /* make working copy of argument, Theoretically you must be able 1555 * to write to optarg, but that seems very ugly to me.... 1556 */ 1557 s = strdup(argument); 1558 if (s == NULL) 1559 return; 1560 1561 /* get port */ 1562 if ((comma = strchr(s, ',')) != NULL) { 1563 if (!strcasecmp(comma + 1, "any")) { 1564 *port = -1; 1565 } else if (!sscanf(comma + 1, "%d", port) || 1566 (*port < 0) || (*port > 65535)) { 1567 fprintf(stderr, "Invalid port specfication in %s\n", 1568 argument); 1569 free(s); 1570 exit(-2); 1571 } 1572 *comma = '\0'; 1573 } 1574 1575 1576 /* get ip address */ 1577 if (!strcasecmp(s, "any")) { 1578 ip->in4.s_addr = INADDR_ANY; 1579#ifdef USE_INET6 1580 ip->in6 = in6addr_any; 1581 } else if (use_inet6 && inet_pton(AF_INET6, s, &ip->in6)) { 1582 ok = 1; 1583#endif 1584 } else if (inet_aton(s, &ip->in4)) 1585 ok = 1; 1586 1587 if (ok == 0) { 1588 fprintf(stderr, "Invalid IP address: %s\n", s); 1589 free(s); 1590 exit(-2); 1591 } 1592 1593 /* free allocated memory */ 1594 free(s); 1595} 1596 1597 1598#ifdef STATETOP 1599static void sig_resize(s) 1600int s; 1601{ 1602 handle_resize = 1; 1603} 1604 1605static void sig_break(s) 1606int s; 1607{ 1608 handle_break = 1; 1609} 1610 1611static char *getip(v, addr) 1612int v; 1613i6addr_t *addr; 1614{ 1615 static char hostbuf[MAXHOSTNAMELEN+1]; 1616 1617 if (v == 4) 1618 return inet_ntoa(addr->in4); 1619 1620#ifdef USE_INET6 1621 (void) inet_ntop(AF_INET6, &addr->in6, hostbuf, sizeof(hostbuf) - 1); 1622 hostbuf[MAXHOSTNAMELEN] = '\0'; 1623 return hostbuf; 1624#else 1625 return "IPv6"; 1626#endif 1627} 1628 1629 1630static char *ttl_to_string(ttl) 1631long int ttl; 1632{ 1633 static char ttlbuf[STSTRSIZE]; 1634 int hours, minutes, seconds; 1635 1636 /* ttl is in half seconds */ 1637 ttl /= 2; 1638 1639 hours = ttl / 3600; 1640 ttl = ttl % 3600; 1641 minutes = ttl / 60; 1642 seconds = ttl % 60; 1643 1644 if (hours > 0) 1645 sprintf(ttlbuf, "%2d:%02d:%02d", hours, minutes, seconds); 1646 else 1647 sprintf(ttlbuf, "%2d:%02d", minutes, seconds); 1648 return ttlbuf; 1649} 1650 1651 1652static int sort_pkts(a, b) 1653const void *a; 1654const void *b; 1655{ 1656 1657 register const statetop_t *ap = a; 1658 register const statetop_t *bp = b; 1659 1660 if (ap->st_pkts == bp->st_pkts) 1661 return 0; 1662 else if (ap->st_pkts < bp->st_pkts) 1663 return 1; 1664 return -1; 1665} 1666 1667 1668static int sort_bytes(a, b) 1669const void *a; 1670const void *b; 1671{ 1672 register const statetop_t *ap = a; 1673 register const statetop_t *bp = b; 1674 1675 if (ap->st_bytes == bp->st_bytes) 1676 return 0; 1677 else if (ap->st_bytes < bp->st_bytes) 1678 return 1; 1679 return -1; 1680} 1681 1682 1683static int sort_p(a, b) 1684const void *a; 1685const void *b; 1686{ 1687 register const statetop_t *ap = a; 1688 register const statetop_t *bp = b; 1689 1690 if (ap->st_p == bp->st_p) 1691 return 0; 1692 else if (ap->st_p < bp->st_p) 1693 return 1; 1694 return -1; 1695} 1696 1697 1698static int sort_ttl(a, b) 1699const void *a; 1700const void *b; 1701{ 1702 register const statetop_t *ap = a; 1703 register const statetop_t *bp = b; 1704 1705 if (ap->st_age == bp->st_age) 1706 return 0; 1707 else if (ap->st_age < bp->st_age) 1708 return 1; 1709 return -1; 1710} 1711 1712static int sort_srcip(a, b) 1713const void *a; 1714const void *b; 1715{ 1716 register const statetop_t *ap = a; 1717 register const statetop_t *bp = b; 1718 1719#ifdef USE_INET6 1720 if (use_inet6) { 1721 if (IP6_EQ(&ap->st_src, &bp->st_src)) 1722 return 0; 1723 else if (IP6_GT(&ap->st_src, &bp->st_src)) 1724 return 1; 1725 } else 1726#endif 1727 { 1728 if (ntohl(ap->st_src.in4.s_addr) == 1729 ntohl(bp->st_src.in4.s_addr)) 1730 return 0; 1731 else if (ntohl(ap->st_src.in4.s_addr) > 1732 ntohl(bp->st_src.in4.s_addr)) 1733 return 1; 1734 } 1735 return -1; 1736} 1737 1738static int sort_srcpt(a, b) 1739const void *a; 1740const void *b; 1741{ 1742 register const statetop_t *ap = a; 1743 register const statetop_t *bp = b; 1744 1745 if (htons(ap->st_sport) == htons(bp->st_sport)) 1746 return 0; 1747 else if (htons(ap->st_sport) > htons(bp->st_sport)) 1748 return 1; 1749 return -1; 1750} 1751 1752static int sort_dstip(a, b) 1753const void *a; 1754const void *b; 1755{ 1756 register const statetop_t *ap = a; 1757 register const statetop_t *bp = b; 1758 1759#ifdef USE_INET6 1760 if (use_inet6) { 1761 if (IP6_EQ(&ap->st_dst, &bp->st_dst)) 1762 return 0; 1763 else if (IP6_GT(&ap->st_dst, &bp->st_dst)) 1764 return 1; 1765 } else 1766#endif 1767 { 1768 if (ntohl(ap->st_dst.in4.s_addr) == 1769 ntohl(bp->st_dst.in4.s_addr)) 1770 return 0; 1771 else if (ntohl(ap->st_dst.in4.s_addr) > 1772 ntohl(bp->st_dst.in4.s_addr)) 1773 return 1; 1774 } 1775 return -1; 1776} 1777 1778static int sort_dstpt(a, b) 1779const void *a; 1780const void *b; 1781{ 1782 register const statetop_t *ap = a; 1783 register const statetop_t *bp = b; 1784 1785 if (htons(ap->st_dport) == htons(bp->st_dport)) 1786 return 0; 1787 else if (htons(ap->st_dport) > htons(bp->st_dport)) 1788 return 1; 1789 return -1; 1790} 1791 1792#endif 1793