1145519Sdarrenr/* $FreeBSD$ */ 2145510Sdarrenr 3145510Sdarrenr/* 4170268Sdarrenr * Copyright (C) 2002-2006 by Darren Reed. 5145510Sdarrenr * 6145510Sdarrenr * See the IPFILTER.LICENCE file for details on licencing. 7145510Sdarrenr */ 8145510Sdarrenr#ifdef __FreeBSD__ 9145510Sdarrenr# ifndef __FreeBSD_cc_version 10145510Sdarrenr# include <osreldate.h> 11145510Sdarrenr# else 12145510Sdarrenr# if __FreeBSD_cc_version < 430000 13145510Sdarrenr# include <osreldate.h> 14145510Sdarrenr# endif 15145510Sdarrenr# endif 16145510Sdarrenr#endif 17145510Sdarrenr#include <sys/ioctl.h> 18145510Sdarrenr#include <fcntl.h> 19145510Sdarrenr#ifdef linux 20145510Sdarrenr# include <linux/a.out.h> 21145510Sdarrenr#else 22145510Sdarrenr# include <nlist.h> 23145510Sdarrenr#endif 24145510Sdarrenr#include <ctype.h> 25145510Sdarrenr#if defined(sun) && (defined(__svr4__) || defined(__SVR4)) 26145510Sdarrenr# include <stddef.h> 27145510Sdarrenr#endif 28145510Sdarrenr#include "ipf.h" 29145510Sdarrenr#include "netinet/ipl.h" 30145510Sdarrenr#if defined(STATETOP) 31145510Sdarrenr# if defined(_BSDI_VERSION) 32145510Sdarrenr# undef STATETOP 33145510Sdarrenr# endif 34145510Sdarrenr# if defined(__FreeBSD__) && \ 35145510Sdarrenr (!defined(__FreeBSD_version) || (__FreeBSD_version < 430000)) 36145510Sdarrenr# undef STATETOP 37145510Sdarrenr# endif 38145510Sdarrenr# if defined(__NetBSD_Version__) && (__NetBSD_Version__ < 105000000) 39145510Sdarrenr# undef STATETOP 40145510Sdarrenr# endif 41145510Sdarrenr# if defined(sun) 42145510Sdarrenr# if defined(__svr4__) || defined(__SVR4) 43145510Sdarrenr# include <sys/select.h> 44145510Sdarrenr# else 45145510Sdarrenr# undef STATETOP /* NOT supported on SunOS4 */ 46145510Sdarrenr# endif 47145510Sdarrenr# endif 48145510Sdarrenr#endif 49145510Sdarrenr#if defined(STATETOP) && !defined(linux) 50145510Sdarrenr# include <netinet/ip_var.h> 51145510Sdarrenr# include <netinet/tcp_fsm.h> 52145510Sdarrenr#endif 53145510Sdarrenr#ifdef STATETOP 54145510Sdarrenr# include <ctype.h> 55145510Sdarrenr# include <signal.h> 56170268Sdarrenr# include <time.h> 57145510Sdarrenr# if SOLARIS || defined(__NetBSD__) || defined(_BSDI_VERSION) || \ 58145510Sdarrenr defined(__sgi) 59145510Sdarrenr# ifdef ERR 60145510Sdarrenr# undef ERR 61145510Sdarrenr# endif 62145510Sdarrenr# include <curses.h> 63145510Sdarrenr# else /* SOLARIS */ 64145510Sdarrenr# include <ncurses.h> 65145510Sdarrenr# endif /* SOLARIS */ 66145510Sdarrenr#endif /* STATETOP */ 67145510Sdarrenr#include "kmem.h" 68145510Sdarrenr#if defined(__NetBSD__) || (__OpenBSD__) 69145510Sdarrenr# include <paths.h> 70145510Sdarrenr#endif 71145510Sdarrenr 72145510Sdarrenr#if !defined(lint) 73145510Sdarrenrstatic const char sccsid[] = "@(#)fils.c 1.21 4/20/96 (C) 1993-2000 Darren Reed"; 74172776Sdarrenrstatic const char rcsid[] = "@(#)$Id: ipfstat.c,v 1.44.2.25 2007/06/30 09:48:50 darrenr Exp $"; 75145510Sdarrenr#endif 76145510Sdarrenr 77145510Sdarrenr#ifdef __hpux 78145510Sdarrenr# define nlist nlist64 79145510Sdarrenr#endif 80145510Sdarrenr 81145510Sdarrenrextern char *optarg; 82145510Sdarrenrextern int optind; 83145510Sdarrenrextern int opterr; 84145510Sdarrenr 85145510Sdarrenr#define PRINTF (void)printf 86145510Sdarrenr#define FPRINTF (void)fprintf 87145510Sdarrenrstatic char *filters[4] = { "ipfilter(in)", "ipfilter(out)", 88145510Sdarrenr "ipacct(in)", "ipacct(out)" }; 89145510Sdarrenrstatic int state_logging = -1; 90145510Sdarrenr 91145510Sdarrenrint opts = 0; 92145510Sdarrenrint use_inet6 = 0; 93145510Sdarrenrint live_kernel = 1; 94145510Sdarrenrint state_fd = -1; 95145510Sdarrenrint ipf_fd = -1; 96170268Sdarrenrint auth_fd = -1; 97170268Sdarrenrint nat_fd = -1; 98170268Sdarrenrfrgroup_t *grtop = NULL; 99170268Sdarrenrfrgroup_t *grtail = NULL; 100145510Sdarrenr 101145510Sdarrenr#ifdef STATETOP 102145510Sdarrenr#define STSTRSIZE 80 103145510Sdarrenr#define STGROWSIZE 16 104145510Sdarrenr#define HOSTNMLEN 40 105145510Sdarrenr 106145510Sdarrenr#define STSORT_PR 0 107145510Sdarrenr#define STSORT_PKTS 1 108145510Sdarrenr#define STSORT_BYTES 2 109145510Sdarrenr#define STSORT_TTL 3 110145510Sdarrenr#define STSORT_SRCIP 4 111145510Sdarrenr#define STSORT_SRCPT 5 112145510Sdarrenr#define STSORT_DSTIP 6 113145510Sdarrenr#define STSORT_DSTPT 7 114145510Sdarrenr#define STSORT_MAX STSORT_DSTPT 115145510Sdarrenr#define STSORT_DEFAULT STSORT_BYTES 116145510Sdarrenr 117145510Sdarrenr 118145510Sdarrenrtypedef struct statetop { 119145510Sdarrenr i6addr_t st_src; 120145510Sdarrenr i6addr_t st_dst; 121145510Sdarrenr u_short st_sport; 122145510Sdarrenr u_short st_dport; 123145510Sdarrenr u_char st_p; 124145510Sdarrenr u_char st_v; 125145510Sdarrenr u_char st_state[2]; 126145510Sdarrenr U_QUAD_T st_pkts; 127145510Sdarrenr U_QUAD_T st_bytes; 128145510Sdarrenr u_long st_age; 129145510Sdarrenr} statetop_t; 130145510Sdarrenr#endif 131145510Sdarrenr 132145510Sdarrenrint main __P((int, char *[])); 133145510Sdarrenr 134170268Sdarrenrstatic int fetchfrag __P((int, int, ipfr_t *)); 135145510Sdarrenrstatic void showstats __P((friostat_t *, u_32_t)); 136170268Sdarrenrstatic void showfrstates __P((ipfrstat_t *, u_long)); 137145510Sdarrenrstatic void showlist __P((friostat_t *)); 138145510Sdarrenrstatic void showipstates __P((ips_stat_t *)); 139145510Sdarrenrstatic void showauthstates __P((fr_authstat_t *)); 140145510Sdarrenrstatic void showgroups __P((friostat_t *)); 141145510Sdarrenrstatic void usage __P((char *)); 142170268Sdarrenrstatic void showtqtable_live __P((int)); 143170268Sdarrenrstatic void printlivelist __P((int, int, frentry_t *, char *, char *)); 144170268Sdarrenrstatic void printdeadlist __P((int, int, frentry_t *, char *, char *)); 145145510Sdarrenrstatic void parse_ipportstr __P((const char *, i6addr_t *, int *)); 146145510Sdarrenrstatic void ipfstate_live __P((char *, friostat_t **, ips_stat_t **, 147145510Sdarrenr ipfrstat_t **, fr_authstat_t **, u_32_t *)); 148145510Sdarrenrstatic void ipfstate_dead __P((char *, friostat_t **, ips_stat_t **, 149145510Sdarrenr ipfrstat_t **, fr_authstat_t **, u_32_t *)); 150170268Sdarrenrstatic ipstate_t *fetchstate __P((ipstate_t *, ipstate_t *)); 151145510Sdarrenr#ifdef STATETOP 152145510Sdarrenrstatic void topipstates __P((i6addr_t, i6addr_t, int, int, int, 153145510Sdarrenr int, int, int)); 154145510Sdarrenrstatic void sig_break __P((int)); 155145510Sdarrenrstatic void sig_resize __P((int)); 156145510Sdarrenrstatic char *getip __P((int, i6addr_t *)); 157145510Sdarrenrstatic char *ttl_to_string __P((long)); 158145510Sdarrenrstatic int sort_p __P((const void *, const void *)); 159145510Sdarrenrstatic int sort_pkts __P((const void *, const void *)); 160145510Sdarrenrstatic int sort_bytes __P((const void *, const void *)); 161145510Sdarrenrstatic int sort_ttl __P((const void *, const void *)); 162145510Sdarrenrstatic int sort_srcip __P((const void *, const void *)); 163145510Sdarrenrstatic int sort_srcpt __P((const void *, const void *)); 164145510Sdarrenrstatic int sort_dstip __P((const void *, const void *)); 165145510Sdarrenrstatic int sort_dstpt __P((const void *, const void *)); 166145510Sdarrenr#endif 167145510Sdarrenr 168145510Sdarrenr 169145510Sdarrenrstatic void usage(name) 170145510Sdarrenrchar *name; 171145510Sdarrenr{ 172145510Sdarrenr#ifdef USE_INET6 173145510Sdarrenr fprintf(stderr, "Usage: %s [-6aAdfghIilnoRsv]\n", name); 174145510Sdarrenr#else 175145510Sdarrenr fprintf(stderr, "Usage: %s [-aAdfghIilnoRsv]\n", name); 176145510Sdarrenr#endif 177145510Sdarrenr fprintf(stderr, " %s [-M corefile] [-N symbol-list]\n", name); 178145510Sdarrenr#ifdef USE_INET6 179145510Sdarrenr fprintf(stderr, " %s -t [-6C] ", name); 180145510Sdarrenr#else 181145510Sdarrenr fprintf(stderr, " %s -t [-C] ", name); 182145510Sdarrenr#endif 183145510Sdarrenr fprintf(stderr, "[-D destination address] [-P protocol] [-S source address] [-T refresh time]\n"); 184145510Sdarrenr exit(1); 185145510Sdarrenr} 186145510Sdarrenr 187145510Sdarrenr 188145510Sdarrenrint main(argc,argv) 189145510Sdarrenrint argc; 190145510Sdarrenrchar *argv[]; 191145510Sdarrenr{ 192145510Sdarrenr fr_authstat_t frauthst; 193145510Sdarrenr fr_authstat_t *frauthstp = &frauthst; 194145510Sdarrenr friostat_t fio; 195145510Sdarrenr friostat_t *fiop = &fio; 196145510Sdarrenr ips_stat_t ipsst; 197145510Sdarrenr ips_stat_t *ipsstp = &ipsst; 198145510Sdarrenr ipfrstat_t ifrst; 199145510Sdarrenr ipfrstat_t *ifrstp = &ifrst; 200170268Sdarrenr char *memf = NULL; 201145510Sdarrenr char *options, *kern = NULL; 202145510Sdarrenr int c, myoptind; 203145510Sdarrenr 204145510Sdarrenr int protocol = -1; /* -1 = wild card for any protocol */ 205145510Sdarrenr int refreshtime = 1; /* default update time */ 206145510Sdarrenr int sport = -1; /* -1 = wild card for any source port */ 207145510Sdarrenr int dport = -1; /* -1 = wild card for any dest port */ 208145510Sdarrenr int topclosed = 0; /* do not show closed tcp sessions */ 209145510Sdarrenr i6addr_t saddr, daddr; 210145510Sdarrenr u_32_t frf; 211145510Sdarrenr 212145510Sdarrenr#ifdef USE_INET6 213145510Sdarrenr options = "6aACdfghIilnostvD:M:N:P:RS:T:"; 214145510Sdarrenr#else 215145510Sdarrenr options = "aACdfghIilnostvD:M:N:P:RS:T:"; 216145510Sdarrenr#endif 217145510Sdarrenr 218145510Sdarrenr saddr.in4.s_addr = INADDR_ANY; /* default any v4 source addr */ 219145510Sdarrenr daddr.in4.s_addr = INADDR_ANY; /* default any v4 dest addr */ 220145510Sdarrenr#ifdef USE_INET6 221145510Sdarrenr saddr.in6 = in6addr_any; /* default any v6 source addr */ 222145510Sdarrenr daddr.in6 = in6addr_any; /* default any v6 dest addr */ 223145510Sdarrenr#endif 224145510Sdarrenr 225145510Sdarrenr /* Don't warn about invalid flags when we run getopt for the 1st time */ 226145510Sdarrenr opterr = 0; 227145510Sdarrenr 228145510Sdarrenr /* 229145510Sdarrenr * Parse these two arguments now lest there be any buffer overflows 230145510Sdarrenr * in the parsing of the rest. 231145510Sdarrenr */ 232145510Sdarrenr myoptind = optind; 233145510Sdarrenr while ((c = getopt(argc, argv, options)) != -1) { 234145510Sdarrenr switch (c) 235145510Sdarrenr { 236145510Sdarrenr case 'M' : 237145510Sdarrenr memf = optarg; 238145510Sdarrenr live_kernel = 0; 239145510Sdarrenr break; 240145510Sdarrenr case 'N' : 241145510Sdarrenr kern = optarg; 242145510Sdarrenr live_kernel = 0; 243145510Sdarrenr break; 244145510Sdarrenr } 245145510Sdarrenr } 246145510Sdarrenr optind = myoptind; 247145510Sdarrenr 248145510Sdarrenr if (live_kernel == 1) { 249145510Sdarrenr if ((state_fd = open(IPSTATE_NAME, O_RDONLY)) == -1) { 250145510Sdarrenr perror("open(IPSTATE_NAME)"); 251145510Sdarrenr exit(-1); 252145510Sdarrenr } 253170268Sdarrenr if ((auth_fd = open(IPAUTH_NAME, O_RDONLY)) == -1) { 254170268Sdarrenr perror("open(IPAUTH_NAME)"); 255170268Sdarrenr exit(-1); 256170268Sdarrenr } 257170268Sdarrenr if ((nat_fd = open(IPNAT_NAME, O_RDONLY)) == -1) { 258170268Sdarrenr perror("open(IPAUTH_NAME)"); 259170268Sdarrenr exit(-1); 260170268Sdarrenr } 261170268Sdarrenr if ((ipf_fd = open(IPL_NAME, O_RDONLY)) == -1) { 262170268Sdarrenr fprintf(stderr, "open(%s)", IPL_NAME); 263145510Sdarrenr perror(""); 264145510Sdarrenr exit(-1); 265145510Sdarrenr } 266145510Sdarrenr } 267145510Sdarrenr 268145510Sdarrenr if (kern != NULL || memf != NULL) { 269145510Sdarrenr (void)setgid(getgid()); 270145510Sdarrenr (void)setuid(getuid()); 271145510Sdarrenr } 272145510Sdarrenr 273170268Sdarrenr if (live_kernel == 1) { 274170268Sdarrenr (void) checkrev(IPL_NAME); 275170268Sdarrenr } else { 276170268Sdarrenr if (openkmem(kern, memf) == -1) 277170268Sdarrenr exit(-1); 278170268Sdarrenr } 279145510Sdarrenr 280145510Sdarrenr (void)setgid(getgid()); 281145510Sdarrenr (void)setuid(getuid()); 282145510Sdarrenr 283145510Sdarrenr opterr = 1; 284145510Sdarrenr 285145510Sdarrenr while ((c = getopt(argc, argv, options)) != -1) 286145510Sdarrenr { 287145510Sdarrenr switch (c) 288145510Sdarrenr { 289145510Sdarrenr#ifdef USE_INET6 290145510Sdarrenr case '6' : 291145510Sdarrenr use_inet6 = 1; 292145510Sdarrenr break; 293145510Sdarrenr#endif 294145510Sdarrenr case 'a' : 295145510Sdarrenr opts |= OPT_ACCNT|OPT_SHOWLIST; 296145510Sdarrenr break; 297145510Sdarrenr case 'A' : 298145510Sdarrenr opts |= OPT_AUTHSTATS; 299145510Sdarrenr break; 300145510Sdarrenr case 'C' : 301145510Sdarrenr topclosed = 1; 302145510Sdarrenr break; 303145510Sdarrenr case 'd' : 304145510Sdarrenr opts |= OPT_DEBUG; 305145510Sdarrenr break; 306145510Sdarrenr case 'D' : 307145510Sdarrenr parse_ipportstr(optarg, &daddr, &dport); 308145510Sdarrenr break; 309145510Sdarrenr case 'f' : 310145510Sdarrenr opts |= OPT_FRSTATES; 311145510Sdarrenr break; 312145510Sdarrenr case 'g' : 313145510Sdarrenr opts |= OPT_GROUPS; 314145510Sdarrenr break; 315145510Sdarrenr case 'h' : 316145510Sdarrenr opts |= OPT_HITS; 317145510Sdarrenr break; 318145510Sdarrenr case 'i' : 319145510Sdarrenr opts |= OPT_INQUE|OPT_SHOWLIST; 320145510Sdarrenr break; 321145510Sdarrenr case 'I' : 322145510Sdarrenr opts |= OPT_INACTIVE; 323145510Sdarrenr break; 324145510Sdarrenr case 'l' : 325145510Sdarrenr opts |= OPT_SHOWLIST; 326145510Sdarrenr break; 327145510Sdarrenr case 'M' : 328145510Sdarrenr break; 329145510Sdarrenr case 'N' : 330145510Sdarrenr break; 331145510Sdarrenr case 'n' : 332145510Sdarrenr opts |= OPT_SHOWLINENO; 333145510Sdarrenr break; 334145510Sdarrenr case 'o' : 335145510Sdarrenr opts |= OPT_OUTQUE|OPT_SHOWLIST; 336145510Sdarrenr break; 337145510Sdarrenr case 'P' : 338145510Sdarrenr protocol = getproto(optarg); 339145510Sdarrenr if (protocol == -1) { 340145510Sdarrenr fprintf(stderr, "%s: Invalid protocol: %s\n", 341145510Sdarrenr argv[0], optarg); 342145510Sdarrenr exit(-2); 343145510Sdarrenr } 344145510Sdarrenr break; 345145510Sdarrenr case 'R' : 346145510Sdarrenr opts |= OPT_NORESOLVE; 347145510Sdarrenr break; 348145510Sdarrenr case 's' : 349145510Sdarrenr opts |= OPT_IPSTATES; 350145510Sdarrenr break; 351145510Sdarrenr case 'S' : 352145510Sdarrenr parse_ipportstr(optarg, &saddr, &sport); 353145510Sdarrenr break; 354145510Sdarrenr case 't' : 355145510Sdarrenr#ifdef STATETOP 356145510Sdarrenr opts |= OPT_STATETOP; 357145510Sdarrenr break; 358145510Sdarrenr#else 359145510Sdarrenr fprintf(stderr, 360145510Sdarrenr "%s: state top facility not compiled in\n", 361145510Sdarrenr argv[0]); 362145510Sdarrenr exit(-2); 363145510Sdarrenr#endif 364145510Sdarrenr case 'T' : 365145510Sdarrenr if (!sscanf(optarg, "%d", &refreshtime) || 366145510Sdarrenr (refreshtime <= 0)) { 367145510Sdarrenr fprintf(stderr, 368145510Sdarrenr "%s: Invalid refreshtime < 1 : %s\n", 369145510Sdarrenr argv[0], optarg); 370145510Sdarrenr exit(-2); 371145510Sdarrenr } 372145510Sdarrenr break; 373145510Sdarrenr case 'v' : 374145510Sdarrenr opts |= OPT_VERBOSE; 375145510Sdarrenr break; 376145510Sdarrenr default : 377145510Sdarrenr usage(argv[0]); 378145510Sdarrenr break; 379145510Sdarrenr } 380145510Sdarrenr } 381145510Sdarrenr 382145510Sdarrenr if (live_kernel == 1) { 383145510Sdarrenr bzero((char *)&fio, sizeof(fio)); 384145510Sdarrenr bzero((char *)&ipsst, sizeof(ipsst)); 385145510Sdarrenr bzero((char *)&ifrst, sizeof(ifrst)); 386145510Sdarrenr 387170268Sdarrenr ipfstate_live(IPL_NAME, &fiop, &ipsstp, &ifrstp, 388145510Sdarrenr &frauthstp, &frf); 389145510Sdarrenr } else 390145510Sdarrenr ipfstate_dead(kern, &fiop, &ipsstp, &ifrstp, &frauthstp, &frf); 391145510Sdarrenr 392145510Sdarrenr if (opts & OPT_IPSTATES) { 393145510Sdarrenr showipstates(ipsstp); 394145510Sdarrenr } else if (opts & OPT_SHOWLIST) { 395145510Sdarrenr showlist(fiop); 396145510Sdarrenr if ((opts & OPT_OUTQUE) && (opts & OPT_INQUE)){ 397145510Sdarrenr opts &= ~OPT_OUTQUE; 398145510Sdarrenr showlist(fiop); 399145510Sdarrenr } 400145510Sdarrenr } else if (opts & OPT_FRSTATES) 401170268Sdarrenr showfrstates(ifrstp, fiop->f_ticks); 402145510Sdarrenr#ifdef STATETOP 403145510Sdarrenr else if (opts & OPT_STATETOP) 404145510Sdarrenr topipstates(saddr, daddr, sport, dport, protocol, 405145510Sdarrenr use_inet6 ? 6 : 4, refreshtime, topclosed); 406145510Sdarrenr#endif 407145510Sdarrenr else if (opts & OPT_AUTHSTATS) 408145510Sdarrenr showauthstates(frauthstp); 409145510Sdarrenr else if (opts & OPT_GROUPS) 410145510Sdarrenr showgroups(fiop); 411145510Sdarrenr else 412145510Sdarrenr showstats(fiop, frf); 413145510Sdarrenr 414145510Sdarrenr return 0; 415145510Sdarrenr} 416145510Sdarrenr 417145510Sdarrenr 418145510Sdarrenr/* 419145510Sdarrenr * Fill in the stats structures from the live kernel, using a combination 420145510Sdarrenr * of ioctl's and copying directly from kernel memory. 421145510Sdarrenr */ 422145510Sdarrenrstatic void ipfstate_live(device, fiopp, ipsstpp, ifrstpp, frauthstpp, frfp) 423145510Sdarrenrchar *device; 424145510Sdarrenrfriostat_t **fiopp; 425145510Sdarrenrips_stat_t **ipsstpp; 426145510Sdarrenripfrstat_t **ifrstpp; 427145510Sdarrenrfr_authstat_t **frauthstpp; 428145510Sdarrenru_32_t *frfp; 429145510Sdarrenr{ 430145510Sdarrenr ipfobj_t ipfo; 431145510Sdarrenr 432145510Sdarrenr if (checkrev(device) == -1) { 433145510Sdarrenr fprintf(stderr, "User/kernel version check failed\n"); 434145510Sdarrenr exit(1); 435145510Sdarrenr } 436145510Sdarrenr 437145510Sdarrenr if ((opts & OPT_AUTHSTATS) == 0) { 438145510Sdarrenr bzero((caddr_t)&ipfo, sizeof(ipfo)); 439145510Sdarrenr ipfo.ipfo_rev = IPFILTER_VERSION; 440170268Sdarrenr ipfo.ipfo_type = IPFOBJ_IPFSTAT; 441145510Sdarrenr ipfo.ipfo_size = sizeof(friostat_t); 442145510Sdarrenr ipfo.ipfo_ptr = (void *)*fiopp; 443145510Sdarrenr 444145510Sdarrenr if (ioctl(ipf_fd, SIOCGETFS, &ipfo) == -1) { 445145510Sdarrenr perror("ioctl(ipf:SIOCGETFS)"); 446145510Sdarrenr exit(-1); 447145510Sdarrenr } 448145510Sdarrenr 449145510Sdarrenr if (ioctl(ipf_fd, SIOCGETFF, frfp) == -1) 450145510Sdarrenr perror("ioctl(SIOCGETFF)"); 451145510Sdarrenr } 452145510Sdarrenr 453145510Sdarrenr if ((opts & OPT_IPSTATES) != 0) { 454145510Sdarrenr 455145510Sdarrenr bzero((caddr_t)&ipfo, sizeof(ipfo)); 456145510Sdarrenr ipfo.ipfo_rev = IPFILTER_VERSION; 457170268Sdarrenr ipfo.ipfo_type = IPFOBJ_STATESTAT; 458145510Sdarrenr ipfo.ipfo_size = sizeof(ips_stat_t); 459145510Sdarrenr ipfo.ipfo_ptr = (void *)*ipsstpp; 460145510Sdarrenr 461145510Sdarrenr if ((ioctl(state_fd, SIOCGETFS, &ipfo) == -1)) { 462145510Sdarrenr perror("ioctl(state:SIOCGETFS)"); 463145510Sdarrenr exit(-1); 464145510Sdarrenr } 465145510Sdarrenr if (ioctl(state_fd, SIOCGETLG, &state_logging) == -1) { 466145510Sdarrenr perror("ioctl(state:SIOCGETLG)"); 467145510Sdarrenr exit(-1); 468145510Sdarrenr } 469145510Sdarrenr } 470145510Sdarrenr 471145510Sdarrenr if ((opts & OPT_FRSTATES) != 0) { 472145510Sdarrenr bzero((caddr_t)&ipfo, sizeof(ipfo)); 473145510Sdarrenr ipfo.ipfo_rev = IPFILTER_VERSION; 474170268Sdarrenr ipfo.ipfo_type = IPFOBJ_FRAGSTAT; 475145510Sdarrenr ipfo.ipfo_size = sizeof(ipfrstat_t); 476145510Sdarrenr ipfo.ipfo_ptr = (void *)*ifrstpp; 477145510Sdarrenr 478145510Sdarrenr if (ioctl(ipf_fd, SIOCGFRST, &ipfo) == -1) { 479145510Sdarrenr perror("ioctl(SIOCGFRST)"); 480145510Sdarrenr exit(-1); 481145510Sdarrenr } 482145510Sdarrenr } 483145510Sdarrenr 484170268Sdarrenr if (opts & OPT_DEBUG) 485145510Sdarrenr PRINTF("opts %#x name %s\n", opts, device); 486145510Sdarrenr 487145510Sdarrenr if ((opts & OPT_AUTHSTATS) != 0) { 488145510Sdarrenr bzero((caddr_t)&ipfo, sizeof(ipfo)); 489145510Sdarrenr ipfo.ipfo_rev = IPFILTER_VERSION; 490170268Sdarrenr ipfo.ipfo_type = IPFOBJ_AUTHSTAT; 491145510Sdarrenr ipfo.ipfo_size = sizeof(fr_authstat_t); 492145510Sdarrenr ipfo.ipfo_ptr = (void *)*frauthstpp; 493145510Sdarrenr 494170268Sdarrenr if (ioctl(auth_fd, SIOCATHST, &ipfo) == -1) { 495145510Sdarrenr perror("ioctl(SIOCATHST)"); 496145510Sdarrenr exit(-1); 497145510Sdarrenr } 498145510Sdarrenr } 499145510Sdarrenr} 500145510Sdarrenr 501145510Sdarrenr 502145510Sdarrenr/* 503145510Sdarrenr * Build up the stats structures from data held in the "core" memory. 504145510Sdarrenr * This is mainly useful when looking at data in crash dumps and ioctl's 505145510Sdarrenr * just won't work any more. 506145510Sdarrenr */ 507145510Sdarrenrstatic void ipfstate_dead(kernel, fiopp, ipsstpp, ifrstpp, frauthstpp, frfp) 508145510Sdarrenrchar *kernel; 509145510Sdarrenrfriostat_t **fiopp; 510145510Sdarrenrips_stat_t **ipsstpp; 511145510Sdarrenripfrstat_t **ifrstpp; 512145510Sdarrenrfr_authstat_t **frauthstpp; 513145510Sdarrenru_32_t *frfp; 514145510Sdarrenr{ 515145510Sdarrenr static fr_authstat_t frauthst, *frauthstp; 516145510Sdarrenr static ips_stat_t ipsst, *ipsstp; 517145510Sdarrenr static ipfrstat_t ifrst, *ifrstp; 518145510Sdarrenr static friostat_t fio, *fiop; 519170268Sdarrenr static ipftq_t ipssttab[IPF_TCP_NSTATES]; 520145510Sdarrenr int temp; 521145510Sdarrenr 522145510Sdarrenr void *rules[2][2]; 523170268Sdarrenr struct nlist deadlist[44] = { 524145510Sdarrenr { "fr_authstats" }, /* 0 */ 525145510Sdarrenr { "fae_list" }, 526145510Sdarrenr { "ipauth" }, 527145510Sdarrenr { "fr_authlist" }, 528145510Sdarrenr { "fr_authstart" }, 529145510Sdarrenr { "fr_authend" }, /* 5 */ 530145510Sdarrenr { "fr_authnext" }, 531145510Sdarrenr { "fr_auth" }, 532145510Sdarrenr { "fr_authused" }, 533145510Sdarrenr { "fr_authsize" }, 534145510Sdarrenr { "fr_defaultauthage" }, /* 10 */ 535145510Sdarrenr { "fr_authpkts" }, 536145510Sdarrenr { "fr_auth_lock" }, 537145510Sdarrenr { "frstats" }, 538145510Sdarrenr { "ips_stats" }, 539145510Sdarrenr { "ips_num" }, /* 15 */ 540145510Sdarrenr { "ips_wild" }, 541145510Sdarrenr { "ips_list" }, 542145510Sdarrenr { "ips_table" }, 543145510Sdarrenr { "fr_statemax" }, 544145510Sdarrenr { "fr_statesize" }, /* 20 */ 545145510Sdarrenr { "fr_state_doflush" }, 546145510Sdarrenr { "fr_state_lock" }, 547145510Sdarrenr { "ipfr_heads" }, 548145510Sdarrenr { "ipfr_nattab" }, 549145510Sdarrenr { "ipfr_stats" }, /* 25 */ 550145510Sdarrenr { "ipfr_inuse" }, 551145510Sdarrenr { "fr_ipfrttl" }, 552145510Sdarrenr { "fr_frag_lock" }, 553145510Sdarrenr { "ipfr_timer_id" }, 554145510Sdarrenr { "fr_nat_lock" }, /* 30 */ 555145510Sdarrenr { "ipfilter" }, 556145510Sdarrenr { "ipfilter6" }, 557145510Sdarrenr { "ipacct" }, 558145510Sdarrenr { "ipacct6" }, 559145510Sdarrenr { "ipl_frouteok" }, /* 35 */ 560145510Sdarrenr { "fr_running" }, 561145510Sdarrenr { "ipfgroups" }, 562145510Sdarrenr { "fr_active" }, 563145510Sdarrenr { "fr_pass" }, 564145510Sdarrenr { "fr_flags" }, /* 40 */ 565145510Sdarrenr { "ipstate_logging" }, 566170268Sdarrenr { "ips_tqtqb" }, 567145510Sdarrenr { NULL } 568145510Sdarrenr }; 569145510Sdarrenr 570145510Sdarrenr 571145510Sdarrenr frauthstp = &frauthst; 572145510Sdarrenr ipsstp = &ipsst; 573145510Sdarrenr ifrstp = &ifrst; 574145510Sdarrenr fiop = &fio; 575145510Sdarrenr 576145510Sdarrenr *frfp = 0; 577145510Sdarrenr *fiopp = fiop; 578145510Sdarrenr *ipsstpp = ipsstp; 579145510Sdarrenr *ifrstpp = ifrstp; 580145510Sdarrenr *frauthstpp = frauthstp; 581145510Sdarrenr 582145510Sdarrenr bzero((char *)fiop, sizeof(*fiop)); 583145510Sdarrenr bzero((char *)ipsstp, sizeof(*ipsstp)); 584145510Sdarrenr bzero((char *)ifrstp, sizeof(*ifrstp)); 585145510Sdarrenr bzero((char *)frauthstp, sizeof(*frauthstp)); 586145510Sdarrenr 587145510Sdarrenr if (nlist(kernel, deadlist) == -1) { 588145510Sdarrenr fprintf(stderr, "nlist error\n"); 589145510Sdarrenr return; 590145510Sdarrenr } 591145510Sdarrenr 592145510Sdarrenr /* 593145510Sdarrenr * This is for SIOCGETFF. 594145510Sdarrenr */ 595145510Sdarrenr kmemcpy((char *)frfp, (u_long)deadlist[40].n_value, sizeof(*frfp)); 596145510Sdarrenr 597145510Sdarrenr /* 598145510Sdarrenr * f_locks is a combination of the lock variable from each part of 599145510Sdarrenr * ipfilter (state, auth, nat, fragments). 600145510Sdarrenr */ 601145510Sdarrenr kmemcpy((char *)fiop, (u_long)deadlist[13].n_value, sizeof(*fiop)); 602145510Sdarrenr kmemcpy((char *)&fiop->f_locks[0], (u_long)deadlist[22].n_value, 603145510Sdarrenr sizeof(fiop->f_locks[0])); 604145510Sdarrenr kmemcpy((char *)&fiop->f_locks[0], (u_long)deadlist[30].n_value, 605145510Sdarrenr sizeof(fiop->f_locks[1])); 606145510Sdarrenr kmemcpy((char *)&fiop->f_locks[2], (u_long)deadlist[28].n_value, 607145510Sdarrenr sizeof(fiop->f_locks[2])); 608145510Sdarrenr kmemcpy((char *)&fiop->f_locks[3], (u_long)deadlist[12].n_value, 609145510Sdarrenr sizeof(fiop->f_locks[3])); 610145510Sdarrenr 611145510Sdarrenr /* 612145510Sdarrenr * Get pointers to each list of rules (active, inactive, in, out) 613145510Sdarrenr */ 614145510Sdarrenr kmemcpy((char *)&rules, (u_long)deadlist[31].n_value, sizeof(rules)); 615145510Sdarrenr fiop->f_fin[0] = rules[0][0]; 616145510Sdarrenr fiop->f_fin[1] = rules[0][1]; 617145510Sdarrenr fiop->f_fout[0] = rules[1][0]; 618145510Sdarrenr fiop->f_fout[1] = rules[1][1]; 619145510Sdarrenr 620145510Sdarrenr /* 621145510Sdarrenr * Same for IPv6, except make them null if support for it is not 622145510Sdarrenr * being compiled in. 623145510Sdarrenr */ 624145510Sdarrenr#ifdef USE_INET6 625145510Sdarrenr kmemcpy((char *)&rules, (u_long)deadlist[32].n_value, sizeof(rules)); 626145510Sdarrenr fiop->f_fin6[0] = rules[0][0]; 627145510Sdarrenr fiop->f_fin6[1] = rules[0][1]; 628145510Sdarrenr fiop->f_fout6[0] = rules[1][0]; 629145510Sdarrenr fiop->f_fout6[1] = rules[1][1]; 630145510Sdarrenr#else 631145510Sdarrenr fiop->f_fin6[0] = NULL; 632145510Sdarrenr fiop->f_fin6[1] = NULL; 633145510Sdarrenr fiop->f_fout6[0] = NULL; 634145510Sdarrenr fiop->f_fout6[1] = NULL; 635145510Sdarrenr#endif 636145510Sdarrenr 637145510Sdarrenr /* 638145510Sdarrenr * Now get accounting rules pointers. 639145510Sdarrenr */ 640145510Sdarrenr kmemcpy((char *)&rules, (u_long)deadlist[33].n_value, sizeof(rules)); 641145510Sdarrenr fiop->f_acctin[0] = rules[0][0]; 642145510Sdarrenr fiop->f_acctin[1] = rules[0][1]; 643145510Sdarrenr fiop->f_acctout[0] = rules[1][0]; 644145510Sdarrenr fiop->f_acctout[1] = rules[1][1]; 645145510Sdarrenr 646145510Sdarrenr#ifdef USE_INET6 647145510Sdarrenr kmemcpy((char *)&rules, (u_long)deadlist[34].n_value, sizeof(rules)); 648145510Sdarrenr fiop->f_acctin6[0] = rules[0][0]; 649145510Sdarrenr fiop->f_acctin6[1] = rules[0][1]; 650145510Sdarrenr fiop->f_acctout6[0] = rules[1][0]; 651145510Sdarrenr fiop->f_acctout6[1] = rules[1][1]; 652145510Sdarrenr#else 653145510Sdarrenr fiop->f_acctin6[0] = NULL; 654145510Sdarrenr fiop->f_acctin6[1] = NULL; 655145510Sdarrenr fiop->f_acctout6[0] = NULL; 656145510Sdarrenr fiop->f_acctout6[1] = NULL; 657145510Sdarrenr#endif 658145510Sdarrenr 659145510Sdarrenr /* 660145510Sdarrenr * A collection of "global" variables used inside the kernel which 661145510Sdarrenr * are all collected in friostat_t via ioctl. 662145510Sdarrenr */ 663145510Sdarrenr kmemcpy((char *)&fiop->f_froute, (u_long)deadlist[35].n_value, 664145510Sdarrenr sizeof(fiop->f_froute)); 665145510Sdarrenr kmemcpy((char *)&fiop->f_running, (u_long)deadlist[36].n_value, 666145510Sdarrenr sizeof(fiop->f_running)); 667145510Sdarrenr kmemcpy((char *)&fiop->f_groups, (u_long)deadlist[37].n_value, 668145510Sdarrenr sizeof(fiop->f_groups)); 669145510Sdarrenr kmemcpy((char *)&fiop->f_active, (u_long)deadlist[38].n_value, 670145510Sdarrenr sizeof(fiop->f_active)); 671145510Sdarrenr kmemcpy((char *)&fiop->f_defpass, (u_long)deadlist[39].n_value, 672145510Sdarrenr sizeof(fiop->f_defpass)); 673145510Sdarrenr 674145510Sdarrenr /* 675145510Sdarrenr * Build up the state information stats structure. 676145510Sdarrenr */ 677145510Sdarrenr kmemcpy((char *)ipsstp, (u_long)deadlist[14].n_value, sizeof(*ipsstp)); 678145510Sdarrenr kmemcpy((char *)&temp, (u_long)deadlist[15].n_value, sizeof(temp)); 679170268Sdarrenr kmemcpy((char *)ipssttab, (u_long)deadlist[42].n_value, 680170268Sdarrenr sizeof(ipssttab)); 681145510Sdarrenr ipsstp->iss_active = temp; 682145510Sdarrenr ipsstp->iss_table = (void *)deadlist[18].n_value; 683145510Sdarrenr ipsstp->iss_list = (void *)deadlist[17].n_value; 684170268Sdarrenr ipsstp->iss_tcptab = ipssttab; 685145510Sdarrenr 686145510Sdarrenr /* 687145510Sdarrenr * Build up the authentiation information stats structure. 688145510Sdarrenr */ 689145510Sdarrenr kmemcpy((char *)frauthstp, (u_long)deadlist[0].n_value, 690145510Sdarrenr sizeof(*frauthstp)); 691145510Sdarrenr frauthstp->fas_faelist = (void *)deadlist[1].n_value; 692145510Sdarrenr 693145510Sdarrenr /* 694145510Sdarrenr * Build up the fragment information stats structure. 695145510Sdarrenr */ 696145510Sdarrenr kmemcpy((char *)ifrstp, (u_long)deadlist[25].n_value, 697145510Sdarrenr sizeof(*ifrstp)); 698145510Sdarrenr ifrstp->ifs_table = (void *)deadlist[23].n_value; 699145510Sdarrenr ifrstp->ifs_nattab = (void *)deadlist[24].n_value; 700145510Sdarrenr kmemcpy((char *)&ifrstp->ifs_inuse, (u_long)deadlist[26].n_value, 701145510Sdarrenr sizeof(ifrstp->ifs_inuse)); 702145510Sdarrenr 703145510Sdarrenr /* 704145510Sdarrenr * Get logging on/off switches 705145510Sdarrenr */ 706145510Sdarrenr kmemcpy((char *)&state_logging, (u_long)deadlist[41].n_value, 707145510Sdarrenr sizeof(state_logging)); 708145510Sdarrenr} 709145510Sdarrenr 710145510Sdarrenr 711145510Sdarrenr/* 712145510Sdarrenr * Display the kernel stats for packets blocked and passed and other 713145510Sdarrenr * associated running totals which are kept. 714145510Sdarrenr */ 715145510Sdarrenrstatic void showstats(fp, frf) 716145510Sdarrenrstruct friostat *fp; 717145510Sdarrenru_32_t frf; 718145510Sdarrenr{ 719145510Sdarrenr 720145510Sdarrenr PRINTF("bad packets:\t\tin %lu\tout %lu\n", 721145510Sdarrenr fp->f_st[0].fr_bad, fp->f_st[1].fr_bad); 722145510Sdarrenr#ifdef USE_INET6 723145510Sdarrenr PRINTF(" IPv6 packets:\t\tin %lu out %lu\n", 724145510Sdarrenr fp->f_st[0].fr_ipv6, fp->f_st[1].fr_ipv6); 725145510Sdarrenr#endif 726145510Sdarrenr PRINTF(" input packets:\t\tblocked %lu passed %lu nomatch %lu", 727145510Sdarrenr fp->f_st[0].fr_block, fp->f_st[0].fr_pass, 728145510Sdarrenr fp->f_st[0].fr_nom); 729145510Sdarrenr PRINTF(" counted %lu short %lu\n", 730145510Sdarrenr fp->f_st[0].fr_acct, fp->f_st[0].fr_short); 731145510Sdarrenr PRINTF("output packets:\t\tblocked %lu passed %lu nomatch %lu", 732145510Sdarrenr fp->f_st[1].fr_block, fp->f_st[1].fr_pass, 733145510Sdarrenr fp->f_st[1].fr_nom); 734145510Sdarrenr PRINTF(" counted %lu short %lu\n", 735145510Sdarrenr fp->f_st[1].fr_acct, fp->f_st[1].fr_short); 736145510Sdarrenr PRINTF(" input packets logged:\tblocked %lu passed %lu\n", 737145510Sdarrenr fp->f_st[0].fr_bpkl, fp->f_st[0].fr_ppkl); 738145510Sdarrenr PRINTF("output packets logged:\tblocked %lu passed %lu\n", 739145510Sdarrenr fp->f_st[1].fr_bpkl, fp->f_st[1].fr_ppkl); 740145510Sdarrenr PRINTF(" packets logged:\tinput %lu output %lu\n", 741145510Sdarrenr fp->f_st[0].fr_pkl, fp->f_st[1].fr_pkl); 742145510Sdarrenr PRINTF(" log failures:\t\tinput %lu output %lu\n", 743145510Sdarrenr fp->f_st[0].fr_skip, fp->f_st[1].fr_skip); 744145510Sdarrenr PRINTF("fragment state(in):\tkept %lu\tlost %lu\tnot fragmented %lu\n", 745145510Sdarrenr fp->f_st[0].fr_nfr, fp->f_st[0].fr_bnfr, 746145510Sdarrenr fp->f_st[0].fr_cfr); 747145510Sdarrenr PRINTF("fragment state(out):\tkept %lu\tlost %lu\tnot fragmented %lu\n", 748145510Sdarrenr fp->f_st[1].fr_nfr, fp->f_st[1].fr_bnfr, 749145510Sdarrenr fp->f_st[0].fr_cfr); 750145510Sdarrenr PRINTF("packet state(in):\tkept %lu\tlost %lu\n", 751145510Sdarrenr fp->f_st[0].fr_ads, fp->f_st[0].fr_bads); 752145510Sdarrenr PRINTF("packet state(out):\tkept %lu\tlost %lu\n", 753145510Sdarrenr fp->f_st[1].fr_ads, fp->f_st[1].fr_bads); 754145510Sdarrenr PRINTF("ICMP replies:\t%lu\tTCP RSTs sent:\t%lu\n", 755145510Sdarrenr fp->f_st[0].fr_ret, fp->f_st[1].fr_ret); 756145510Sdarrenr PRINTF("Invalid source(in):\t%lu\n", fp->f_st[0].fr_badsrc); 757145510Sdarrenr PRINTF("Result cache hits(in):\t%lu\t(out):\t%lu\n", 758145510Sdarrenr fp->f_st[0].fr_chit, fp->f_st[1].fr_chit); 759145510Sdarrenr PRINTF("IN Pullups succeeded:\t%lu\tfailed:\t%lu\n", 760145510Sdarrenr fp->f_st[0].fr_pull[0], fp->f_st[0].fr_pull[1]); 761145510Sdarrenr PRINTF("OUT Pullups succeeded:\t%lu\tfailed:\t%lu\n", 762145510Sdarrenr fp->f_st[1].fr_pull[0], fp->f_st[1].fr_pull[1]); 763145510Sdarrenr PRINTF("Fastroute successes:\t%lu\tfailures:\t%lu\n", 764145510Sdarrenr fp->f_froute[0], fp->f_froute[1]); 765145510Sdarrenr PRINTF("TCP cksum fails(in):\t%lu\t(out):\t%lu\n", 766145510Sdarrenr fp->f_st[0].fr_tcpbad, fp->f_st[1].fr_tcpbad); 767145510Sdarrenr PRINTF("IPF Ticks:\t%lu\n", fp->f_ticks); 768145510Sdarrenr 769145510Sdarrenr PRINTF("Packet log flags set: (%#x)\n", frf); 770145510Sdarrenr if (frf & FF_LOGPASS) 771145510Sdarrenr PRINTF("\tpackets passed through filter\n"); 772145510Sdarrenr if (frf & FF_LOGBLOCK) 773145510Sdarrenr PRINTF("\tpackets blocked by filter\n"); 774145510Sdarrenr if (frf & FF_LOGNOMATCH) 775145510Sdarrenr PRINTF("\tpackets not matched by filter\n"); 776145510Sdarrenr if (!frf) 777145510Sdarrenr PRINTF("\tnone\n"); 778145510Sdarrenr} 779145510Sdarrenr 780145510Sdarrenr 781145510Sdarrenr/* 782145510Sdarrenr * Print out a list of rules from the kernel, starting at the one passed. 783145510Sdarrenr */ 784170268Sdarrenrstatic void printlivelist(out, set, fp, group, comment) 785170268Sdarrenrint out, set; 786145510Sdarrenrfrentry_t *fp; 787170268Sdarrenrchar *group, *comment; 788145510Sdarrenr{ 789170268Sdarrenr struct frentry fb; 790170268Sdarrenr ipfruleiter_t rule; 791170268Sdarrenr frentry_t zero; 792170268Sdarrenr frgroup_t *g; 793170268Sdarrenr ipfobj_t obj; 794170268Sdarrenr int n; 795145510Sdarrenr 796170268Sdarrenr if (use_inet6 == 1) 797170268Sdarrenr fb.fr_v = 6; 798170268Sdarrenr else 799170268Sdarrenr fb.fr_v = 4; 800170268Sdarrenr fb.fr_next = fp; 801170268Sdarrenr n = 0; 802170268Sdarrenr 803170268Sdarrenr rule.iri_inout = out; 804170268Sdarrenr rule.iri_active = set; 805170268Sdarrenr rule.iri_rule = &fb; 806170268Sdarrenr rule.iri_nrules = 1; 807170268Sdarrenr rule.iri_v = use_inet6 ? 6 : 4; 808170268Sdarrenr if (group != NULL) 809170268Sdarrenr strncpy(rule.iri_group, group, FR_GROUPLEN); 810170268Sdarrenr else 811170268Sdarrenr rule.iri_group[0] = '\0'; 812170268Sdarrenr 813170268Sdarrenr bzero((char *)&zero, sizeof(zero)); 814170268Sdarrenr 815170268Sdarrenr bzero((char *)&obj, sizeof(obj)); 816170268Sdarrenr obj.ipfo_rev = IPFILTER_VERSION; 817170268Sdarrenr obj.ipfo_type = IPFOBJ_IPFITER; 818170268Sdarrenr obj.ipfo_size = sizeof(rule); 819170268Sdarrenr obj.ipfo_ptr = &rule; 820170268Sdarrenr 821170268Sdarrenr do { 822170268Sdarrenr u_long array[1000]; 823170268Sdarrenr 824170268Sdarrenr memset(array, 0xff, sizeof(array)); 825170268Sdarrenr fp = (frentry_t *)array; 826170268Sdarrenr rule.iri_rule = fp; 827170268Sdarrenr if (ioctl(ipf_fd, SIOCIPFITER, &obj) == -1) { 828170268Sdarrenr perror("ioctl(SIOCIPFITER)"); 829170268Sdarrenr n = IPFGENITER_IPF; 830170268Sdarrenr ioctl(ipf_fd, SIOCIPFDELTOK, &n); 831145510Sdarrenr return; 832145510Sdarrenr } 833170268Sdarrenr if (bcmp(fp, &zero, sizeof(zero)) == 0) 834170268Sdarrenr break; 835170268Sdarrenr if (fp->fr_data != NULL) 836170268Sdarrenr fp->fr_data = (char *)fp + sizeof(*fp); 837170268Sdarrenr 838170268Sdarrenr n++; 839170268Sdarrenr 840145510Sdarrenr if (opts & (OPT_HITS|OPT_VERBOSE)) 841145510Sdarrenr#ifdef USE_QUAD_T 842145510Sdarrenr PRINTF("%qu ", (unsigned long long) fp->fr_hits); 843145510Sdarrenr#else 844145510Sdarrenr PRINTF("%lu ", fp->fr_hits); 845145510Sdarrenr#endif 846145510Sdarrenr if (opts & (OPT_ACCNT|OPT_VERBOSE)) 847145510Sdarrenr#ifdef USE_QUAD_T 848145510Sdarrenr PRINTF("%qu ", (unsigned long long) fp->fr_bytes); 849145510Sdarrenr#else 850145510Sdarrenr PRINTF("%lu ", fp->fr_bytes); 851145510Sdarrenr#endif 852145510Sdarrenr if (opts & OPT_SHOWLINENO) 853145510Sdarrenr PRINTF("@%d ", n); 854170268Sdarrenr 855170268Sdarrenr printfr(fp, ioctl); 856170268Sdarrenr if (opts & OPT_DEBUG) { 857170268Sdarrenr binprint(fp, sizeof(*fp)); 858170268Sdarrenr if (fp->fr_data != NULL && fp->fr_dsize > 0) 859170268Sdarrenr binprint(fp->fr_data, fp->fr_dsize); 860170268Sdarrenr } 861170268Sdarrenr if (fp->fr_grhead[0] != '\0') { 862170268Sdarrenr for (g = grtop; g != NULL; g = g->fg_next) { 863170268Sdarrenr if (!strncmp(fp->fr_grhead, g->fg_name, 864170268Sdarrenr FR_GROUPLEN)) 865170268Sdarrenr break; 866170268Sdarrenr } 867170268Sdarrenr if (g == NULL) { 868170268Sdarrenr g = calloc(1, sizeof(*g)); 869170268Sdarrenr 870170268Sdarrenr if (g != NULL) { 871170268Sdarrenr strncpy(g->fg_name, fp->fr_grhead, 872170268Sdarrenr FR_GROUPLEN); 873170268Sdarrenr if (grtop == NULL) { 874170268Sdarrenr grtop = g; 875170268Sdarrenr grtail = g; 876170268Sdarrenr } else { 877170268Sdarrenr grtail->fg_next = g; 878170268Sdarrenr grtail = g; 879170268Sdarrenr } 880170268Sdarrenr } 881170268Sdarrenr } 882170268Sdarrenr } 883170268Sdarrenr if (fp->fr_type == FR_T_CALLFUNC) { 884170268Sdarrenr printlivelist(out, set, fp->fr_data, group, 885170268Sdarrenr "# callfunc: "); 886170268Sdarrenr } 887170268Sdarrenr } while (fp->fr_next != NULL); 888170268Sdarrenr 889170268Sdarrenr n = IPFGENITER_IPF; 890170268Sdarrenr ioctl(ipf_fd, SIOCIPFDELTOK, &n); 891170268Sdarrenr 892170268Sdarrenr if (group == NULL) { 893170268Sdarrenr while ((g = grtop) != NULL) { 894170268Sdarrenr printf("# Group %s\n", g->fg_name); 895170268Sdarrenr printlivelist(out, set, NULL, g->fg_name, comment); 896170268Sdarrenr grtop = g->fg_next; 897170268Sdarrenr free(g); 898170268Sdarrenr } 899170268Sdarrenr } 900170268Sdarrenr} 901170268Sdarrenr 902170268Sdarrenr 903170268Sdarrenrstatic void printdeadlist(out, set, fp, group, comment) 904170268Sdarrenrint out, set; 905170268Sdarrenrfrentry_t *fp; 906170268Sdarrenrchar *group, *comment; 907170268Sdarrenr{ 908170268Sdarrenr frgroup_t *grtop, *grtail, *g; 909170268Sdarrenr struct frentry fb; 910170268Sdarrenr char *data; 911170268Sdarrenr u_32_t type; 912170268Sdarrenr int n; 913170268Sdarrenr 914170268Sdarrenr fb.fr_next = fp; 915170268Sdarrenr n = 0; 916170268Sdarrenr grtop = NULL; 917170268Sdarrenr grtail = NULL; 918170268Sdarrenr 919170268Sdarrenr do { 920170268Sdarrenr fp = fb.fr_next; 921170268Sdarrenr if (kmemcpy((char *)&fb, (u_long)fb.fr_next, 922170268Sdarrenr sizeof(fb)) == -1) { 923170268Sdarrenr perror("kmemcpy"); 924170268Sdarrenr return; 925170268Sdarrenr } 926170268Sdarrenr 927145510Sdarrenr data = NULL; 928170268Sdarrenr type = fb.fr_type & ~FR_T_BUILTIN; 929145510Sdarrenr if (type == FR_T_IPF || type == FR_T_BPFOPC) { 930170268Sdarrenr if (fb.fr_dsize) { 931170268Sdarrenr data = malloc(fb.fr_dsize); 932145510Sdarrenr 933170268Sdarrenr if (kmemcpy(data, (u_long)fb.fr_data, 934170268Sdarrenr fb.fr_dsize) == -1) { 935145510Sdarrenr perror("kmemcpy"); 936145510Sdarrenr return; 937145510Sdarrenr } 938170268Sdarrenr fb.fr_data = data; 939145510Sdarrenr } 940145510Sdarrenr } 941145510Sdarrenr 942170268Sdarrenr n++; 943170268Sdarrenr 944170268Sdarrenr if (opts & (OPT_HITS|OPT_VERBOSE)) 945170268Sdarrenr#ifdef USE_QUAD_T 946170268Sdarrenr PRINTF("%qu ", (unsigned long long) fb.fr_hits); 947170268Sdarrenr#else 948170268Sdarrenr PRINTF("%lu ", fb.fr_hits); 949170268Sdarrenr#endif 950170268Sdarrenr if (opts & (OPT_ACCNT|OPT_VERBOSE)) 951170268Sdarrenr#ifdef USE_QUAD_T 952170268Sdarrenr PRINTF("%qu ", (unsigned long long) fb.fr_bytes); 953170268Sdarrenr#else 954170268Sdarrenr PRINTF("%lu ", fb.fr_bytes); 955170268Sdarrenr#endif 956170268Sdarrenr if (opts & OPT_SHOWLINENO) 957170268Sdarrenr PRINTF("@%d ", n); 958170268Sdarrenr 959145510Sdarrenr printfr(fp, ioctl); 960145510Sdarrenr if (opts & OPT_DEBUG) { 961145510Sdarrenr binprint(fp, sizeof(*fp)); 962170268Sdarrenr if (fb.fr_data != NULL && fb.fr_dsize > 0) 963170268Sdarrenr binprint(fb.fr_data, fb.fr_dsize); 964145510Sdarrenr } 965145510Sdarrenr if (data != NULL) 966145510Sdarrenr free(data); 967170268Sdarrenr if (fb.fr_grhead[0] != '\0') { 968170268Sdarrenr g = calloc(1, sizeof(*g)); 969170268Sdarrenr 970170268Sdarrenr if (g != NULL) { 971170268Sdarrenr strncpy(g->fg_name, fb.fr_grhead, 972170268Sdarrenr FR_GROUPLEN); 973170268Sdarrenr if (grtop == NULL) { 974170268Sdarrenr grtop = g; 975170268Sdarrenr grtail = g; 976170268Sdarrenr } else { 977170268Sdarrenr grtail->fg_next = g; 978170268Sdarrenr grtail = g; 979170268Sdarrenr } 980170268Sdarrenr } 981145510Sdarrenr } 982145510Sdarrenr if (type == FR_T_CALLFUNC) { 983170268Sdarrenr printdeadlist(out, set, fb.fr_data, group, 984170268Sdarrenr "# callfunc: "); 985145510Sdarrenr } 986170268Sdarrenr } while (fb.fr_next != NULL); 987170268Sdarrenr 988170268Sdarrenr while ((g = grtop) != NULL) { 989170268Sdarrenr printdeadlist(out, set, NULL, g->fg_name, comment); 990170268Sdarrenr grtop = g->fg_next; 991170268Sdarrenr free(g); 992145510Sdarrenr } 993145510Sdarrenr} 994145510Sdarrenr 995145510Sdarrenr/* 996145510Sdarrenr * print out all of the asked for rule sets, using the stats struct as 997145510Sdarrenr * the base from which to get the pointers. 998145510Sdarrenr */ 999145510Sdarrenrstatic void showlist(fiop) 1000145510Sdarrenrstruct friostat *fiop; 1001145510Sdarrenr{ 1002145510Sdarrenr struct frentry *fp = NULL; 1003145510Sdarrenr int i, set; 1004145510Sdarrenr 1005145510Sdarrenr set = fiop->f_active; 1006145510Sdarrenr if (opts & OPT_INACTIVE) 1007145510Sdarrenr set = 1 - set; 1008145510Sdarrenr if (opts & OPT_ACCNT) { 1009145510Sdarrenr#ifdef USE_INET6 1010145510Sdarrenr if ((use_inet6) && (opts & OPT_OUTQUE)) { 1011145510Sdarrenr i = F_ACOUT; 1012145510Sdarrenr fp = (struct frentry *)fiop->f_acctout6[set]; 1013145510Sdarrenr } else if ((use_inet6) && (opts & OPT_INQUE)) { 1014145510Sdarrenr i = F_ACIN; 1015145510Sdarrenr fp = (struct frentry *)fiop->f_acctin6[set]; 1016145510Sdarrenr } else 1017145510Sdarrenr#endif 1018145510Sdarrenr if (opts & OPT_OUTQUE) { 1019145510Sdarrenr i = F_ACOUT; 1020145510Sdarrenr fp = (struct frentry *)fiop->f_acctout[set]; 1021145510Sdarrenr } else if (opts & OPT_INQUE) { 1022145510Sdarrenr i = F_ACIN; 1023145510Sdarrenr fp = (struct frentry *)fiop->f_acctin[set]; 1024145510Sdarrenr } else { 1025145510Sdarrenr FPRINTF(stderr, "No -i or -o given with -a\n"); 1026145510Sdarrenr return; 1027145510Sdarrenr } 1028145510Sdarrenr } else { 1029145510Sdarrenr#ifdef USE_INET6 1030145510Sdarrenr if ((use_inet6) && (opts & OPT_OUTQUE)) { 1031145510Sdarrenr i = F_OUT; 1032145510Sdarrenr fp = (struct frentry *)fiop->f_fout6[set]; 1033145510Sdarrenr } else if ((use_inet6) && (opts & OPT_INQUE)) { 1034145510Sdarrenr i = F_IN; 1035145510Sdarrenr fp = (struct frentry *)fiop->f_fin6[set]; 1036145510Sdarrenr } else 1037145510Sdarrenr#endif 1038145510Sdarrenr if (opts & OPT_OUTQUE) { 1039145510Sdarrenr i = F_OUT; 1040145510Sdarrenr fp = (struct frentry *)fiop->f_fout[set]; 1041145510Sdarrenr } else if (opts & OPT_INQUE) { 1042145510Sdarrenr i = F_IN; 1043145510Sdarrenr fp = (struct frentry *)fiop->f_fin[set]; 1044145510Sdarrenr } else 1045145510Sdarrenr return; 1046145510Sdarrenr } 1047170268Sdarrenr if (opts & OPT_DEBUG) 1048145510Sdarrenr FPRINTF(stderr, "showlist:opts %#x i %d\n", opts, i); 1049145510Sdarrenr 1050170268Sdarrenr if (opts & OPT_DEBUG) 1051145510Sdarrenr PRINTF("fp %p set %d\n", fp, set); 1052145510Sdarrenr if (!fp) { 1053145510Sdarrenr FPRINTF(stderr, "empty list for %s%s\n", 1054145510Sdarrenr (opts & OPT_INACTIVE) ? "inactive " : "", filters[i]); 1055145510Sdarrenr return; 1056145510Sdarrenr } 1057170268Sdarrenr if (live_kernel == 1) 1058170268Sdarrenr printlivelist(i, set, fp, NULL, NULL); 1059170268Sdarrenr else 1060170268Sdarrenr printdeadlist(i, set, fp, NULL, NULL); 1061145510Sdarrenr} 1062145510Sdarrenr 1063145510Sdarrenr 1064145510Sdarrenr/* 1065145510Sdarrenr * Display ipfilter stateful filtering information 1066145510Sdarrenr */ 1067145510Sdarrenrstatic void showipstates(ipsp) 1068145510Sdarrenrips_stat_t *ipsp; 1069145510Sdarrenr{ 1070145510Sdarrenr u_long minlen, maxlen, totallen, *buckets; 1071170268Sdarrenr ipftable_t table; 1072170268Sdarrenr ipfobj_t obj; 1073145510Sdarrenr int i, sz; 1074145510Sdarrenr 1075145510Sdarrenr /* 1076145510Sdarrenr * If a list of states hasn't been asked for, only print out stats 1077145510Sdarrenr */ 1078145510Sdarrenr if (!(opts & OPT_SHOWLIST)) { 1079170268Sdarrenr 1080170268Sdarrenr sz = sizeof(*buckets) * ipsp->iss_statesize; 1081170268Sdarrenr buckets = (u_long *)malloc(sz); 1082170268Sdarrenr 1083170268Sdarrenr obj.ipfo_rev = IPFILTER_VERSION; 1084170268Sdarrenr obj.ipfo_type = IPFOBJ_GTABLE; 1085170268Sdarrenr obj.ipfo_size = sizeof(table); 1086170268Sdarrenr obj.ipfo_ptr = &table; 1087170268Sdarrenr 1088170268Sdarrenr table.ita_type = IPFTABLE_BUCKETS; 1089170268Sdarrenr table.ita_table = buckets; 1090170268Sdarrenr 1091170268Sdarrenr if (live_kernel == 1) { 1092170268Sdarrenr if (ioctl(state_fd, SIOCGTABL, &obj) != 0) { 1093170268Sdarrenr free(buckets); 1094170268Sdarrenr return; 1095170268Sdarrenr } 1096170268Sdarrenr } else { 1097170268Sdarrenr if (kmemcpy((char *)buckets, 1098170268Sdarrenr (u_long)ipsp->iss_bucketlen, sz)) { 1099170268Sdarrenr free(buckets); 1100170268Sdarrenr return; 1101170268Sdarrenr } 1102170268Sdarrenr } 1103170268Sdarrenr 1104145510Sdarrenr PRINTF("IP states added:\n\t%lu TCP\n\t%lu UDP\n\t%lu ICMP\n", 1105145510Sdarrenr ipsp->iss_tcp, ipsp->iss_udp, ipsp->iss_icmp); 1106145510Sdarrenr PRINTF("\t%lu hits\n\t%lu misses\n", ipsp->iss_hits, 1107145510Sdarrenr ipsp->iss_miss); 1108170268Sdarrenr PRINTF("\t%lu bucket full\n", ipsp->iss_bucketfull); 1109170268Sdarrenr PRINTF("\t%lu maximum rule references\n", ipsp->iss_maxref); 1110145510Sdarrenr PRINTF("\t%lu maximum\n\t%lu no memory\n\t%lu bkts in use\n", 1111145510Sdarrenr ipsp->iss_max, ipsp->iss_nomem, ipsp->iss_inuse); 1112145510Sdarrenr PRINTF("\t%lu active\n\t%lu expired\n\t%lu closed\n", 1113145510Sdarrenr ipsp->iss_active, ipsp->iss_expire, ipsp->iss_fin); 1114145510Sdarrenr 1115145510Sdarrenr PRINTF("State logging %sabled\n", 1116145510Sdarrenr state_logging ? "en" : "dis"); 1117145510Sdarrenr 1118145510Sdarrenr PRINTF("\nState table bucket statistics:\n"); 1119145510Sdarrenr PRINTF("\t%lu in use\t\n", ipsp->iss_inuse); 1120170268Sdarrenr PRINTF("\t%u%% hash efficiency\n", ipsp->iss_active ? 1121170268Sdarrenr (u_int)(ipsp->iss_inuse * 100 / ipsp->iss_active) : 0); 1122145510Sdarrenr 1123172776Sdarrenr minlen = ipsp->iss_inuse; 1124145510Sdarrenr totallen = 0; 1125145510Sdarrenr maxlen = 0; 1126145510Sdarrenr 1127145510Sdarrenr for (i = 0; i < ipsp->iss_statesize; i++) { 1128145510Sdarrenr if (buckets[i] > maxlen) 1129145510Sdarrenr maxlen = buckets[i]; 1130145510Sdarrenr if (buckets[i] < minlen) 1131172776Sdarrenr minlen = buckets[i]; 1132145510Sdarrenr totallen += buckets[i]; 1133145510Sdarrenr } 1134145510Sdarrenr 1135145510Sdarrenr PRINTF("\t%2.2f%% bucket usage\n\t%lu minimal length\n", 1136145510Sdarrenr ((float)ipsp->iss_inuse / ipsp->iss_statesize) * 100.0, 1137145510Sdarrenr minlen); 1138145510Sdarrenr PRINTF("\t%lu maximal length\n\t%.3f average length\n", 1139145510Sdarrenr maxlen, 1140145510Sdarrenr ipsp->iss_inuse ? (float) totallen/ ipsp->iss_inuse : 1141145510Sdarrenr 0.0); 1142145510Sdarrenr 1143145510Sdarrenr#define ENTRIES_PER_LINE 5 1144145510Sdarrenr 1145145510Sdarrenr if (opts & OPT_VERBOSE) { 1146145510Sdarrenr PRINTF("\nCurrent bucket sizes :\n"); 1147145510Sdarrenr for (i = 0; i < ipsp->iss_statesize; i++) { 1148145510Sdarrenr if ((i % ENTRIES_PER_LINE) == 0) 1149145510Sdarrenr PRINTF("\t"); 1150145510Sdarrenr PRINTF("%4d -> %4lu", i, buckets[i]); 1151145510Sdarrenr if ((i % ENTRIES_PER_LINE) == 1152145510Sdarrenr (ENTRIES_PER_LINE - 1)) 1153145510Sdarrenr PRINTF("\n"); 1154145510Sdarrenr else 1155145510Sdarrenr PRINTF(" "); 1156145510Sdarrenr } 1157145510Sdarrenr PRINTF("\n"); 1158145510Sdarrenr } 1159145510Sdarrenr PRINTF("\n"); 1160145510Sdarrenr 1161145510Sdarrenr free(buckets); 1162170268Sdarrenr 1163170268Sdarrenr if (live_kernel == 1) { 1164170268Sdarrenr showtqtable_live(state_fd); 1165170268Sdarrenr } else { 1166170268Sdarrenr printtqtable(ipsp->iss_tcptab); 1167170268Sdarrenr } 1168170268Sdarrenr 1169145510Sdarrenr return; 1170170268Sdarrenr 1171145510Sdarrenr } 1172145510Sdarrenr 1173145510Sdarrenr /* 1174145510Sdarrenr * Print out all the state information currently held in the kernel. 1175145510Sdarrenr */ 1176145510Sdarrenr while (ipsp->iss_list != NULL) { 1177170268Sdarrenr ipstate_t ips; 1178170268Sdarrenr 1179170268Sdarrenr ipsp->iss_list = fetchstate(ipsp->iss_list, &ips); 1180170268Sdarrenr 1181170268Sdarrenr if (ipsp->iss_list != NULL) { 1182170268Sdarrenr ipsp->iss_list = ips.is_next; 1183170268Sdarrenr printstate(&ips, opts, ipsp->iss_ticks); 1184170268Sdarrenr } 1185145510Sdarrenr } 1186145510Sdarrenr} 1187145510Sdarrenr 1188145510Sdarrenr 1189145510Sdarrenr#ifdef STATETOP 1190145510Sdarrenrstatic int handle_resize = 0, handle_break = 0; 1191145510Sdarrenr 1192145510Sdarrenrstatic void topipstates(saddr, daddr, sport, dport, protocol, ver, 1193145510Sdarrenr refreshtime, topclosed) 1194145510Sdarrenri6addr_t saddr; 1195145510Sdarrenri6addr_t daddr; 1196145510Sdarrenrint sport; 1197145510Sdarrenrint dport; 1198145510Sdarrenrint protocol; 1199145510Sdarrenrint ver; 1200145510Sdarrenrint refreshtime; 1201145510Sdarrenrint topclosed; 1202145510Sdarrenr{ 1203145510Sdarrenr char str1[STSTRSIZE], str2[STSTRSIZE], str3[STSTRSIZE], str4[STSTRSIZE]; 1204145510Sdarrenr int maxtsentries = 0, reverse = 0, sorting = STSORT_DEFAULT; 1205153881Sguido int i, j, winy, tsentry, maxx, maxy, redraw = 0, ret = 0; 1206145510Sdarrenr int len, srclen, dstlen, forward = 1, c = 0; 1207145510Sdarrenr ips_stat_t ipsst, *ipsstp = &ipsst; 1208145510Sdarrenr statetop_t *tstable = NULL, *tp; 1209153881Sguido const char *errstr = ""; 1210145510Sdarrenr ipstate_t ips; 1211145510Sdarrenr ipfobj_t ipfo; 1212145510Sdarrenr struct timeval selecttimeout; 1213145510Sdarrenr char hostnm[HOSTNMLEN]; 1214145510Sdarrenr struct protoent *proto; 1215145510Sdarrenr fd_set readfd; 1216145510Sdarrenr time_t t; 1217145510Sdarrenr 1218145510Sdarrenr /* install signal handlers */ 1219145510Sdarrenr signal(SIGINT, sig_break); 1220145510Sdarrenr signal(SIGQUIT, sig_break); 1221145510Sdarrenr signal(SIGTERM, sig_break); 1222145510Sdarrenr signal(SIGWINCH, sig_resize); 1223145510Sdarrenr 1224145510Sdarrenr /* init ncurses stuff */ 1225145510Sdarrenr initscr(); 1226145510Sdarrenr cbreak(); 1227145510Sdarrenr noecho(); 1228145510Sdarrenr curs_set(0); 1229145510Sdarrenr timeout(0); 1230145510Sdarrenr getmaxyx(stdscr, maxy, maxx); 1231145510Sdarrenr 1232145510Sdarrenr /* init hostname */ 1233145510Sdarrenr gethostname(hostnm, sizeof(hostnm) - 1); 1234145510Sdarrenr hostnm[sizeof(hostnm) - 1] = '\0'; 1235145510Sdarrenr 1236145510Sdarrenr /* init ipfobj_t stuff */ 1237145510Sdarrenr bzero((caddr_t)&ipfo, sizeof(ipfo)); 1238145510Sdarrenr ipfo.ipfo_rev = IPFILTER_VERSION; 1239170268Sdarrenr ipfo.ipfo_type = IPFOBJ_STATESTAT; 1240145510Sdarrenr ipfo.ipfo_size = sizeof(*ipsstp); 1241145510Sdarrenr ipfo.ipfo_ptr = (void *)ipsstp; 1242145510Sdarrenr 1243145510Sdarrenr /* repeat until user aborts */ 1244145510Sdarrenr while ( 1 ) { 1245145510Sdarrenr 1246145510Sdarrenr /* get state table */ 1247145510Sdarrenr bzero((char *)&ipsst, sizeof(ipsst)); 1248145510Sdarrenr if ((ioctl(state_fd, SIOCGETFS, &ipfo) == -1)) { 1249153881Sguido errstr = "ioctl(SIOCGETFS)"; 1250153881Sguido ret = -1; 1251153881Sguido goto out; 1252145510Sdarrenr } 1253145510Sdarrenr 1254145510Sdarrenr /* clear the history */ 1255145510Sdarrenr tsentry = -1; 1256145510Sdarrenr 1257145510Sdarrenr /* reset max str len */ 1258145510Sdarrenr srclen = dstlen = 0; 1259145510Sdarrenr 1260145510Sdarrenr /* read the state table and store in tstable */ 1261145510Sdarrenr for (; ipsstp->iss_list; ipsstp->iss_list = ips.is_next) { 1262145510Sdarrenr 1263170268Sdarrenr ipsstp->iss_list = fetchstate(ipsstp->iss_list, &ips); 1264170268Sdarrenr if (ipsstp->iss_list == NULL) 1265145510Sdarrenr break; 1266145510Sdarrenr 1267145510Sdarrenr if (ips.is_v != ver) 1268145510Sdarrenr continue; 1269145510Sdarrenr 1270145510Sdarrenr /* check v4 src/dest addresses */ 1271145510Sdarrenr if (ips.is_v == 4) { 1272145510Sdarrenr if ((saddr.in4.s_addr != INADDR_ANY && 1273145510Sdarrenr saddr.in4.s_addr != ips.is_saddr) || 1274145510Sdarrenr (daddr.in4.s_addr != INADDR_ANY && 1275145510Sdarrenr daddr.in4.s_addr != ips.is_daddr)) 1276145510Sdarrenr continue; 1277145510Sdarrenr } 1278145510Sdarrenr#ifdef USE_INET6 1279145510Sdarrenr /* check v6 src/dest addresses */ 1280145510Sdarrenr if (ips.is_v == 6) { 1281145510Sdarrenr if ((IP6_NEQ(&saddr, &in6addr_any) && 1282145510Sdarrenr IP6_NEQ(&saddr, &ips.is_src)) || 1283145510Sdarrenr (IP6_NEQ(&daddr, &in6addr_any) && 1284145510Sdarrenr IP6_NEQ(&daddr, &ips.is_dst))) 1285145510Sdarrenr continue; 1286145510Sdarrenr } 1287145510Sdarrenr#endif 1288145510Sdarrenr /* check protocol */ 1289145510Sdarrenr if (protocol > 0 && protocol != ips.is_p) 1290145510Sdarrenr continue; 1291145510Sdarrenr 1292145510Sdarrenr /* check ports if protocol is TCP or UDP */ 1293145510Sdarrenr if (((ips.is_p == IPPROTO_TCP) || 1294145510Sdarrenr (ips.is_p == IPPROTO_UDP)) && 1295145510Sdarrenr (((sport > 0) && (htons(sport) != ips.is_sport)) || 1296145510Sdarrenr ((dport > 0) && (htons(dport) != ips.is_dport)))) 1297145510Sdarrenr continue; 1298145510Sdarrenr 1299145510Sdarrenr /* show closed TCP sessions ? */ 1300145510Sdarrenr if ((topclosed == 0) && (ips.is_p == IPPROTO_TCP) && 1301145510Sdarrenr (ips.is_state[0] >= IPF_TCPS_LAST_ACK) && 1302145510Sdarrenr (ips.is_state[1] >= IPF_TCPS_LAST_ACK)) 1303145510Sdarrenr continue; 1304145510Sdarrenr 1305145510Sdarrenr /* 1306145510Sdarrenr * if necessary make room for this state 1307145510Sdarrenr * entry 1308145510Sdarrenr */ 1309145510Sdarrenr tsentry++; 1310145510Sdarrenr if (!maxtsentries || tsentry == maxtsentries) { 1311145510Sdarrenr maxtsentries += STGROWSIZE; 1312145510Sdarrenr tstable = realloc(tstable, 1313145510Sdarrenr maxtsentries * sizeof(statetop_t)); 1314145510Sdarrenr if (tstable == NULL) { 1315145510Sdarrenr perror("realloc"); 1316145510Sdarrenr exit(-1); 1317145510Sdarrenr } 1318145510Sdarrenr } 1319145510Sdarrenr 1320145510Sdarrenr /* get max src/dest address string length */ 1321145510Sdarrenr len = strlen(getip(ips.is_v, &ips.is_src)); 1322145510Sdarrenr if (srclen < len) 1323145510Sdarrenr srclen = len; 1324145510Sdarrenr len = strlen(getip(ips.is_v, &ips.is_dst)); 1325145510Sdarrenr if (dstlen < len) 1326145510Sdarrenr dstlen = len; 1327145510Sdarrenr 1328145510Sdarrenr /* fill structure */ 1329145510Sdarrenr tp = tstable + tsentry; 1330145510Sdarrenr tp->st_src = ips.is_src; 1331145510Sdarrenr tp->st_dst = ips.is_dst; 1332145510Sdarrenr tp->st_p = ips.is_p; 1333145510Sdarrenr tp->st_v = ips.is_v; 1334145510Sdarrenr tp->st_state[0] = ips.is_state[0]; 1335145510Sdarrenr tp->st_state[1] = ips.is_state[1]; 1336145510Sdarrenr if (forward) { 1337145510Sdarrenr tp->st_pkts = ips.is_pkts[0]+ips.is_pkts[1]; 1338145510Sdarrenr tp->st_bytes = ips.is_bytes[0]+ips.is_bytes[1]; 1339145510Sdarrenr } else { 1340145510Sdarrenr tp->st_pkts = ips.is_pkts[2]+ips.is_pkts[3]; 1341145510Sdarrenr tp->st_bytes = ips.is_bytes[2]+ips.is_bytes[3]; 1342145510Sdarrenr } 1343145510Sdarrenr tp->st_age = ips.is_die - ipsstp->iss_ticks; 1344145510Sdarrenr if ((ips.is_p == IPPROTO_TCP) || 1345145510Sdarrenr (ips.is_p == IPPROTO_UDP)) { 1346145510Sdarrenr tp->st_sport = ips.is_sport; 1347145510Sdarrenr tp->st_dport = ips.is_dport; 1348145510Sdarrenr } 1349145510Sdarrenr } 1350145510Sdarrenr 1351145510Sdarrenr 1352145510Sdarrenr /* sort the array */ 1353145510Sdarrenr if (tsentry != -1) { 1354145510Sdarrenr switch (sorting) 1355145510Sdarrenr { 1356145510Sdarrenr case STSORT_PR: 1357145510Sdarrenr qsort(tstable, tsentry + 1, 1358145510Sdarrenr sizeof(statetop_t), sort_p); 1359145510Sdarrenr break; 1360145510Sdarrenr case STSORT_PKTS: 1361145510Sdarrenr qsort(tstable, tsentry + 1, 1362145510Sdarrenr sizeof(statetop_t), sort_pkts); 1363145510Sdarrenr break; 1364145510Sdarrenr case STSORT_BYTES: 1365145510Sdarrenr qsort(tstable, tsentry + 1, 1366145510Sdarrenr sizeof(statetop_t), sort_bytes); 1367145510Sdarrenr break; 1368145510Sdarrenr case STSORT_TTL: 1369145510Sdarrenr qsort(tstable, tsentry + 1, 1370145510Sdarrenr sizeof(statetop_t), sort_ttl); 1371145510Sdarrenr break; 1372145510Sdarrenr case STSORT_SRCIP: 1373145510Sdarrenr qsort(tstable, tsentry + 1, 1374145510Sdarrenr sizeof(statetop_t), sort_srcip); 1375145510Sdarrenr break; 1376145510Sdarrenr case STSORT_SRCPT: 1377145510Sdarrenr qsort(tstable, tsentry +1, 1378145510Sdarrenr sizeof(statetop_t), sort_srcpt); 1379145510Sdarrenr break; 1380145510Sdarrenr case STSORT_DSTIP: 1381145510Sdarrenr qsort(tstable, tsentry + 1, 1382145510Sdarrenr sizeof(statetop_t), sort_dstip); 1383145510Sdarrenr break; 1384145510Sdarrenr case STSORT_DSTPT: 1385145510Sdarrenr qsort(tstable, tsentry + 1, 1386145510Sdarrenr sizeof(statetop_t), sort_dstpt); 1387145510Sdarrenr break; 1388145510Sdarrenr default: 1389145510Sdarrenr break; 1390145510Sdarrenr } 1391145510Sdarrenr } 1392145510Sdarrenr 1393145510Sdarrenr /* handle window resizes */ 1394145510Sdarrenr if (handle_resize) { 1395145510Sdarrenr endwin(); 1396145510Sdarrenr initscr(); 1397145510Sdarrenr cbreak(); 1398145510Sdarrenr noecho(); 1399145510Sdarrenr curs_set(0); 1400145510Sdarrenr timeout(0); 1401145510Sdarrenr getmaxyx(stdscr, maxy, maxx); 1402145510Sdarrenr redraw = 1; 1403145510Sdarrenr handle_resize = 0; 1404145510Sdarrenr } 1405145510Sdarrenr 1406145510Sdarrenr /* stop program? */ 1407145510Sdarrenr if (handle_break) 1408145510Sdarrenr break; 1409145510Sdarrenr 1410145510Sdarrenr /* print title */ 1411145510Sdarrenr erase(); 1412145510Sdarrenr attron(A_BOLD); 1413145510Sdarrenr winy = 0; 1414145510Sdarrenr move(winy,0); 1415145510Sdarrenr sprintf(str1, "%s - %s - state top", hostnm, IPL_VERSION); 1416145510Sdarrenr for (j = 0 ; j < (maxx - 8 - strlen(str1)) / 2; j++) 1417145510Sdarrenr printw(" "); 1418145510Sdarrenr printw("%s", str1); 1419145510Sdarrenr attroff(A_BOLD); 1420145510Sdarrenr 1421145510Sdarrenr /* just for fun add a clock */ 1422145510Sdarrenr move(winy, maxx - 8); 1423145510Sdarrenr t = time(NULL); 1424145510Sdarrenr strftime(str1, 80, "%T", localtime(&t)); 1425145510Sdarrenr printw("%s\n", str1); 1426145510Sdarrenr 1427145510Sdarrenr /* 1428145510Sdarrenr * print the display filters, this is placed in the loop, 1429145510Sdarrenr * because someday I might add code for changing these 1430145510Sdarrenr * while the programming is running :-) 1431145510Sdarrenr */ 1432145510Sdarrenr if (sport >= 0) 1433145510Sdarrenr sprintf(str1, "%s,%d", getip(ver, &saddr), sport); 1434145510Sdarrenr else 1435145510Sdarrenr sprintf(str1, "%s", getip(ver, &saddr)); 1436145510Sdarrenr 1437145510Sdarrenr if (dport >= 0) 1438145510Sdarrenr sprintf(str2, "%s,%d", getip(ver, &daddr), dport); 1439145510Sdarrenr else 1440145510Sdarrenr sprintf(str2, "%s", getip(ver, &daddr)); 1441145510Sdarrenr 1442145510Sdarrenr if (protocol < 0) 1443145510Sdarrenr strcpy(str3, "any"); 1444145510Sdarrenr else if ((proto = getprotobynumber(protocol)) != NULL) 1445145510Sdarrenr sprintf(str3, "%s", proto->p_name); 1446145510Sdarrenr else 1447145510Sdarrenr sprintf(str3, "%d", protocol); 1448145510Sdarrenr 1449145510Sdarrenr switch (sorting) 1450145510Sdarrenr { 1451145510Sdarrenr case STSORT_PR: 1452145510Sdarrenr sprintf(str4, "proto"); 1453145510Sdarrenr break; 1454145510Sdarrenr case STSORT_PKTS: 1455145510Sdarrenr sprintf(str4, "# pkts"); 1456145510Sdarrenr break; 1457145510Sdarrenr case STSORT_BYTES: 1458145510Sdarrenr sprintf(str4, "# bytes"); 1459145510Sdarrenr break; 1460145510Sdarrenr case STSORT_TTL: 1461145510Sdarrenr sprintf(str4, "ttl"); 1462145510Sdarrenr break; 1463145510Sdarrenr case STSORT_SRCIP: 1464145510Sdarrenr sprintf(str4, "src ip"); 1465145510Sdarrenr break; 1466145510Sdarrenr case STSORT_SRCPT: 1467145510Sdarrenr sprintf(str4, "src port"); 1468145510Sdarrenr break; 1469145510Sdarrenr case STSORT_DSTIP: 1470145510Sdarrenr sprintf(str4, "dest ip"); 1471145510Sdarrenr break; 1472145510Sdarrenr case STSORT_DSTPT: 1473145510Sdarrenr sprintf(str4, "dest port"); 1474145510Sdarrenr break; 1475145510Sdarrenr default: 1476145510Sdarrenr sprintf(str4, "unknown"); 1477145510Sdarrenr break; 1478145510Sdarrenr } 1479145510Sdarrenr 1480145510Sdarrenr if (reverse) 1481145510Sdarrenr strcat(str4, " (reverse)"); 1482145510Sdarrenr 1483145510Sdarrenr winy += 2; 1484145510Sdarrenr move(winy,0); 1485145510Sdarrenr printw("Src: %s, Dest: %s, Proto: %s, Sorted by: %s\n\n", 1486145510Sdarrenr str1, str2, str3, str4); 1487145510Sdarrenr 1488145510Sdarrenr /* 1489145510Sdarrenr * For an IPv4 IP address we need at most 15 characters, 1490145510Sdarrenr * 4 tuples of 3 digits, separated by 3 dots. Enforce this 1491145510Sdarrenr * length, so the colums do not change positions based 1492145510Sdarrenr * on the size of the IP address. This length makes the 1493145510Sdarrenr * output fit in a 80 column terminal. 1494145510Sdarrenr * We are lacking a good solution for IPv6 addresses (that 1495145510Sdarrenr * can be longer that 15 characters), so we do not enforce 1496145510Sdarrenr * a maximum on the IP field size. 1497145510Sdarrenr */ 1498145510Sdarrenr if (srclen < 15) 1499145510Sdarrenr srclen = 15; 1500145510Sdarrenr if (dstlen < 15) 1501145510Sdarrenr dstlen = 15; 1502145510Sdarrenr 1503145510Sdarrenr /* print column description */ 1504145510Sdarrenr winy += 2; 1505145510Sdarrenr move(winy,0); 1506145510Sdarrenr attron(A_BOLD); 1507145510Sdarrenr printw("%-*s %-*s %3s %4s %7s %9s %9s\n", 1508145510Sdarrenr srclen + 6, "Source IP", dstlen + 6, "Destination IP", 1509145510Sdarrenr "ST", "PR", "#pkts", "#bytes", "ttl"); 1510145510Sdarrenr attroff(A_BOLD); 1511145510Sdarrenr 1512145510Sdarrenr /* print all the entries */ 1513145510Sdarrenr tp = tstable; 1514145510Sdarrenr if (reverse) 1515145510Sdarrenr tp += tsentry; 1516145510Sdarrenr 1517145510Sdarrenr if (tsentry > maxy - 6) 1518145510Sdarrenr tsentry = maxy - 6; 1519145510Sdarrenr for (i = 0; i <= tsentry; i++) { 1520145510Sdarrenr /* print src/dest and port */ 1521145510Sdarrenr if ((tp->st_p == IPPROTO_TCP) || 1522145510Sdarrenr (tp->st_p == IPPROTO_UDP)) { 1523145510Sdarrenr sprintf(str1, "%s,%hu", 1524145510Sdarrenr getip(tp->st_v, &tp->st_src), 1525145510Sdarrenr ntohs(tp->st_sport)); 1526145510Sdarrenr sprintf(str2, "%s,%hu", 1527145510Sdarrenr getip(tp->st_v, &tp->st_dst), 1528145510Sdarrenr ntohs(tp->st_dport)); 1529145510Sdarrenr } else { 1530145510Sdarrenr sprintf(str1, "%s", getip(tp->st_v, 1531145510Sdarrenr &tp->st_src)); 1532145510Sdarrenr sprintf(str2, "%s", getip(tp->st_v, 1533145510Sdarrenr &tp->st_dst)); 1534145510Sdarrenr } 1535145510Sdarrenr winy++; 1536145510Sdarrenr move(winy, 0); 1537145510Sdarrenr printw("%-*s %-*s", srclen + 6, str1, dstlen + 6, str2); 1538145510Sdarrenr 1539145510Sdarrenr /* print state */ 1540145510Sdarrenr sprintf(str1, "%X/%X", tp->st_state[0], 1541145510Sdarrenr tp->st_state[1]); 1542145510Sdarrenr printw(" %3s", str1); 1543145510Sdarrenr 1544145510Sdarrenr /* print protocol */ 1545145510Sdarrenr proto = getprotobynumber(tp->st_p); 1546145510Sdarrenr if (proto) { 1547145510Sdarrenr strncpy(str1, proto->p_name, 4); 1548145510Sdarrenr str1[4] = '\0'; 1549145510Sdarrenr } else { 1550145510Sdarrenr sprintf(str1, "%d", tp->st_p); 1551145510Sdarrenr } 1552145510Sdarrenr /* just print icmp for IPv6-ICMP */ 1553145510Sdarrenr if (tp->st_p == IPPROTO_ICMPV6) 1554145510Sdarrenr strcpy(str1, "icmp"); 1555145510Sdarrenr printw(" %4s", str1); 1556145510Sdarrenr 1557145510Sdarrenr /* print #pkt/#bytes */ 1558145510Sdarrenr#ifdef USE_QUAD_T 1559145510Sdarrenr printw(" %7qu %9qu", (unsigned long long) tp->st_pkts, 1560145510Sdarrenr (unsigned long long) tp->st_bytes); 1561145510Sdarrenr#else 1562145510Sdarrenr printw(" %7lu %9lu", tp->st_pkts, tp->st_bytes); 1563145510Sdarrenr#endif 1564145510Sdarrenr printw(" %9s", ttl_to_string(tp->st_age)); 1565145510Sdarrenr 1566145510Sdarrenr if (reverse) 1567145510Sdarrenr tp--; 1568145510Sdarrenr else 1569145510Sdarrenr tp++; 1570145510Sdarrenr } 1571145510Sdarrenr 1572145510Sdarrenr /* screen data structure is filled, now update the screen */ 1573145510Sdarrenr if (redraw) 1574145510Sdarrenr clearok(stdscr,1); 1575145510Sdarrenr 1576145510Sdarrenr if (refresh() == ERR) 1577145510Sdarrenr break; 1578145510Sdarrenr if (redraw) { 1579145510Sdarrenr clearok(stdscr,0); 1580145510Sdarrenr redraw = 0; 1581145510Sdarrenr } 1582145510Sdarrenr 1583145510Sdarrenr /* wait for key press or a 1 second time out period */ 1584145510Sdarrenr selecttimeout.tv_sec = refreshtime; 1585145510Sdarrenr selecttimeout.tv_usec = 0; 1586145510Sdarrenr FD_ZERO(&readfd); 1587145510Sdarrenr FD_SET(0, &readfd); 1588145510Sdarrenr select(1, &readfd, NULL, NULL, &selecttimeout); 1589145510Sdarrenr 1590145510Sdarrenr /* if key pressed, read all waiting keys */ 1591145510Sdarrenr if (FD_ISSET(0, &readfd)) { 1592145510Sdarrenr c = wgetch(stdscr); 1593145510Sdarrenr if (c == ERR) 1594145510Sdarrenr continue; 1595145510Sdarrenr 1596145510Sdarrenr if (ISALPHA(c) && ISUPPER(c)) 1597145510Sdarrenr c = TOLOWER(c); 1598145510Sdarrenr if (c == 'l') { 1599145510Sdarrenr redraw = 1; 1600145510Sdarrenr } else if (c == 'q') { 1601145510Sdarrenr break; 1602145510Sdarrenr } else if (c == 'r') { 1603145510Sdarrenr reverse = !reverse; 1604145510Sdarrenr } else if (c == 'b') { 1605145510Sdarrenr forward = 0; 1606145510Sdarrenr } else if (c == 'f') { 1607145510Sdarrenr forward = 1; 1608145510Sdarrenr } else if (c == 's') { 1609145510Sdarrenr if (++sorting > STSORT_MAX) 1610145510Sdarrenr sorting = 0; 1611145510Sdarrenr } 1612145510Sdarrenr } 1613145510Sdarrenr } /* while */ 1614145510Sdarrenr 1615153881Sguidoout: 1616145510Sdarrenr printw("\n"); 1617145510Sdarrenr curs_set(1); 1618153881Sguido /* nocbreak(); XXX - endwin() should make this redundant */ 1619145510Sdarrenr endwin(); 1620145510Sdarrenr 1621145510Sdarrenr free(tstable); 1622153881Sguido if (ret != 0) 1623153881Sguido perror(errstr); 1624145510Sdarrenr} 1625145510Sdarrenr#endif 1626145510Sdarrenr 1627145510Sdarrenr 1628145510Sdarrenr/* 1629145510Sdarrenr * Show fragment cache information that's held in the kernel. 1630145510Sdarrenr */ 1631170268Sdarrenrstatic void showfrstates(ifsp, ticks) 1632145510Sdarrenripfrstat_t *ifsp; 1633170268Sdarrenru_long ticks; 1634145510Sdarrenr{ 1635145510Sdarrenr struct ipfr *ipfrtab[IPFT_SIZE], ifr; 1636145510Sdarrenr int i; 1637145510Sdarrenr 1638145510Sdarrenr /* 1639145510Sdarrenr * print out the numeric statistics 1640145510Sdarrenr */ 1641145510Sdarrenr PRINTF("IP fragment states:\n\t%lu new\n\t%lu expired\n\t%lu hits\n", 1642145510Sdarrenr ifsp->ifs_new, ifsp->ifs_expire, ifsp->ifs_hits); 1643145510Sdarrenr PRINTF("\t%lu retrans\n\t%lu too short\n", 1644145510Sdarrenr ifsp->ifs_retrans0, ifsp->ifs_short); 1645145510Sdarrenr PRINTF("\t%lu no memory\n\t%lu already exist\n", 1646145510Sdarrenr ifsp->ifs_nomem, ifsp->ifs_exists); 1647145510Sdarrenr PRINTF("\t%lu inuse\n", ifsp->ifs_inuse); 1648170268Sdarrenr PRINTF("\n"); 1649145510Sdarrenr 1650170268Sdarrenr if (live_kernel == 0) { 1651170268Sdarrenr if (kmemcpy((char *)ipfrtab, (u_long)ifsp->ifs_table, 1652170268Sdarrenr sizeof(ipfrtab))) 1653170268Sdarrenr return; 1654170268Sdarrenr } 1655170268Sdarrenr 1656145510Sdarrenr /* 1657145510Sdarrenr * Print out the contents (if any) of the fragment cache table. 1658145510Sdarrenr */ 1659170268Sdarrenr if (live_kernel == 1) { 1660170268Sdarrenr do { 1661170268Sdarrenr if (fetchfrag(ipf_fd, IPFGENITER_FRAG, &ifr) != 0) 1662145510Sdarrenr break; 1663170268Sdarrenr if (ifr.ipfr_ifp == NULL) 1664170268Sdarrenr break; 1665170268Sdarrenr ifr.ipfr_ttl -= ticks; 1666145510Sdarrenr printfraginfo("", &ifr); 1667170268Sdarrenr } while (1); 1668170268Sdarrenr } else { 1669170268Sdarrenr for (i = 0; i < IPFT_SIZE; i++) 1670170268Sdarrenr while (ipfrtab[i] != NULL) { 1671170268Sdarrenr if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i], 1672170268Sdarrenr sizeof(ifr)) == -1) 1673170268Sdarrenr break; 1674170268Sdarrenr printfraginfo("", &ifr); 1675170268Sdarrenr ipfrtab[i] = ifr.ipfr_next; 1676170268Sdarrenr } 1677170268Sdarrenr } 1678145510Sdarrenr /* 1679145510Sdarrenr * Print out the contents (if any) of the NAT fragment cache table. 1680145510Sdarrenr */ 1681170268Sdarrenr 1682170268Sdarrenr if (live_kernel == 0) { 1683170268Sdarrenr if (kmemcpy((char *)ipfrtab, (u_long)ifsp->ifs_nattab, 1684170268Sdarrenr sizeof(ipfrtab))) 1685170268Sdarrenr return; 1686170268Sdarrenr } 1687170268Sdarrenr 1688170268Sdarrenr if (live_kernel == 1) { 1689170268Sdarrenr do { 1690170268Sdarrenr if (fetchfrag(nat_fd, IPFGENITER_NATFRAG, &ifr) != 0) 1691145510Sdarrenr break; 1692170268Sdarrenr if (ifr.ipfr_ifp == NULL) 1693170268Sdarrenr break; 1694170268Sdarrenr ifr.ipfr_ttl -= ticks; 1695145510Sdarrenr printfraginfo("NAT: ", &ifr); 1696170268Sdarrenr } while (1); 1697170268Sdarrenr } else { 1698170268Sdarrenr for (i = 0; i < IPFT_SIZE; i++) 1699170268Sdarrenr while (ipfrtab[i] != NULL) { 1700170268Sdarrenr if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i], 1701170268Sdarrenr sizeof(ifr)) == -1) 1702170268Sdarrenr break; 1703170268Sdarrenr printfraginfo("NAT: ", &ifr); 1704170268Sdarrenr ipfrtab[i] = ifr.ipfr_next; 1705170268Sdarrenr } 1706170268Sdarrenr } 1707145510Sdarrenr} 1708145510Sdarrenr 1709145510Sdarrenr 1710145510Sdarrenr/* 1711145510Sdarrenr * Show stats on how auth within IPFilter has been used 1712145510Sdarrenr */ 1713145510Sdarrenrstatic void showauthstates(asp) 1714145510Sdarrenrfr_authstat_t *asp; 1715145510Sdarrenr{ 1716145510Sdarrenr frauthent_t *frap, fra; 1717170268Sdarrenr ipfgeniter_t auth; 1718170268Sdarrenr ipfobj_t obj; 1719145510Sdarrenr 1720170268Sdarrenr obj.ipfo_rev = IPFILTER_VERSION; 1721170268Sdarrenr obj.ipfo_type = IPFOBJ_GENITER; 1722170268Sdarrenr obj.ipfo_size = sizeof(auth); 1723170268Sdarrenr obj.ipfo_ptr = &auth; 1724170268Sdarrenr 1725170268Sdarrenr auth.igi_type = IPFGENITER_AUTH; 1726170268Sdarrenr auth.igi_nitems = 1; 1727170268Sdarrenr auth.igi_data = &fra; 1728170268Sdarrenr 1729145510Sdarrenr#ifdef USE_QUAD_T 1730145510Sdarrenr printf("Authorisation hits: %qu\tmisses %qu\n", 1731145510Sdarrenr (unsigned long long) asp->fas_hits, 1732145510Sdarrenr (unsigned long long) asp->fas_miss); 1733145510Sdarrenr#else 1734145510Sdarrenr printf("Authorisation hits: %ld\tmisses %ld\n", asp->fas_hits, 1735145510Sdarrenr asp->fas_miss); 1736145510Sdarrenr#endif 1737145510Sdarrenr printf("nospace %ld\nadded %ld\nsendfail %ld\nsendok %ld\n", 1738145510Sdarrenr asp->fas_nospace, asp->fas_added, asp->fas_sendfail, 1739145510Sdarrenr asp->fas_sendok); 1740145510Sdarrenr printf("queok %ld\nquefail %ld\nexpire %ld\n", 1741145510Sdarrenr asp->fas_queok, asp->fas_quefail, asp->fas_expire); 1742145510Sdarrenr 1743145510Sdarrenr frap = asp->fas_faelist; 1744145510Sdarrenr while (frap) { 1745170268Sdarrenr if (live_kernel == 1) { 1746170268Sdarrenr if (ioctl(auth_fd, SIOCGENITER, &obj)) 1747170268Sdarrenr break; 1748170268Sdarrenr } else { 1749170268Sdarrenr if (kmemcpy((char *)&fra, (u_long)frap, 1750170268Sdarrenr sizeof(fra)) == -1) 1751170268Sdarrenr break; 1752170268Sdarrenr } 1753145510Sdarrenr printf("age %ld\t", fra.fae_age); 1754145510Sdarrenr printfr(&fra.fae_fr, ioctl); 1755145510Sdarrenr frap = fra.fae_next; 1756145510Sdarrenr } 1757145510Sdarrenr} 1758145510Sdarrenr 1759145510Sdarrenr 1760145510Sdarrenr/* 1761145510Sdarrenr * Display groups used for each of filter rules, accounting rules and 1762145510Sdarrenr * authentication, separately. 1763145510Sdarrenr */ 1764145510Sdarrenrstatic void showgroups(fiop) 1765145510Sdarrenrstruct friostat *fiop; 1766145510Sdarrenr{ 1767145510Sdarrenr static char *gnames[3] = { "Filter", "Accounting", "Authentication" }; 1768145510Sdarrenr static int gnums[3] = { IPL_LOGIPF, IPL_LOGCOUNT, IPL_LOGAUTH }; 1769145510Sdarrenr frgroup_t *fp, grp; 1770145510Sdarrenr int on, off, i; 1771145510Sdarrenr 1772145510Sdarrenr on = fiop->f_active; 1773145510Sdarrenr off = 1 - on; 1774145510Sdarrenr 1775145510Sdarrenr for (i = 0; i < 3; i++) { 1776145510Sdarrenr printf("%s groups (active):\n", gnames[i]); 1777145510Sdarrenr for (fp = fiop->f_groups[gnums[i]][on]; fp != NULL; 1778145510Sdarrenr fp = grp.fg_next) 1779145510Sdarrenr if (kmemcpy((char *)&grp, (u_long)fp, sizeof(grp))) 1780145510Sdarrenr break; 1781145510Sdarrenr else 1782145510Sdarrenr printf("%s\n", grp.fg_name); 1783145510Sdarrenr printf("%s groups (inactive):\n", gnames[i]); 1784145510Sdarrenr for (fp = fiop->f_groups[gnums[i]][off]; fp != NULL; 1785145510Sdarrenr fp = grp.fg_next) 1786145510Sdarrenr if (kmemcpy((char *)&grp, (u_long)fp, sizeof(grp))) 1787145510Sdarrenr break; 1788145510Sdarrenr else 1789145510Sdarrenr printf("%s\n", grp.fg_name); 1790145510Sdarrenr } 1791145510Sdarrenr} 1792145510Sdarrenr 1793145510Sdarrenrstatic void parse_ipportstr(argument, ip, port) 1794145510Sdarrenrconst char *argument; 1795145510Sdarrenri6addr_t *ip; 1796145510Sdarrenrint *port; 1797145510Sdarrenr{ 1798145510Sdarrenr char *s, *comma; 1799145510Sdarrenr int ok = 0; 1800145510Sdarrenr 1801145510Sdarrenr /* make working copy of argument, Theoretically you must be able 1802145510Sdarrenr * to write to optarg, but that seems very ugly to me.... 1803145510Sdarrenr */ 1804145510Sdarrenr s = strdup(argument); 1805145510Sdarrenr if (s == NULL) 1806145510Sdarrenr return; 1807145510Sdarrenr 1808145510Sdarrenr /* get port */ 1809145510Sdarrenr if ((comma = strchr(s, ',')) != NULL) { 1810145510Sdarrenr if (!strcasecmp(comma + 1, "any")) { 1811145510Sdarrenr *port = -1; 1812145510Sdarrenr } else if (!sscanf(comma + 1, "%d", port) || 1813145510Sdarrenr (*port < 0) || (*port > 65535)) { 1814171017Sdarrenr fprintf(stderr, "Invalid port specification in %s\n", 1815145510Sdarrenr argument); 1816145510Sdarrenr free(s); 1817145510Sdarrenr exit(-2); 1818145510Sdarrenr } 1819145510Sdarrenr *comma = '\0'; 1820145510Sdarrenr } 1821145510Sdarrenr 1822145510Sdarrenr 1823145510Sdarrenr /* get ip address */ 1824145510Sdarrenr if (!strcasecmp(s, "any")) { 1825145510Sdarrenr ip->in4.s_addr = INADDR_ANY; 1826171017Sdarrenr ok = 1; 1827145510Sdarrenr#ifdef USE_INET6 1828145510Sdarrenr ip->in6 = in6addr_any; 1829145510Sdarrenr } else if (use_inet6 && inet_pton(AF_INET6, s, &ip->in6)) { 1830145510Sdarrenr ok = 1; 1831145510Sdarrenr#endif 1832145510Sdarrenr } else if (inet_aton(s, &ip->in4)) 1833145510Sdarrenr ok = 1; 1834145510Sdarrenr 1835145510Sdarrenr if (ok == 0) { 1836145510Sdarrenr fprintf(stderr, "Invalid IP address: %s\n", s); 1837145510Sdarrenr free(s); 1838145510Sdarrenr exit(-2); 1839145510Sdarrenr } 1840145510Sdarrenr 1841145510Sdarrenr /* free allocated memory */ 1842145510Sdarrenr free(s); 1843145510Sdarrenr} 1844145510Sdarrenr 1845145510Sdarrenr 1846145510Sdarrenr#ifdef STATETOP 1847145510Sdarrenrstatic void sig_resize(s) 1848145510Sdarrenrint s; 1849145510Sdarrenr{ 1850145510Sdarrenr handle_resize = 1; 1851145510Sdarrenr} 1852145510Sdarrenr 1853145510Sdarrenrstatic void sig_break(s) 1854145510Sdarrenrint s; 1855145510Sdarrenr{ 1856145510Sdarrenr handle_break = 1; 1857145510Sdarrenr} 1858145510Sdarrenr 1859145510Sdarrenrstatic char *getip(v, addr) 1860145510Sdarrenrint v; 1861145510Sdarrenri6addr_t *addr; 1862145510Sdarrenr{ 1863153881Sguido#ifdef USE_INET6 1864145510Sdarrenr static char hostbuf[MAXHOSTNAMELEN+1]; 1865153881Sguido#endif 1866145510Sdarrenr 1867145510Sdarrenr if (v == 4) 1868145510Sdarrenr return inet_ntoa(addr->in4); 1869145510Sdarrenr 1870145510Sdarrenr#ifdef USE_INET6 1871145510Sdarrenr (void) inet_ntop(AF_INET6, &addr->in6, hostbuf, sizeof(hostbuf) - 1); 1872145510Sdarrenr hostbuf[MAXHOSTNAMELEN] = '\0'; 1873145510Sdarrenr return hostbuf; 1874145510Sdarrenr#else 1875145510Sdarrenr return "IPv6"; 1876145510Sdarrenr#endif 1877145510Sdarrenr} 1878145510Sdarrenr 1879145510Sdarrenr 1880145510Sdarrenrstatic char *ttl_to_string(ttl) 1881145510Sdarrenrlong int ttl; 1882145510Sdarrenr{ 1883145510Sdarrenr static char ttlbuf[STSTRSIZE]; 1884145510Sdarrenr int hours, minutes, seconds; 1885145510Sdarrenr 1886145510Sdarrenr /* ttl is in half seconds */ 1887145510Sdarrenr ttl /= 2; 1888145510Sdarrenr 1889145510Sdarrenr hours = ttl / 3600; 1890145510Sdarrenr ttl = ttl % 3600; 1891145510Sdarrenr minutes = ttl / 60; 1892145510Sdarrenr seconds = ttl % 60; 1893145510Sdarrenr 1894145510Sdarrenr if (hours > 0) 1895145510Sdarrenr sprintf(ttlbuf, "%2d:%02d:%02d", hours, minutes, seconds); 1896145510Sdarrenr else 1897145510Sdarrenr sprintf(ttlbuf, "%2d:%02d", minutes, seconds); 1898145510Sdarrenr return ttlbuf; 1899145510Sdarrenr} 1900145510Sdarrenr 1901145510Sdarrenr 1902145510Sdarrenrstatic int sort_pkts(a, b) 1903145510Sdarrenrconst void *a; 1904145510Sdarrenrconst void *b; 1905145510Sdarrenr{ 1906145510Sdarrenr 1907145510Sdarrenr register const statetop_t *ap = a; 1908145510Sdarrenr register const statetop_t *bp = b; 1909145510Sdarrenr 1910145510Sdarrenr if (ap->st_pkts == bp->st_pkts) 1911145510Sdarrenr return 0; 1912145510Sdarrenr else if (ap->st_pkts < bp->st_pkts) 1913145510Sdarrenr return 1; 1914145510Sdarrenr return -1; 1915145510Sdarrenr} 1916145510Sdarrenr 1917145510Sdarrenr 1918145510Sdarrenrstatic int sort_bytes(a, b) 1919145510Sdarrenrconst void *a; 1920145510Sdarrenrconst void *b; 1921145510Sdarrenr{ 1922145510Sdarrenr register const statetop_t *ap = a; 1923145510Sdarrenr register const statetop_t *bp = b; 1924145510Sdarrenr 1925145510Sdarrenr if (ap->st_bytes == bp->st_bytes) 1926145510Sdarrenr return 0; 1927145510Sdarrenr else if (ap->st_bytes < bp->st_bytes) 1928145510Sdarrenr return 1; 1929145510Sdarrenr return -1; 1930145510Sdarrenr} 1931145510Sdarrenr 1932145510Sdarrenr 1933145510Sdarrenrstatic int sort_p(a, b) 1934145510Sdarrenrconst void *a; 1935145510Sdarrenrconst void *b; 1936145510Sdarrenr{ 1937145510Sdarrenr register const statetop_t *ap = a; 1938145510Sdarrenr register const statetop_t *bp = b; 1939145510Sdarrenr 1940145510Sdarrenr if (ap->st_p == bp->st_p) 1941145510Sdarrenr return 0; 1942145510Sdarrenr else if (ap->st_p < bp->st_p) 1943145510Sdarrenr return 1; 1944145510Sdarrenr return -1; 1945145510Sdarrenr} 1946145510Sdarrenr 1947145510Sdarrenr 1948145510Sdarrenrstatic int sort_ttl(a, b) 1949145510Sdarrenrconst void *a; 1950145510Sdarrenrconst void *b; 1951145510Sdarrenr{ 1952145510Sdarrenr register const statetop_t *ap = a; 1953145510Sdarrenr register const statetop_t *bp = b; 1954145510Sdarrenr 1955145510Sdarrenr if (ap->st_age == bp->st_age) 1956145510Sdarrenr return 0; 1957145510Sdarrenr else if (ap->st_age < bp->st_age) 1958145510Sdarrenr return 1; 1959145510Sdarrenr return -1; 1960145510Sdarrenr} 1961145510Sdarrenr 1962145510Sdarrenrstatic int sort_srcip(a, b) 1963145510Sdarrenrconst void *a; 1964145510Sdarrenrconst void *b; 1965145510Sdarrenr{ 1966145510Sdarrenr register const statetop_t *ap = a; 1967145510Sdarrenr register const statetop_t *bp = b; 1968145510Sdarrenr 1969145510Sdarrenr#ifdef USE_INET6 1970145510Sdarrenr if (use_inet6) { 1971145510Sdarrenr if (IP6_EQ(&ap->st_src, &bp->st_src)) 1972145510Sdarrenr return 0; 1973145510Sdarrenr else if (IP6_GT(&ap->st_src, &bp->st_src)) 1974145510Sdarrenr return 1; 1975145510Sdarrenr } else 1976145510Sdarrenr#endif 1977145510Sdarrenr { 1978145510Sdarrenr if (ntohl(ap->st_src.in4.s_addr) == 1979145510Sdarrenr ntohl(bp->st_src.in4.s_addr)) 1980145510Sdarrenr return 0; 1981145510Sdarrenr else if (ntohl(ap->st_src.in4.s_addr) > 1982145510Sdarrenr ntohl(bp->st_src.in4.s_addr)) 1983145510Sdarrenr return 1; 1984145510Sdarrenr } 1985145510Sdarrenr return -1; 1986145510Sdarrenr} 1987145510Sdarrenr 1988145510Sdarrenrstatic int sort_srcpt(a, b) 1989145510Sdarrenrconst void *a; 1990145510Sdarrenrconst void *b; 1991145510Sdarrenr{ 1992145510Sdarrenr register const statetop_t *ap = a; 1993145510Sdarrenr register const statetop_t *bp = b; 1994145510Sdarrenr 1995145510Sdarrenr if (htons(ap->st_sport) == htons(bp->st_sport)) 1996145510Sdarrenr return 0; 1997145510Sdarrenr else if (htons(ap->st_sport) > htons(bp->st_sport)) 1998145510Sdarrenr return 1; 1999145510Sdarrenr return -1; 2000145510Sdarrenr} 2001145510Sdarrenr 2002145510Sdarrenrstatic int sort_dstip(a, b) 2003145510Sdarrenrconst void *a; 2004145510Sdarrenrconst void *b; 2005145510Sdarrenr{ 2006145510Sdarrenr register const statetop_t *ap = a; 2007145510Sdarrenr register const statetop_t *bp = b; 2008145510Sdarrenr 2009145510Sdarrenr#ifdef USE_INET6 2010145510Sdarrenr if (use_inet6) { 2011145510Sdarrenr if (IP6_EQ(&ap->st_dst, &bp->st_dst)) 2012145510Sdarrenr return 0; 2013145510Sdarrenr else if (IP6_GT(&ap->st_dst, &bp->st_dst)) 2014145510Sdarrenr return 1; 2015145510Sdarrenr } else 2016145510Sdarrenr#endif 2017145510Sdarrenr { 2018145510Sdarrenr if (ntohl(ap->st_dst.in4.s_addr) == 2019145510Sdarrenr ntohl(bp->st_dst.in4.s_addr)) 2020145510Sdarrenr return 0; 2021145510Sdarrenr else if (ntohl(ap->st_dst.in4.s_addr) > 2022145510Sdarrenr ntohl(bp->st_dst.in4.s_addr)) 2023145510Sdarrenr return 1; 2024145510Sdarrenr } 2025145510Sdarrenr return -1; 2026145510Sdarrenr} 2027145510Sdarrenr 2028145510Sdarrenrstatic int sort_dstpt(a, b) 2029145510Sdarrenrconst void *a; 2030145510Sdarrenrconst void *b; 2031145510Sdarrenr{ 2032145510Sdarrenr register const statetop_t *ap = a; 2033145510Sdarrenr register const statetop_t *bp = b; 2034145510Sdarrenr 2035145510Sdarrenr if (htons(ap->st_dport) == htons(bp->st_dport)) 2036145510Sdarrenr return 0; 2037145510Sdarrenr else if (htons(ap->st_dport) > htons(bp->st_dport)) 2038145510Sdarrenr return 1; 2039145510Sdarrenr return -1; 2040145510Sdarrenr} 2041145510Sdarrenr 2042145510Sdarrenr#endif 2043170268Sdarrenr 2044170268Sdarrenr 2045170268Sdarrenripstate_t *fetchstate(src, dst) 2046170268Sdarrenripstate_t *src, *dst; 2047170268Sdarrenr{ 2048170268Sdarrenr int i; 2049170268Sdarrenr 2050170268Sdarrenr if (live_kernel == 1) { 2051170268Sdarrenr ipfgeniter_t state; 2052170268Sdarrenr ipfobj_t obj; 2053170268Sdarrenr 2054170268Sdarrenr obj.ipfo_rev = IPFILTER_VERSION; 2055170268Sdarrenr obj.ipfo_type = IPFOBJ_GENITER; 2056170268Sdarrenr obj.ipfo_size = sizeof(state); 2057170268Sdarrenr obj.ipfo_ptr = &state; 2058170268Sdarrenr 2059170268Sdarrenr state.igi_type = IPFGENITER_STATE; 2060170268Sdarrenr state.igi_nitems = 1; 2061170268Sdarrenr state.igi_data = dst; 2062170268Sdarrenr 2063170268Sdarrenr if (ioctl(state_fd, SIOCGENITER, &obj) != 0) 2064170268Sdarrenr return NULL; 2065170268Sdarrenr if (dst->is_next == NULL) { 2066170268Sdarrenr i = IPFGENITER_STATE; 2067170268Sdarrenr ioctl(state_fd, SIOCIPFDELTOK, &i); 2068170268Sdarrenr } 2069170268Sdarrenr } else { 2070170268Sdarrenr if (kmemcpy((char *)dst, (u_long)src, sizeof(*dst))) 2071170268Sdarrenr return NULL; 2072170268Sdarrenr } 2073170268Sdarrenr return dst; 2074170268Sdarrenr} 2075170268Sdarrenr 2076170268Sdarrenr 2077170268Sdarrenrstatic int fetchfrag(fd, type, frp) 2078170268Sdarrenrint fd, type; 2079170268Sdarrenripfr_t *frp; 2080170268Sdarrenr{ 2081170268Sdarrenr ipfgeniter_t frag; 2082170268Sdarrenr ipfobj_t obj; 2083170268Sdarrenr 2084170268Sdarrenr obj.ipfo_rev = IPFILTER_VERSION; 2085170268Sdarrenr obj.ipfo_type = IPFOBJ_GENITER; 2086170268Sdarrenr obj.ipfo_size = sizeof(frag); 2087170268Sdarrenr obj.ipfo_ptr = &frag; 2088170268Sdarrenr 2089170268Sdarrenr frag.igi_type = type; 2090170268Sdarrenr frag.igi_nitems = 1; 2091170268Sdarrenr frag.igi_data = frp; 2092170268Sdarrenr 2093170268Sdarrenr if (ioctl(fd, SIOCGENITER, &obj)) 2094170268Sdarrenr return EFAULT; 2095170268Sdarrenr return 0; 2096170268Sdarrenr} 2097170268Sdarrenr 2098170268Sdarrenr 2099170268Sdarrenrstatic void showtqtable_live(fd) 2100170268Sdarrenrint fd; 2101170268Sdarrenr{ 2102170268Sdarrenr ipftq_t table[IPF_TCP_NSTATES]; 2103170268Sdarrenr ipfobj_t obj; 2104170268Sdarrenr 2105170268Sdarrenr bzero((char *)&obj, sizeof(obj)); 2106170268Sdarrenr obj.ipfo_rev = IPFILTER_VERSION; 2107170268Sdarrenr obj.ipfo_size = sizeof(table); 2108170268Sdarrenr obj.ipfo_ptr = (void *)table; 2109170268Sdarrenr obj.ipfo_type = IPFOBJ_STATETQTAB; 2110170268Sdarrenr 2111170268Sdarrenr if (ioctl(fd, SIOCGTQTAB, &obj) == 0) { 2112170268Sdarrenr printtqtable(table); 2113170268Sdarrenr } 2114170268Sdarrenr} 2115