ipfstat.c revision 145510
1145510Sdarrenr/* $NetBSD$ */ 2145510Sdarrenr 3145510Sdarrenr/* 4145510Sdarrenr * Copyright (C) 1993-2001, 2003 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> 56145510Sdarrenr# if SOLARIS || defined(__NetBSD__) || defined(_BSDI_VERSION) || \ 57145510Sdarrenr defined(__sgi) 58145510Sdarrenr# ifdef ERR 59145510Sdarrenr# undef ERR 60145510Sdarrenr# endif 61145510Sdarrenr# include <curses.h> 62145510Sdarrenr# else /* SOLARIS */ 63145510Sdarrenr# include <ncurses.h> 64145510Sdarrenr# endif /* SOLARIS */ 65145510Sdarrenr#endif /* STATETOP */ 66145510Sdarrenr#include "kmem.h" 67145510Sdarrenr#if defined(__NetBSD__) || (__OpenBSD__) 68145510Sdarrenr# include <paths.h> 69145510Sdarrenr#endif 70145510Sdarrenr 71145510Sdarrenr#if !defined(lint) 72145510Sdarrenrstatic const char sccsid[] = "@(#)fils.c 1.21 4/20/96 (C) 1993-2000 Darren Reed"; 73145510Sdarrenrstatic const char rcsid[] = "@(#)Id: ipfstat.c,v 1.44.2.11 2005/03/30 14:09:57 darrenr Exp"; 74145510Sdarrenr#endif 75145510Sdarrenr 76145510Sdarrenr#ifdef __hpux 77145510Sdarrenr# define nlist nlist64 78145510Sdarrenr#endif 79145510Sdarrenr 80145510Sdarrenrextern char *optarg; 81145510Sdarrenrextern int optind; 82145510Sdarrenrextern int opterr; 83145510Sdarrenr 84145510Sdarrenr#define PRINTF (void)printf 85145510Sdarrenr#define FPRINTF (void)fprintf 86145510Sdarrenr#define F_IN 0 87145510Sdarrenr#define F_OUT 1 88145510Sdarrenr#define F_ACIN 2 89145510Sdarrenr#define F_ACOUT 3 90145510Sdarrenrstatic char *filters[4] = { "ipfilter(in)", "ipfilter(out)", 91145510Sdarrenr "ipacct(in)", "ipacct(out)" }; 92145510Sdarrenrstatic int state_logging = -1; 93145510Sdarrenr 94145510Sdarrenrint opts = 0; 95145510Sdarrenrint use_inet6 = 0; 96145510Sdarrenrint live_kernel = 1; 97145510Sdarrenrint state_fd = -1; 98145510Sdarrenrint ipf_fd = -1; 99145510Sdarrenr 100145510Sdarrenr#ifdef STATETOP 101145510Sdarrenr#define STSTRSIZE 80 102145510Sdarrenr#define STGROWSIZE 16 103145510Sdarrenr#define HOSTNMLEN 40 104145510Sdarrenr 105145510Sdarrenr#define STSORT_PR 0 106145510Sdarrenr#define STSORT_PKTS 1 107145510Sdarrenr#define STSORT_BYTES 2 108145510Sdarrenr#define STSORT_TTL 3 109145510Sdarrenr#define STSORT_SRCIP 4 110145510Sdarrenr#define STSORT_SRCPT 5 111145510Sdarrenr#define STSORT_DSTIP 6 112145510Sdarrenr#define STSORT_DSTPT 7 113145510Sdarrenr#define STSORT_MAX STSORT_DSTPT 114145510Sdarrenr#define STSORT_DEFAULT STSORT_BYTES 115145510Sdarrenr 116145510Sdarrenr 117145510Sdarrenrtypedef struct statetop { 118145510Sdarrenr i6addr_t st_src; 119145510Sdarrenr i6addr_t st_dst; 120145510Sdarrenr u_short st_sport; 121145510Sdarrenr u_short st_dport; 122145510Sdarrenr u_char st_p; 123145510Sdarrenr u_char st_v; 124145510Sdarrenr u_char st_state[2]; 125145510Sdarrenr U_QUAD_T st_pkts; 126145510Sdarrenr U_QUAD_T st_bytes; 127145510Sdarrenr u_long st_age; 128145510Sdarrenr} statetop_t; 129145510Sdarrenr#endif 130145510Sdarrenr 131145510Sdarrenrint main __P((int, char *[])); 132145510Sdarrenr 133145510Sdarrenrstatic void showstats __P((friostat_t *, u_32_t)); 134145510Sdarrenrstatic void showfrstates __P((ipfrstat_t *)); 135145510Sdarrenrstatic void showlist __P((friostat_t *)); 136145510Sdarrenrstatic void showipstates __P((ips_stat_t *)); 137145510Sdarrenrstatic void showauthstates __P((fr_authstat_t *)); 138145510Sdarrenrstatic void showgroups __P((friostat_t *)); 139145510Sdarrenrstatic void usage __P((char *)); 140145510Sdarrenrstatic void printlist __P((frentry_t *, char *)); 141145510Sdarrenrstatic void parse_ipportstr __P((const char *, i6addr_t *, int *)); 142145510Sdarrenrstatic void ipfstate_live __P((char *, friostat_t **, ips_stat_t **, 143145510Sdarrenr ipfrstat_t **, fr_authstat_t **, u_32_t *)); 144145510Sdarrenrstatic void ipfstate_dead __P((char *, friostat_t **, ips_stat_t **, 145145510Sdarrenr ipfrstat_t **, fr_authstat_t **, u_32_t *)); 146145510Sdarrenr#ifdef STATETOP 147145510Sdarrenrstatic void topipstates __P((i6addr_t, i6addr_t, int, int, int, 148145510Sdarrenr int, int, int)); 149145510Sdarrenrstatic void sig_break __P((int)); 150145510Sdarrenrstatic void sig_resize __P((int)); 151145510Sdarrenrstatic char *getip __P((int, i6addr_t *)); 152145510Sdarrenrstatic char *ttl_to_string __P((long)); 153145510Sdarrenrstatic int sort_p __P((const void *, const void *)); 154145510Sdarrenrstatic int sort_pkts __P((const void *, const void *)); 155145510Sdarrenrstatic int sort_bytes __P((const void *, const void *)); 156145510Sdarrenrstatic int sort_ttl __P((const void *, const void *)); 157145510Sdarrenrstatic int sort_srcip __P((const void *, const void *)); 158145510Sdarrenrstatic int sort_srcpt __P((const void *, const void *)); 159145510Sdarrenrstatic int sort_dstip __P((const void *, const void *)); 160145510Sdarrenrstatic int sort_dstpt __P((const void *, const void *)); 161145510Sdarrenr#endif 162145510Sdarrenr 163145510Sdarrenr 164145510Sdarrenrstatic void usage(name) 165145510Sdarrenrchar *name; 166145510Sdarrenr{ 167145510Sdarrenr#ifdef USE_INET6 168145510Sdarrenr fprintf(stderr, "Usage: %s [-6aAdfghIilnoRsv]\n", name); 169145510Sdarrenr#else 170145510Sdarrenr fprintf(stderr, "Usage: %s [-aAdfghIilnoRsv]\n", name); 171145510Sdarrenr#endif 172145510Sdarrenr fprintf(stderr, " %s [-M corefile] [-N symbol-list]\n", name); 173145510Sdarrenr#ifdef USE_INET6 174145510Sdarrenr fprintf(stderr, " %s -t [-6C] ", name); 175145510Sdarrenr#else 176145510Sdarrenr fprintf(stderr, " %s -t [-C] ", name); 177145510Sdarrenr#endif 178145510Sdarrenr fprintf(stderr, "[-D destination address] [-P protocol] [-S source address] [-T refresh time]\n"); 179145510Sdarrenr exit(1); 180145510Sdarrenr} 181145510Sdarrenr 182145510Sdarrenr 183145510Sdarrenrint main(argc,argv) 184145510Sdarrenrint argc; 185145510Sdarrenrchar *argv[]; 186145510Sdarrenr{ 187145510Sdarrenr fr_authstat_t frauthst; 188145510Sdarrenr fr_authstat_t *frauthstp = &frauthst; 189145510Sdarrenr friostat_t fio; 190145510Sdarrenr friostat_t *fiop = &fio; 191145510Sdarrenr ips_stat_t ipsst; 192145510Sdarrenr ips_stat_t *ipsstp = &ipsst; 193145510Sdarrenr ipfrstat_t ifrst; 194145510Sdarrenr ipfrstat_t *ifrstp = &ifrst; 195145510Sdarrenr char *device = IPL_NAME, *memf = NULL; 196145510Sdarrenr char *options, *kern = NULL; 197145510Sdarrenr int c, myoptind; 198145510Sdarrenr 199145510Sdarrenr int protocol = -1; /* -1 = wild card for any protocol */ 200145510Sdarrenr int refreshtime = 1; /* default update time */ 201145510Sdarrenr int sport = -1; /* -1 = wild card for any source port */ 202145510Sdarrenr int dport = -1; /* -1 = wild card for any dest port */ 203145510Sdarrenr int topclosed = 0; /* do not show closed tcp sessions */ 204145510Sdarrenr i6addr_t saddr, daddr; 205145510Sdarrenr u_32_t frf; 206145510Sdarrenr 207145510Sdarrenr#ifdef USE_INET6 208145510Sdarrenr options = "6aACdfghIilnostvD:M:N:P:RS:T:"; 209145510Sdarrenr#else 210145510Sdarrenr options = "aACdfghIilnostvD:M:N:P:RS:T:"; 211145510Sdarrenr#endif 212145510Sdarrenr 213145510Sdarrenr saddr.in4.s_addr = INADDR_ANY; /* default any v4 source addr */ 214145510Sdarrenr daddr.in4.s_addr = INADDR_ANY; /* default any v4 dest addr */ 215145510Sdarrenr#ifdef USE_INET6 216145510Sdarrenr saddr.in6 = in6addr_any; /* default any v6 source addr */ 217145510Sdarrenr daddr.in6 = in6addr_any; /* default any v6 dest addr */ 218145510Sdarrenr#endif 219145510Sdarrenr 220145510Sdarrenr /* Don't warn about invalid flags when we run getopt for the 1st time */ 221145510Sdarrenr opterr = 0; 222145510Sdarrenr 223145510Sdarrenr /* 224145510Sdarrenr * Parse these two arguments now lest there be any buffer overflows 225145510Sdarrenr * in the parsing of the rest. 226145510Sdarrenr */ 227145510Sdarrenr myoptind = optind; 228145510Sdarrenr while ((c = getopt(argc, argv, options)) != -1) { 229145510Sdarrenr switch (c) 230145510Sdarrenr { 231145510Sdarrenr case 'M' : 232145510Sdarrenr memf = optarg; 233145510Sdarrenr live_kernel = 0; 234145510Sdarrenr break; 235145510Sdarrenr case 'N' : 236145510Sdarrenr kern = optarg; 237145510Sdarrenr live_kernel = 0; 238145510Sdarrenr break; 239145510Sdarrenr } 240145510Sdarrenr } 241145510Sdarrenr optind = myoptind; 242145510Sdarrenr 243145510Sdarrenr if (live_kernel == 1) { 244145510Sdarrenr if ((state_fd = open(IPSTATE_NAME, O_RDONLY)) == -1) { 245145510Sdarrenr perror("open(IPSTATE_NAME)"); 246145510Sdarrenr exit(-1); 247145510Sdarrenr } 248145510Sdarrenr if ((ipf_fd = open(device, O_RDONLY)) == -1) { 249145510Sdarrenr fprintf(stderr, "open(%s)", device); 250145510Sdarrenr perror(""); 251145510Sdarrenr exit(-1); 252145510Sdarrenr } 253145510Sdarrenr } 254145510Sdarrenr 255145510Sdarrenr if (kern != NULL || memf != NULL) { 256145510Sdarrenr (void)setgid(getgid()); 257145510Sdarrenr (void)setuid(getuid()); 258145510Sdarrenr } 259145510Sdarrenr 260145510Sdarrenr if (live_kernel == 1) 261145510Sdarrenr (void) checkrev(device); 262145510Sdarrenr if (openkmem(kern, memf) == -1) 263145510Sdarrenr exit(-1); 264145510Sdarrenr 265145510Sdarrenr (void)setgid(getgid()); 266145510Sdarrenr (void)setuid(getuid()); 267145510Sdarrenr 268145510Sdarrenr opterr = 1; 269145510Sdarrenr 270145510Sdarrenr while ((c = getopt(argc, argv, options)) != -1) 271145510Sdarrenr { 272145510Sdarrenr switch (c) 273145510Sdarrenr { 274145510Sdarrenr#ifdef USE_INET6 275145510Sdarrenr case '6' : 276145510Sdarrenr use_inet6 = 1; 277145510Sdarrenr break; 278145510Sdarrenr#endif 279145510Sdarrenr case 'a' : 280145510Sdarrenr opts |= OPT_ACCNT|OPT_SHOWLIST; 281145510Sdarrenr break; 282145510Sdarrenr case 'A' : 283145510Sdarrenr opts |= OPT_AUTHSTATS; 284145510Sdarrenr break; 285145510Sdarrenr case 'C' : 286145510Sdarrenr topclosed = 1; 287145510Sdarrenr break; 288145510Sdarrenr case 'd' : 289145510Sdarrenr opts |= OPT_DEBUG; 290145510Sdarrenr break; 291145510Sdarrenr case 'D' : 292145510Sdarrenr parse_ipportstr(optarg, &daddr, &dport); 293145510Sdarrenr break; 294145510Sdarrenr case 'f' : 295145510Sdarrenr opts |= OPT_FRSTATES; 296145510Sdarrenr break; 297145510Sdarrenr case 'g' : 298145510Sdarrenr opts |= OPT_GROUPS; 299145510Sdarrenr break; 300145510Sdarrenr case 'h' : 301145510Sdarrenr opts |= OPT_HITS; 302145510Sdarrenr break; 303145510Sdarrenr case 'i' : 304145510Sdarrenr opts |= OPT_INQUE|OPT_SHOWLIST; 305145510Sdarrenr break; 306145510Sdarrenr case 'I' : 307145510Sdarrenr opts |= OPT_INACTIVE; 308145510Sdarrenr break; 309145510Sdarrenr case 'l' : 310145510Sdarrenr opts |= OPT_SHOWLIST; 311145510Sdarrenr break; 312145510Sdarrenr case 'M' : 313145510Sdarrenr break; 314145510Sdarrenr case 'N' : 315145510Sdarrenr break; 316145510Sdarrenr case 'n' : 317145510Sdarrenr opts |= OPT_SHOWLINENO; 318145510Sdarrenr break; 319145510Sdarrenr case 'o' : 320145510Sdarrenr opts |= OPT_OUTQUE|OPT_SHOWLIST; 321145510Sdarrenr break; 322145510Sdarrenr case 'P' : 323145510Sdarrenr protocol = getproto(optarg); 324145510Sdarrenr if (protocol == -1) { 325145510Sdarrenr fprintf(stderr, "%s: Invalid protocol: %s\n", 326145510Sdarrenr argv[0], optarg); 327145510Sdarrenr exit(-2); 328145510Sdarrenr } 329145510Sdarrenr break; 330145510Sdarrenr case 'R' : 331145510Sdarrenr opts |= OPT_NORESOLVE; 332145510Sdarrenr break; 333145510Sdarrenr case 's' : 334145510Sdarrenr opts |= OPT_IPSTATES; 335145510Sdarrenr break; 336145510Sdarrenr case 'S' : 337145510Sdarrenr parse_ipportstr(optarg, &saddr, &sport); 338145510Sdarrenr break; 339145510Sdarrenr case 't' : 340145510Sdarrenr#ifdef STATETOP 341145510Sdarrenr opts |= OPT_STATETOP; 342145510Sdarrenr break; 343145510Sdarrenr#else 344145510Sdarrenr fprintf(stderr, 345145510Sdarrenr "%s: state top facility not compiled in\n", 346145510Sdarrenr argv[0]); 347145510Sdarrenr exit(-2); 348145510Sdarrenr#endif 349145510Sdarrenr case 'T' : 350145510Sdarrenr if (!sscanf(optarg, "%d", &refreshtime) || 351145510Sdarrenr (refreshtime <= 0)) { 352145510Sdarrenr fprintf(stderr, 353145510Sdarrenr "%s: Invalid refreshtime < 1 : %s\n", 354145510Sdarrenr argv[0], optarg); 355145510Sdarrenr exit(-2); 356145510Sdarrenr } 357145510Sdarrenr break; 358145510Sdarrenr case 'v' : 359145510Sdarrenr opts |= OPT_VERBOSE; 360145510Sdarrenr break; 361145510Sdarrenr default : 362145510Sdarrenr usage(argv[0]); 363145510Sdarrenr break; 364145510Sdarrenr } 365145510Sdarrenr } 366145510Sdarrenr 367145510Sdarrenr if (live_kernel == 1) { 368145510Sdarrenr bzero((char *)&fio, sizeof(fio)); 369145510Sdarrenr bzero((char *)&ipsst, sizeof(ipsst)); 370145510Sdarrenr bzero((char *)&ifrst, sizeof(ifrst)); 371145510Sdarrenr 372145510Sdarrenr ipfstate_live(device, &fiop, &ipsstp, &ifrstp, 373145510Sdarrenr &frauthstp, &frf); 374145510Sdarrenr } else 375145510Sdarrenr ipfstate_dead(kern, &fiop, &ipsstp, &ifrstp, &frauthstp, &frf); 376145510Sdarrenr 377145510Sdarrenr if (opts & OPT_IPSTATES) { 378145510Sdarrenr showipstates(ipsstp); 379145510Sdarrenr } else if (opts & OPT_SHOWLIST) { 380145510Sdarrenr showlist(fiop); 381145510Sdarrenr if ((opts & OPT_OUTQUE) && (opts & OPT_INQUE)){ 382145510Sdarrenr opts &= ~OPT_OUTQUE; 383145510Sdarrenr showlist(fiop); 384145510Sdarrenr } 385145510Sdarrenr } else if (opts & OPT_FRSTATES) 386145510Sdarrenr showfrstates(ifrstp); 387145510Sdarrenr#ifdef STATETOP 388145510Sdarrenr else if (opts & OPT_STATETOP) 389145510Sdarrenr topipstates(saddr, daddr, sport, dport, protocol, 390145510Sdarrenr use_inet6 ? 6 : 4, refreshtime, topclosed); 391145510Sdarrenr#endif 392145510Sdarrenr else if (opts & OPT_AUTHSTATS) 393145510Sdarrenr showauthstates(frauthstp); 394145510Sdarrenr else if (opts & OPT_GROUPS) 395145510Sdarrenr showgroups(fiop); 396145510Sdarrenr else 397145510Sdarrenr showstats(fiop, frf); 398145510Sdarrenr 399145510Sdarrenr return 0; 400145510Sdarrenr} 401145510Sdarrenr 402145510Sdarrenr 403145510Sdarrenr/* 404145510Sdarrenr * Fill in the stats structures from the live kernel, using a combination 405145510Sdarrenr * of ioctl's and copying directly from kernel memory. 406145510Sdarrenr */ 407145510Sdarrenrstatic void ipfstate_live(device, fiopp, ipsstpp, ifrstpp, frauthstpp, frfp) 408145510Sdarrenrchar *device; 409145510Sdarrenrfriostat_t **fiopp; 410145510Sdarrenrips_stat_t **ipsstpp; 411145510Sdarrenripfrstat_t **ifrstpp; 412145510Sdarrenrfr_authstat_t **frauthstpp; 413145510Sdarrenru_32_t *frfp; 414145510Sdarrenr{ 415145510Sdarrenr ipfobj_t ipfo; 416145510Sdarrenr 417145510Sdarrenr if (checkrev(device) == -1) { 418145510Sdarrenr fprintf(stderr, "User/kernel version check failed\n"); 419145510Sdarrenr exit(1); 420145510Sdarrenr } 421145510Sdarrenr 422145510Sdarrenr if ((opts & OPT_AUTHSTATS) == 0) { 423145510Sdarrenr bzero((caddr_t)&ipfo, sizeof(ipfo)); 424145510Sdarrenr ipfo.ipfo_rev = IPFILTER_VERSION; 425145510Sdarrenr ipfo.ipfo_size = sizeof(friostat_t); 426145510Sdarrenr ipfo.ipfo_ptr = (void *)*fiopp; 427145510Sdarrenr ipfo.ipfo_type = IPFOBJ_IPFSTAT; 428145510Sdarrenr 429145510Sdarrenr if (ioctl(ipf_fd, SIOCGETFS, &ipfo) == -1) { 430145510Sdarrenr perror("ioctl(ipf:SIOCGETFS)"); 431145510Sdarrenr exit(-1); 432145510Sdarrenr } 433145510Sdarrenr 434145510Sdarrenr if (ioctl(ipf_fd, SIOCGETFF, frfp) == -1) 435145510Sdarrenr perror("ioctl(SIOCGETFF)"); 436145510Sdarrenr } 437145510Sdarrenr 438145510Sdarrenr if ((opts & OPT_IPSTATES) != 0) { 439145510Sdarrenr 440145510Sdarrenr bzero((caddr_t)&ipfo, sizeof(ipfo)); 441145510Sdarrenr ipfo.ipfo_rev = IPFILTER_VERSION; 442145510Sdarrenr ipfo.ipfo_size = sizeof(ips_stat_t); 443145510Sdarrenr ipfo.ipfo_ptr = (void *)*ipsstpp; 444145510Sdarrenr ipfo.ipfo_type = IPFOBJ_STATESTAT; 445145510Sdarrenr 446145510Sdarrenr if ((ioctl(state_fd, SIOCGETFS, &ipfo) == -1)) { 447145510Sdarrenr perror("ioctl(state:SIOCGETFS)"); 448145510Sdarrenr exit(-1); 449145510Sdarrenr } 450145510Sdarrenr if (ioctl(state_fd, SIOCGETLG, &state_logging) == -1) { 451145510Sdarrenr perror("ioctl(state:SIOCGETLG)"); 452145510Sdarrenr exit(-1); 453145510Sdarrenr } 454145510Sdarrenr } 455145510Sdarrenr 456145510Sdarrenr if ((opts & OPT_FRSTATES) != 0) { 457145510Sdarrenr bzero((caddr_t)&ipfo, sizeof(ipfo)); 458145510Sdarrenr ipfo.ipfo_rev = IPFILTER_VERSION; 459145510Sdarrenr ipfo.ipfo_size = sizeof(ipfrstat_t); 460145510Sdarrenr ipfo.ipfo_ptr = (void *)*ifrstpp; 461145510Sdarrenr ipfo.ipfo_type = IPFOBJ_FRAGSTAT; 462145510Sdarrenr 463145510Sdarrenr if (ioctl(ipf_fd, SIOCGFRST, &ipfo) == -1) { 464145510Sdarrenr perror("ioctl(SIOCGFRST)"); 465145510Sdarrenr exit(-1); 466145510Sdarrenr } 467145510Sdarrenr } 468145510Sdarrenr 469145510Sdarrenr if (opts & OPT_VERBOSE) 470145510Sdarrenr PRINTF("opts %#x name %s\n", opts, device); 471145510Sdarrenr 472145510Sdarrenr if ((opts & OPT_AUTHSTATS) != 0) { 473145510Sdarrenr if (ipf_fd >= 0) { 474145510Sdarrenr close(ipf_fd); 475145510Sdarrenr ipf_fd = -1; 476145510Sdarrenr } 477145510Sdarrenr device = IPAUTH_NAME; 478145510Sdarrenr if ((ipf_fd = open(device, O_RDONLY)) == -1) { 479145510Sdarrenr perror("open"); 480145510Sdarrenr exit(-1); 481145510Sdarrenr } 482145510Sdarrenr 483145510Sdarrenr bzero((caddr_t)&ipfo, sizeof(ipfo)); 484145510Sdarrenr ipfo.ipfo_rev = IPFILTER_VERSION; 485145510Sdarrenr ipfo.ipfo_size = sizeof(fr_authstat_t); 486145510Sdarrenr ipfo.ipfo_ptr = (void *)*frauthstpp; 487145510Sdarrenr ipfo.ipfo_type = IPFOBJ_AUTHSTAT; 488145510Sdarrenr 489145510Sdarrenr if (ioctl(ipf_fd, SIOCATHST, &ipfo) == -1) { 490145510Sdarrenr perror("ioctl(SIOCATHST)"); 491145510Sdarrenr exit(-1); 492145510Sdarrenr } 493145510Sdarrenr } 494145510Sdarrenr} 495145510Sdarrenr 496145510Sdarrenr 497145510Sdarrenr/* 498145510Sdarrenr * Build up the stats structures from data held in the "core" memory. 499145510Sdarrenr * This is mainly useful when looking at data in crash dumps and ioctl's 500145510Sdarrenr * just won't work any more. 501145510Sdarrenr */ 502145510Sdarrenrstatic void ipfstate_dead(kernel, fiopp, ipsstpp, ifrstpp, frauthstpp, frfp) 503145510Sdarrenrchar *kernel; 504145510Sdarrenrfriostat_t **fiopp; 505145510Sdarrenrips_stat_t **ipsstpp; 506145510Sdarrenripfrstat_t **ifrstpp; 507145510Sdarrenrfr_authstat_t **frauthstpp; 508145510Sdarrenru_32_t *frfp; 509145510Sdarrenr{ 510145510Sdarrenr static fr_authstat_t frauthst, *frauthstp; 511145510Sdarrenr static ips_stat_t ipsst, *ipsstp; 512145510Sdarrenr static ipfrstat_t ifrst, *ifrstp; 513145510Sdarrenr static friostat_t fio, *fiop; 514145510Sdarrenr int temp; 515145510Sdarrenr 516145510Sdarrenr void *rules[2][2]; 517145510Sdarrenr struct nlist deadlist[43] = { 518145510Sdarrenr { "fr_authstats" }, /* 0 */ 519145510Sdarrenr { "fae_list" }, 520145510Sdarrenr { "ipauth" }, 521145510Sdarrenr { "fr_authlist" }, 522145510Sdarrenr { "fr_authstart" }, 523145510Sdarrenr { "fr_authend" }, /* 5 */ 524145510Sdarrenr { "fr_authnext" }, 525145510Sdarrenr { "fr_auth" }, 526145510Sdarrenr { "fr_authused" }, 527145510Sdarrenr { "fr_authsize" }, 528145510Sdarrenr { "fr_defaultauthage" }, /* 10 */ 529145510Sdarrenr { "fr_authpkts" }, 530145510Sdarrenr { "fr_auth_lock" }, 531145510Sdarrenr { "frstats" }, 532145510Sdarrenr { "ips_stats" }, 533145510Sdarrenr { "ips_num" }, /* 15 */ 534145510Sdarrenr { "ips_wild" }, 535145510Sdarrenr { "ips_list" }, 536145510Sdarrenr { "ips_table" }, 537145510Sdarrenr { "fr_statemax" }, 538145510Sdarrenr { "fr_statesize" }, /* 20 */ 539145510Sdarrenr { "fr_state_doflush" }, 540145510Sdarrenr { "fr_state_lock" }, 541145510Sdarrenr { "ipfr_heads" }, 542145510Sdarrenr { "ipfr_nattab" }, 543145510Sdarrenr { "ipfr_stats" }, /* 25 */ 544145510Sdarrenr { "ipfr_inuse" }, 545145510Sdarrenr { "fr_ipfrttl" }, 546145510Sdarrenr { "fr_frag_lock" }, 547145510Sdarrenr { "ipfr_timer_id" }, 548145510Sdarrenr { "fr_nat_lock" }, /* 30 */ 549145510Sdarrenr { "ipfilter" }, 550145510Sdarrenr { "ipfilter6" }, 551145510Sdarrenr { "ipacct" }, 552145510Sdarrenr { "ipacct6" }, 553145510Sdarrenr { "ipl_frouteok" }, /* 35 */ 554145510Sdarrenr { "fr_running" }, 555145510Sdarrenr { "ipfgroups" }, 556145510Sdarrenr { "fr_active" }, 557145510Sdarrenr { "fr_pass" }, 558145510Sdarrenr { "fr_flags" }, /* 40 */ 559145510Sdarrenr { "ipstate_logging" }, 560145510Sdarrenr { NULL } 561145510Sdarrenr }; 562145510Sdarrenr 563145510Sdarrenr 564145510Sdarrenr frauthstp = &frauthst; 565145510Sdarrenr ipsstp = &ipsst; 566145510Sdarrenr ifrstp = &ifrst; 567145510Sdarrenr fiop = &fio; 568145510Sdarrenr 569145510Sdarrenr *frfp = 0; 570145510Sdarrenr *fiopp = fiop; 571145510Sdarrenr *ipsstpp = ipsstp; 572145510Sdarrenr *ifrstpp = ifrstp; 573145510Sdarrenr *frauthstpp = frauthstp; 574145510Sdarrenr 575145510Sdarrenr bzero((char *)fiop, sizeof(*fiop)); 576145510Sdarrenr bzero((char *)ipsstp, sizeof(*ipsstp)); 577145510Sdarrenr bzero((char *)ifrstp, sizeof(*ifrstp)); 578145510Sdarrenr bzero((char *)frauthstp, sizeof(*frauthstp)); 579145510Sdarrenr 580145510Sdarrenr if (nlist(kernel, deadlist) == -1) { 581145510Sdarrenr fprintf(stderr, "nlist error\n"); 582145510Sdarrenr return; 583145510Sdarrenr } 584145510Sdarrenr 585145510Sdarrenr /* 586145510Sdarrenr * This is for SIOCGETFF. 587145510Sdarrenr */ 588145510Sdarrenr kmemcpy((char *)frfp, (u_long)deadlist[40].n_value, sizeof(*frfp)); 589145510Sdarrenr 590145510Sdarrenr /* 591145510Sdarrenr * f_locks is a combination of the lock variable from each part of 592145510Sdarrenr * ipfilter (state, auth, nat, fragments). 593145510Sdarrenr */ 594145510Sdarrenr kmemcpy((char *)fiop, (u_long)deadlist[13].n_value, sizeof(*fiop)); 595145510Sdarrenr kmemcpy((char *)&fiop->f_locks[0], (u_long)deadlist[22].n_value, 596145510Sdarrenr sizeof(fiop->f_locks[0])); 597145510Sdarrenr kmemcpy((char *)&fiop->f_locks[0], (u_long)deadlist[30].n_value, 598145510Sdarrenr sizeof(fiop->f_locks[1])); 599145510Sdarrenr kmemcpy((char *)&fiop->f_locks[2], (u_long)deadlist[28].n_value, 600145510Sdarrenr sizeof(fiop->f_locks[2])); 601145510Sdarrenr kmemcpy((char *)&fiop->f_locks[3], (u_long)deadlist[12].n_value, 602145510Sdarrenr sizeof(fiop->f_locks[3])); 603145510Sdarrenr 604145510Sdarrenr /* 605145510Sdarrenr * Get pointers to each list of rules (active, inactive, in, out) 606145510Sdarrenr */ 607145510Sdarrenr kmemcpy((char *)&rules, (u_long)deadlist[31].n_value, sizeof(rules)); 608145510Sdarrenr fiop->f_fin[0] = rules[0][0]; 609145510Sdarrenr fiop->f_fin[1] = rules[0][1]; 610145510Sdarrenr fiop->f_fout[0] = rules[1][0]; 611145510Sdarrenr fiop->f_fout[1] = rules[1][1]; 612145510Sdarrenr 613145510Sdarrenr /* 614145510Sdarrenr * Same for IPv6, except make them null if support for it is not 615145510Sdarrenr * being compiled in. 616145510Sdarrenr */ 617145510Sdarrenr#ifdef USE_INET6 618145510Sdarrenr kmemcpy((char *)&rules, (u_long)deadlist[32].n_value, sizeof(rules)); 619145510Sdarrenr fiop->f_fin6[0] = rules[0][0]; 620145510Sdarrenr fiop->f_fin6[1] = rules[0][1]; 621145510Sdarrenr fiop->f_fout6[0] = rules[1][0]; 622145510Sdarrenr fiop->f_fout6[1] = rules[1][1]; 623145510Sdarrenr#else 624145510Sdarrenr fiop->f_fin6[0] = NULL; 625145510Sdarrenr fiop->f_fin6[1] = NULL; 626145510Sdarrenr fiop->f_fout6[0] = NULL; 627145510Sdarrenr fiop->f_fout6[1] = NULL; 628145510Sdarrenr#endif 629145510Sdarrenr 630145510Sdarrenr /* 631145510Sdarrenr * Now get accounting rules pointers. 632145510Sdarrenr */ 633145510Sdarrenr kmemcpy((char *)&rules, (u_long)deadlist[33].n_value, sizeof(rules)); 634145510Sdarrenr fiop->f_acctin[0] = rules[0][0]; 635145510Sdarrenr fiop->f_acctin[1] = rules[0][1]; 636145510Sdarrenr fiop->f_acctout[0] = rules[1][0]; 637145510Sdarrenr fiop->f_acctout[1] = rules[1][1]; 638145510Sdarrenr 639145510Sdarrenr#ifdef USE_INET6 640145510Sdarrenr kmemcpy((char *)&rules, (u_long)deadlist[34].n_value, sizeof(rules)); 641145510Sdarrenr fiop->f_acctin6[0] = rules[0][0]; 642145510Sdarrenr fiop->f_acctin6[1] = rules[0][1]; 643145510Sdarrenr fiop->f_acctout6[0] = rules[1][0]; 644145510Sdarrenr fiop->f_acctout6[1] = rules[1][1]; 645145510Sdarrenr#else 646145510Sdarrenr fiop->f_acctin6[0] = NULL; 647145510Sdarrenr fiop->f_acctin6[1] = NULL; 648145510Sdarrenr fiop->f_acctout6[0] = NULL; 649145510Sdarrenr fiop->f_acctout6[1] = NULL; 650145510Sdarrenr#endif 651145510Sdarrenr 652145510Sdarrenr /* 653145510Sdarrenr * A collection of "global" variables used inside the kernel which 654145510Sdarrenr * are all collected in friostat_t via ioctl. 655145510Sdarrenr */ 656145510Sdarrenr kmemcpy((char *)&fiop->f_froute, (u_long)deadlist[35].n_value, 657145510Sdarrenr sizeof(fiop->f_froute)); 658145510Sdarrenr kmemcpy((char *)&fiop->f_running, (u_long)deadlist[36].n_value, 659145510Sdarrenr sizeof(fiop->f_running)); 660145510Sdarrenr kmemcpy((char *)&fiop->f_groups, (u_long)deadlist[37].n_value, 661145510Sdarrenr sizeof(fiop->f_groups)); 662145510Sdarrenr kmemcpy((char *)&fiop->f_active, (u_long)deadlist[38].n_value, 663145510Sdarrenr sizeof(fiop->f_active)); 664145510Sdarrenr kmemcpy((char *)&fiop->f_defpass, (u_long)deadlist[39].n_value, 665145510Sdarrenr sizeof(fiop->f_defpass)); 666145510Sdarrenr 667145510Sdarrenr /* 668145510Sdarrenr * Build up the state information stats structure. 669145510Sdarrenr */ 670145510Sdarrenr kmemcpy((char *)ipsstp, (u_long)deadlist[14].n_value, sizeof(*ipsstp)); 671145510Sdarrenr kmemcpy((char *)&temp, (u_long)deadlist[15].n_value, sizeof(temp)); 672145510Sdarrenr ipsstp->iss_active = temp; 673145510Sdarrenr ipsstp->iss_table = (void *)deadlist[18].n_value; 674145510Sdarrenr ipsstp->iss_list = (void *)deadlist[17].n_value; 675145510Sdarrenr 676145510Sdarrenr /* 677145510Sdarrenr * Build up the authentiation information stats structure. 678145510Sdarrenr */ 679145510Sdarrenr kmemcpy((char *)frauthstp, (u_long)deadlist[0].n_value, 680145510Sdarrenr sizeof(*frauthstp)); 681145510Sdarrenr frauthstp->fas_faelist = (void *)deadlist[1].n_value; 682145510Sdarrenr 683145510Sdarrenr /* 684145510Sdarrenr * Build up the fragment information stats structure. 685145510Sdarrenr */ 686145510Sdarrenr kmemcpy((char *)ifrstp, (u_long)deadlist[25].n_value, 687145510Sdarrenr sizeof(*ifrstp)); 688145510Sdarrenr ifrstp->ifs_table = (void *)deadlist[23].n_value; 689145510Sdarrenr ifrstp->ifs_nattab = (void *)deadlist[24].n_value; 690145510Sdarrenr kmemcpy((char *)&ifrstp->ifs_inuse, (u_long)deadlist[26].n_value, 691145510Sdarrenr sizeof(ifrstp->ifs_inuse)); 692145510Sdarrenr 693145510Sdarrenr /* 694145510Sdarrenr * Get logging on/off switches 695145510Sdarrenr */ 696145510Sdarrenr kmemcpy((char *)&state_logging, (u_long)deadlist[41].n_value, 697145510Sdarrenr sizeof(state_logging)); 698145510Sdarrenr} 699145510Sdarrenr 700145510Sdarrenr 701145510Sdarrenr/* 702145510Sdarrenr * Display the kernel stats for packets blocked and passed and other 703145510Sdarrenr * associated running totals which are kept. 704145510Sdarrenr */ 705145510Sdarrenrstatic void showstats(fp, frf) 706145510Sdarrenrstruct friostat *fp; 707145510Sdarrenru_32_t frf; 708145510Sdarrenr{ 709145510Sdarrenr 710145510Sdarrenr PRINTF("bad packets:\t\tin %lu\tout %lu\n", 711145510Sdarrenr fp->f_st[0].fr_bad, fp->f_st[1].fr_bad); 712145510Sdarrenr#ifdef USE_INET6 713145510Sdarrenr PRINTF(" IPv6 packets:\t\tin %lu out %lu\n", 714145510Sdarrenr fp->f_st[0].fr_ipv6, fp->f_st[1].fr_ipv6); 715145510Sdarrenr#endif 716145510Sdarrenr PRINTF(" input packets:\t\tblocked %lu passed %lu nomatch %lu", 717145510Sdarrenr fp->f_st[0].fr_block, fp->f_st[0].fr_pass, 718145510Sdarrenr fp->f_st[0].fr_nom); 719145510Sdarrenr PRINTF(" counted %lu short %lu\n", 720145510Sdarrenr fp->f_st[0].fr_acct, fp->f_st[0].fr_short); 721145510Sdarrenr PRINTF("output packets:\t\tblocked %lu passed %lu nomatch %lu", 722145510Sdarrenr fp->f_st[1].fr_block, fp->f_st[1].fr_pass, 723145510Sdarrenr fp->f_st[1].fr_nom); 724145510Sdarrenr PRINTF(" counted %lu short %lu\n", 725145510Sdarrenr fp->f_st[1].fr_acct, fp->f_st[1].fr_short); 726145510Sdarrenr PRINTF(" input packets logged:\tblocked %lu passed %lu\n", 727145510Sdarrenr fp->f_st[0].fr_bpkl, fp->f_st[0].fr_ppkl); 728145510Sdarrenr PRINTF("output packets logged:\tblocked %lu passed %lu\n", 729145510Sdarrenr fp->f_st[1].fr_bpkl, fp->f_st[1].fr_ppkl); 730145510Sdarrenr PRINTF(" packets logged:\tinput %lu output %lu\n", 731145510Sdarrenr fp->f_st[0].fr_pkl, fp->f_st[1].fr_pkl); 732145510Sdarrenr PRINTF(" log failures:\t\tinput %lu output %lu\n", 733145510Sdarrenr fp->f_st[0].fr_skip, fp->f_st[1].fr_skip); 734145510Sdarrenr PRINTF("fragment state(in):\tkept %lu\tlost %lu\tnot fragmented %lu\n", 735145510Sdarrenr fp->f_st[0].fr_nfr, fp->f_st[0].fr_bnfr, 736145510Sdarrenr fp->f_st[0].fr_cfr); 737145510Sdarrenr PRINTF("fragment state(out):\tkept %lu\tlost %lu\tnot fragmented %lu\n", 738145510Sdarrenr fp->f_st[1].fr_nfr, fp->f_st[1].fr_bnfr, 739145510Sdarrenr fp->f_st[0].fr_cfr); 740145510Sdarrenr PRINTF("packet state(in):\tkept %lu\tlost %lu\n", 741145510Sdarrenr fp->f_st[0].fr_ads, fp->f_st[0].fr_bads); 742145510Sdarrenr PRINTF("packet state(out):\tkept %lu\tlost %lu\n", 743145510Sdarrenr fp->f_st[1].fr_ads, fp->f_st[1].fr_bads); 744145510Sdarrenr PRINTF("ICMP replies:\t%lu\tTCP RSTs sent:\t%lu\n", 745145510Sdarrenr fp->f_st[0].fr_ret, fp->f_st[1].fr_ret); 746145510Sdarrenr PRINTF("Invalid source(in):\t%lu\n", fp->f_st[0].fr_badsrc); 747145510Sdarrenr PRINTF("Result cache hits(in):\t%lu\t(out):\t%lu\n", 748145510Sdarrenr fp->f_st[0].fr_chit, fp->f_st[1].fr_chit); 749145510Sdarrenr PRINTF("IN Pullups succeeded:\t%lu\tfailed:\t%lu\n", 750145510Sdarrenr fp->f_st[0].fr_pull[0], fp->f_st[0].fr_pull[1]); 751145510Sdarrenr PRINTF("OUT Pullups succeeded:\t%lu\tfailed:\t%lu\n", 752145510Sdarrenr fp->f_st[1].fr_pull[0], fp->f_st[1].fr_pull[1]); 753145510Sdarrenr PRINTF("Fastroute successes:\t%lu\tfailures:\t%lu\n", 754145510Sdarrenr fp->f_froute[0], fp->f_froute[1]); 755145510Sdarrenr PRINTF("TCP cksum fails(in):\t%lu\t(out):\t%lu\n", 756145510Sdarrenr fp->f_st[0].fr_tcpbad, fp->f_st[1].fr_tcpbad); 757145510Sdarrenr PRINTF("IPF Ticks:\t%lu\n", fp->f_ticks); 758145510Sdarrenr 759145510Sdarrenr PRINTF("Packet log flags set: (%#x)\n", frf); 760145510Sdarrenr if (frf & FF_LOGPASS) 761145510Sdarrenr PRINTF("\tpackets passed through filter\n"); 762145510Sdarrenr if (frf & FF_LOGBLOCK) 763145510Sdarrenr PRINTF("\tpackets blocked by filter\n"); 764145510Sdarrenr if (frf & FF_LOGNOMATCH) 765145510Sdarrenr PRINTF("\tpackets not matched by filter\n"); 766145510Sdarrenr if (!frf) 767145510Sdarrenr PRINTF("\tnone\n"); 768145510Sdarrenr} 769145510Sdarrenr 770145510Sdarrenr 771145510Sdarrenr/* 772145510Sdarrenr * Print out a list of rules from the kernel, starting at the one passed. 773145510Sdarrenr */ 774145510Sdarrenrstatic void printlist(fp, comment) 775145510Sdarrenrfrentry_t *fp; 776145510Sdarrenrchar *comment; 777145510Sdarrenr{ 778145510Sdarrenr struct frentry fb, *fg; 779145510Sdarrenr char *data; 780145510Sdarrenr u_32_t type; 781145510Sdarrenr int n; 782145510Sdarrenr 783145510Sdarrenr for (n = 1; fp; n++) { 784145510Sdarrenr if (kmemcpy((char *)&fb, (u_long)fp, sizeof(fb)) == -1) { 785145510Sdarrenr perror("kmemcpy"); 786145510Sdarrenr return; 787145510Sdarrenr } 788145510Sdarrenr fp = &fb; 789145510Sdarrenr if (opts & (OPT_HITS|OPT_VERBOSE)) 790145510Sdarrenr#ifdef USE_QUAD_T 791145510Sdarrenr PRINTF("%qu ", (unsigned long long) fp->fr_hits); 792145510Sdarrenr#else 793145510Sdarrenr PRINTF("%lu ", fp->fr_hits); 794145510Sdarrenr#endif 795145510Sdarrenr if (opts & (OPT_ACCNT|OPT_VERBOSE)) 796145510Sdarrenr#ifdef USE_QUAD_T 797145510Sdarrenr PRINTF("%qu ", (unsigned long long) fp->fr_bytes); 798145510Sdarrenr#else 799145510Sdarrenr PRINTF("%lu ", fp->fr_bytes); 800145510Sdarrenr#endif 801145510Sdarrenr if (opts & OPT_SHOWLINENO) 802145510Sdarrenr PRINTF("@%d ", n); 803145510Sdarrenr data = NULL; 804145510Sdarrenr type = fp->fr_type & ~FR_T_BUILTIN; 805145510Sdarrenr if (type == FR_T_IPF || type == FR_T_BPFOPC) { 806145510Sdarrenr if (fp->fr_dsize) { 807145510Sdarrenr data = malloc(fp->fr_dsize); 808145510Sdarrenr 809145510Sdarrenr if (kmemcpy(data, (u_long)fp->fr_data, 810145510Sdarrenr fp->fr_dsize) == -1) { 811145510Sdarrenr perror("kmemcpy"); 812145510Sdarrenr return; 813145510Sdarrenr } 814145510Sdarrenr fp->fr_data = data; 815145510Sdarrenr } 816145510Sdarrenr } 817145510Sdarrenr 818145510Sdarrenr printfr(fp, ioctl); 819145510Sdarrenr if (opts & OPT_DEBUG) { 820145510Sdarrenr binprint(fp, sizeof(*fp)); 821145510Sdarrenr if (fp->fr_data != NULL && fp->fr_dsize > 0) 822145510Sdarrenr binprint(fp->fr_data, fp->fr_dsize); 823145510Sdarrenr } 824145510Sdarrenr if (data != NULL) 825145510Sdarrenr free(data); 826145510Sdarrenr if (fp->fr_grp != NULL) { 827145510Sdarrenr if (!kmemcpy((char *)&fg, (u_long)fp->fr_grp, 828145510Sdarrenr sizeof(fg))) 829145510Sdarrenr printlist(fg, comment); 830145510Sdarrenr } 831145510Sdarrenr if (type == FR_T_CALLFUNC) { 832145510Sdarrenr printlist(fp->fr_data, "# callfunc: "); 833145510Sdarrenr } 834145510Sdarrenr fp = fp->fr_next; 835145510Sdarrenr } 836145510Sdarrenr} 837145510Sdarrenr 838145510Sdarrenr/* 839145510Sdarrenr * print out all of the asked for rule sets, using the stats struct as 840145510Sdarrenr * the base from which to get the pointers. 841145510Sdarrenr */ 842145510Sdarrenrstatic void showlist(fiop) 843145510Sdarrenrstruct friostat *fiop; 844145510Sdarrenr{ 845145510Sdarrenr struct frentry *fp = NULL; 846145510Sdarrenr int i, set; 847145510Sdarrenr 848145510Sdarrenr set = fiop->f_active; 849145510Sdarrenr if (opts & OPT_INACTIVE) 850145510Sdarrenr set = 1 - set; 851145510Sdarrenr if (opts & OPT_ACCNT) { 852145510Sdarrenr#ifdef USE_INET6 853145510Sdarrenr if ((use_inet6) && (opts & OPT_OUTQUE)) { 854145510Sdarrenr i = F_ACOUT; 855145510Sdarrenr fp = (struct frentry *)fiop->f_acctout6[set]; 856145510Sdarrenr } else if ((use_inet6) && (opts & OPT_INQUE)) { 857145510Sdarrenr i = F_ACIN; 858145510Sdarrenr fp = (struct frentry *)fiop->f_acctin6[set]; 859145510Sdarrenr } else 860145510Sdarrenr#endif 861145510Sdarrenr if (opts & OPT_OUTQUE) { 862145510Sdarrenr i = F_ACOUT; 863145510Sdarrenr fp = (struct frentry *)fiop->f_acctout[set]; 864145510Sdarrenr } else if (opts & OPT_INQUE) { 865145510Sdarrenr i = F_ACIN; 866145510Sdarrenr fp = (struct frentry *)fiop->f_acctin[set]; 867145510Sdarrenr } else { 868145510Sdarrenr FPRINTF(stderr, "No -i or -o given with -a\n"); 869145510Sdarrenr return; 870145510Sdarrenr } 871145510Sdarrenr } else { 872145510Sdarrenr#ifdef USE_INET6 873145510Sdarrenr if ((use_inet6) && (opts & OPT_OUTQUE)) { 874145510Sdarrenr i = F_OUT; 875145510Sdarrenr fp = (struct frentry *)fiop->f_fout6[set]; 876145510Sdarrenr } else if ((use_inet6) && (opts & OPT_INQUE)) { 877145510Sdarrenr i = F_IN; 878145510Sdarrenr fp = (struct frentry *)fiop->f_fin6[set]; 879145510Sdarrenr } else 880145510Sdarrenr#endif 881145510Sdarrenr if (opts & OPT_OUTQUE) { 882145510Sdarrenr i = F_OUT; 883145510Sdarrenr fp = (struct frentry *)fiop->f_fout[set]; 884145510Sdarrenr } else if (opts & OPT_INQUE) { 885145510Sdarrenr i = F_IN; 886145510Sdarrenr fp = (struct frentry *)fiop->f_fin[set]; 887145510Sdarrenr } else 888145510Sdarrenr return; 889145510Sdarrenr } 890145510Sdarrenr if (opts & OPT_VERBOSE) 891145510Sdarrenr FPRINTF(stderr, "showlist:opts %#x i %d\n", opts, i); 892145510Sdarrenr 893145510Sdarrenr if (opts & OPT_VERBOSE) 894145510Sdarrenr PRINTF("fp %p set %d\n", fp, set); 895145510Sdarrenr if (!fp) { 896145510Sdarrenr FPRINTF(stderr, "empty list for %s%s\n", 897145510Sdarrenr (opts & OPT_INACTIVE) ? "inactive " : "", filters[i]); 898145510Sdarrenr return; 899145510Sdarrenr } 900145510Sdarrenr printlist(fp, NULL); 901145510Sdarrenr} 902145510Sdarrenr 903145510Sdarrenr 904145510Sdarrenr/* 905145510Sdarrenr * Display ipfilter stateful filtering information 906145510Sdarrenr */ 907145510Sdarrenrstatic void showipstates(ipsp) 908145510Sdarrenrips_stat_t *ipsp; 909145510Sdarrenr{ 910145510Sdarrenr u_long minlen, maxlen, totallen, *buckets; 911145510Sdarrenr int i, sz; 912145510Sdarrenr 913145510Sdarrenr sz = sizeof(*buckets) * ipsp->iss_statesize; 914145510Sdarrenr buckets = (u_long *)malloc(sz); 915145510Sdarrenr if (kmemcpy((char *)buckets, (u_long)ipsp->iss_bucketlen, sz)) { 916145510Sdarrenr free(buckets); 917145510Sdarrenr return; 918145510Sdarrenr } 919145510Sdarrenr 920145510Sdarrenr /* 921145510Sdarrenr * If a list of states hasn't been asked for, only print out stats 922145510Sdarrenr */ 923145510Sdarrenr if (!(opts & OPT_SHOWLIST)) { 924145510Sdarrenr PRINTF("IP states added:\n\t%lu TCP\n\t%lu UDP\n\t%lu ICMP\n", 925145510Sdarrenr ipsp->iss_tcp, ipsp->iss_udp, ipsp->iss_icmp); 926145510Sdarrenr PRINTF("\t%lu hits\n\t%lu misses\n", ipsp->iss_hits, 927145510Sdarrenr ipsp->iss_miss); 928145510Sdarrenr PRINTF("\t%lu maximum\n\t%lu no memory\n\t%lu max bucket\n", 929145510Sdarrenr ipsp->iss_max, ipsp->iss_nomem, ipsp->iss_bucketfull); 930145510Sdarrenr PRINTF("\t%lu maximum\n\t%lu no memory\n\t%lu bkts in use\n", 931145510Sdarrenr ipsp->iss_max, ipsp->iss_nomem, ipsp->iss_inuse); 932145510Sdarrenr PRINTF("\t%lu active\n\t%lu expired\n\t%lu closed\n", 933145510Sdarrenr ipsp->iss_active, ipsp->iss_expire, ipsp->iss_fin); 934145510Sdarrenr 935145510Sdarrenr PRINTF("State logging %sabled\n", 936145510Sdarrenr state_logging ? "en" : "dis"); 937145510Sdarrenr 938145510Sdarrenr PRINTF("\nState table bucket statistics:\n"); 939145510Sdarrenr PRINTF("\t%lu in use\t\n", ipsp->iss_inuse); 940145510Sdarrenr 941145510Sdarrenr minlen = ipsp->iss_max; 942145510Sdarrenr totallen = 0; 943145510Sdarrenr maxlen = 0; 944145510Sdarrenr 945145510Sdarrenr for (i = 0; i < ipsp->iss_statesize; i++) { 946145510Sdarrenr if (buckets[i] > maxlen) 947145510Sdarrenr maxlen = buckets[i]; 948145510Sdarrenr if (buckets[i] < minlen) 949145510Sdarrenr minlen = buckets[i]; 950145510Sdarrenr totallen += buckets[i]; 951145510Sdarrenr } 952145510Sdarrenr 953145510Sdarrenr PRINTF("\t%2.2f%% bucket usage\n\t%lu minimal length\n", 954145510Sdarrenr ((float)ipsp->iss_inuse / ipsp->iss_statesize) * 100.0, 955145510Sdarrenr minlen); 956145510Sdarrenr PRINTF("\t%lu maximal length\n\t%.3f average length\n", 957145510Sdarrenr maxlen, 958145510Sdarrenr ipsp->iss_inuse ? (float) totallen/ ipsp->iss_inuse : 959145510Sdarrenr 0.0); 960145510Sdarrenr 961145510Sdarrenr#define ENTRIES_PER_LINE 5 962145510Sdarrenr 963145510Sdarrenr if (opts & OPT_VERBOSE) { 964145510Sdarrenr PRINTF("\nCurrent bucket sizes :\n"); 965145510Sdarrenr for (i = 0; i < ipsp->iss_statesize; i++) { 966145510Sdarrenr if ((i % ENTRIES_PER_LINE) == 0) 967145510Sdarrenr PRINTF("\t"); 968145510Sdarrenr PRINTF("%4d -> %4lu", i, buckets[i]); 969145510Sdarrenr if ((i % ENTRIES_PER_LINE) == 970145510Sdarrenr (ENTRIES_PER_LINE - 1)) 971145510Sdarrenr PRINTF("\n"); 972145510Sdarrenr else 973145510Sdarrenr PRINTF(" "); 974145510Sdarrenr } 975145510Sdarrenr PRINTF("\n"); 976145510Sdarrenr } 977145510Sdarrenr PRINTF("\n"); 978145510Sdarrenr 979145510Sdarrenr free(buckets); 980145510Sdarrenr return; 981145510Sdarrenr } 982145510Sdarrenr 983145510Sdarrenr /* 984145510Sdarrenr * Print out all the state information currently held in the kernel. 985145510Sdarrenr */ 986145510Sdarrenr while (ipsp->iss_list != NULL) { 987145510Sdarrenr ipsp->iss_list = printstate(ipsp->iss_list, opts, 988145510Sdarrenr ipsp->iss_ticks); 989145510Sdarrenr } 990145510Sdarrenr 991145510Sdarrenr free(buckets); 992145510Sdarrenr} 993145510Sdarrenr 994145510Sdarrenr 995145510Sdarrenr#ifdef STATETOP 996145510Sdarrenrstatic int handle_resize = 0, handle_break = 0; 997145510Sdarrenr 998145510Sdarrenrstatic void topipstates(saddr, daddr, sport, dport, protocol, ver, 999145510Sdarrenr refreshtime, topclosed) 1000145510Sdarrenri6addr_t saddr; 1001145510Sdarrenri6addr_t daddr; 1002145510Sdarrenrint sport; 1003145510Sdarrenrint dport; 1004145510Sdarrenrint protocol; 1005145510Sdarrenrint ver; 1006145510Sdarrenrint refreshtime; 1007145510Sdarrenrint topclosed; 1008145510Sdarrenr{ 1009145510Sdarrenr char str1[STSTRSIZE], str2[STSTRSIZE], str3[STSTRSIZE], str4[STSTRSIZE]; 1010145510Sdarrenr int maxtsentries = 0, reverse = 0, sorting = STSORT_DEFAULT; 1011145510Sdarrenr int i, j, winy, tsentry, maxx, maxy, redraw = 0; 1012145510Sdarrenr int len, srclen, dstlen, forward = 1, c = 0; 1013145510Sdarrenr ips_stat_t ipsst, *ipsstp = &ipsst; 1014145510Sdarrenr statetop_t *tstable = NULL, *tp; 1015145510Sdarrenr ipstate_t ips; 1016145510Sdarrenr ipfobj_t ipfo; 1017145510Sdarrenr struct timeval selecttimeout; 1018145510Sdarrenr char hostnm[HOSTNMLEN]; 1019145510Sdarrenr struct protoent *proto; 1020145510Sdarrenr fd_set readfd; 1021145510Sdarrenr time_t t; 1022145510Sdarrenr 1023145510Sdarrenr /* install signal handlers */ 1024145510Sdarrenr signal(SIGINT, sig_break); 1025145510Sdarrenr signal(SIGQUIT, sig_break); 1026145510Sdarrenr signal(SIGTERM, sig_break); 1027145510Sdarrenr signal(SIGWINCH, sig_resize); 1028145510Sdarrenr 1029145510Sdarrenr /* init ncurses stuff */ 1030145510Sdarrenr initscr(); 1031145510Sdarrenr cbreak(); 1032145510Sdarrenr noecho(); 1033145510Sdarrenr curs_set(0); 1034145510Sdarrenr timeout(0); 1035145510Sdarrenr getmaxyx(stdscr, maxy, maxx); 1036145510Sdarrenr 1037145510Sdarrenr /* init hostname */ 1038145510Sdarrenr gethostname(hostnm, sizeof(hostnm) - 1); 1039145510Sdarrenr hostnm[sizeof(hostnm) - 1] = '\0'; 1040145510Sdarrenr 1041145510Sdarrenr /* init ipfobj_t stuff */ 1042145510Sdarrenr bzero((caddr_t)&ipfo, sizeof(ipfo)); 1043145510Sdarrenr ipfo.ipfo_rev = IPFILTER_VERSION; 1044145510Sdarrenr ipfo.ipfo_size = sizeof(*ipsstp); 1045145510Sdarrenr ipfo.ipfo_ptr = (void *)ipsstp; 1046145510Sdarrenr ipfo.ipfo_type = IPFOBJ_STATESTAT; 1047145510Sdarrenr 1048145510Sdarrenr /* repeat until user aborts */ 1049145510Sdarrenr while ( 1 ) { 1050145510Sdarrenr 1051145510Sdarrenr /* get state table */ 1052145510Sdarrenr bzero((char *)&ipsst, sizeof(ipsst)); 1053145510Sdarrenr if ((ioctl(state_fd, SIOCGETFS, &ipfo) == -1)) { 1054145510Sdarrenr perror("ioctl(SIOCGETFS)"); 1055145510Sdarrenr exit(-1); 1056145510Sdarrenr } 1057145510Sdarrenr 1058145510Sdarrenr /* clear the history */ 1059145510Sdarrenr tsentry = -1; 1060145510Sdarrenr 1061145510Sdarrenr /* reset max str len */ 1062145510Sdarrenr srclen = dstlen = 0; 1063145510Sdarrenr 1064145510Sdarrenr /* read the state table and store in tstable */ 1065145510Sdarrenr for (; ipsstp->iss_list; ipsstp->iss_list = ips.is_next) { 1066145510Sdarrenr 1067145510Sdarrenr if (kmemcpy((char *)&ips, (u_long)ipsstp->iss_list, 1068145510Sdarrenr sizeof(ips))) 1069145510Sdarrenr break; 1070145510Sdarrenr 1071145510Sdarrenr if (ips.is_v != ver) 1072145510Sdarrenr continue; 1073145510Sdarrenr 1074145510Sdarrenr /* check v4 src/dest addresses */ 1075145510Sdarrenr if (ips.is_v == 4) { 1076145510Sdarrenr if ((saddr.in4.s_addr != INADDR_ANY && 1077145510Sdarrenr saddr.in4.s_addr != ips.is_saddr) || 1078145510Sdarrenr (daddr.in4.s_addr != INADDR_ANY && 1079145510Sdarrenr daddr.in4.s_addr != ips.is_daddr)) 1080145510Sdarrenr continue; 1081145510Sdarrenr } 1082145510Sdarrenr#ifdef USE_INET6 1083145510Sdarrenr /* check v6 src/dest addresses */ 1084145510Sdarrenr if (ips.is_v == 6) { 1085145510Sdarrenr if ((IP6_NEQ(&saddr, &in6addr_any) && 1086145510Sdarrenr IP6_NEQ(&saddr, &ips.is_src)) || 1087145510Sdarrenr (IP6_NEQ(&daddr, &in6addr_any) && 1088145510Sdarrenr IP6_NEQ(&daddr, &ips.is_dst))) 1089145510Sdarrenr continue; 1090145510Sdarrenr } 1091145510Sdarrenr#endif 1092145510Sdarrenr /* check protocol */ 1093145510Sdarrenr if (protocol > 0 && protocol != ips.is_p) 1094145510Sdarrenr continue; 1095145510Sdarrenr 1096145510Sdarrenr /* check ports if protocol is TCP or UDP */ 1097145510Sdarrenr if (((ips.is_p == IPPROTO_TCP) || 1098145510Sdarrenr (ips.is_p == IPPROTO_UDP)) && 1099145510Sdarrenr (((sport > 0) && (htons(sport) != ips.is_sport)) || 1100145510Sdarrenr ((dport > 0) && (htons(dport) != ips.is_dport)))) 1101145510Sdarrenr continue; 1102145510Sdarrenr 1103145510Sdarrenr /* show closed TCP sessions ? */ 1104145510Sdarrenr if ((topclosed == 0) && (ips.is_p == IPPROTO_TCP) && 1105145510Sdarrenr (ips.is_state[0] >= IPF_TCPS_LAST_ACK) && 1106145510Sdarrenr (ips.is_state[1] >= IPF_TCPS_LAST_ACK)) 1107145510Sdarrenr continue; 1108145510Sdarrenr 1109145510Sdarrenr /* 1110145510Sdarrenr * if necessary make room for this state 1111145510Sdarrenr * entry 1112145510Sdarrenr */ 1113145510Sdarrenr tsentry++; 1114145510Sdarrenr if (!maxtsentries || tsentry == maxtsentries) { 1115145510Sdarrenr maxtsentries += STGROWSIZE; 1116145510Sdarrenr tstable = realloc(tstable, 1117145510Sdarrenr maxtsentries * sizeof(statetop_t)); 1118145510Sdarrenr if (tstable == NULL) { 1119145510Sdarrenr perror("realloc"); 1120145510Sdarrenr exit(-1); 1121145510Sdarrenr } 1122145510Sdarrenr } 1123145510Sdarrenr 1124145510Sdarrenr /* get max src/dest address string length */ 1125145510Sdarrenr len = strlen(getip(ips.is_v, &ips.is_src)); 1126145510Sdarrenr if (srclen < len) 1127145510Sdarrenr srclen = len; 1128145510Sdarrenr len = strlen(getip(ips.is_v, &ips.is_dst)); 1129145510Sdarrenr if (dstlen < len) 1130145510Sdarrenr dstlen = len; 1131145510Sdarrenr 1132145510Sdarrenr /* fill structure */ 1133145510Sdarrenr tp = tstable + tsentry; 1134145510Sdarrenr tp->st_src = ips.is_src; 1135145510Sdarrenr tp->st_dst = ips.is_dst; 1136145510Sdarrenr tp->st_p = ips.is_p; 1137145510Sdarrenr tp->st_v = ips.is_v; 1138145510Sdarrenr tp->st_state[0] = ips.is_state[0]; 1139145510Sdarrenr tp->st_state[1] = ips.is_state[1]; 1140145510Sdarrenr if (forward) { 1141145510Sdarrenr tp->st_pkts = ips.is_pkts[0]+ips.is_pkts[1]; 1142145510Sdarrenr tp->st_bytes = ips.is_bytes[0]+ips.is_bytes[1]; 1143145510Sdarrenr } else { 1144145510Sdarrenr tp->st_pkts = ips.is_pkts[2]+ips.is_pkts[3]; 1145145510Sdarrenr tp->st_bytes = ips.is_bytes[2]+ips.is_bytes[3]; 1146145510Sdarrenr } 1147145510Sdarrenr tp->st_age = ips.is_die - ipsstp->iss_ticks; 1148145510Sdarrenr if ((ips.is_p == IPPROTO_TCP) || 1149145510Sdarrenr (ips.is_p == IPPROTO_UDP)) { 1150145510Sdarrenr tp->st_sport = ips.is_sport; 1151145510Sdarrenr tp->st_dport = ips.is_dport; 1152145510Sdarrenr } 1153145510Sdarrenr } 1154145510Sdarrenr 1155145510Sdarrenr 1156145510Sdarrenr /* sort the array */ 1157145510Sdarrenr if (tsentry != -1) { 1158145510Sdarrenr switch (sorting) 1159145510Sdarrenr { 1160145510Sdarrenr case STSORT_PR: 1161145510Sdarrenr qsort(tstable, tsentry + 1, 1162145510Sdarrenr sizeof(statetop_t), sort_p); 1163145510Sdarrenr break; 1164145510Sdarrenr case STSORT_PKTS: 1165145510Sdarrenr qsort(tstable, tsentry + 1, 1166145510Sdarrenr sizeof(statetop_t), sort_pkts); 1167145510Sdarrenr break; 1168145510Sdarrenr case STSORT_BYTES: 1169145510Sdarrenr qsort(tstable, tsentry + 1, 1170145510Sdarrenr sizeof(statetop_t), sort_bytes); 1171145510Sdarrenr break; 1172145510Sdarrenr case STSORT_TTL: 1173145510Sdarrenr qsort(tstable, tsentry + 1, 1174145510Sdarrenr sizeof(statetop_t), sort_ttl); 1175145510Sdarrenr break; 1176145510Sdarrenr case STSORT_SRCIP: 1177145510Sdarrenr qsort(tstable, tsentry + 1, 1178145510Sdarrenr sizeof(statetop_t), sort_srcip); 1179145510Sdarrenr break; 1180145510Sdarrenr case STSORT_SRCPT: 1181145510Sdarrenr qsort(tstable, tsentry +1, 1182145510Sdarrenr sizeof(statetop_t), sort_srcpt); 1183145510Sdarrenr break; 1184145510Sdarrenr case STSORT_DSTIP: 1185145510Sdarrenr qsort(tstable, tsentry + 1, 1186145510Sdarrenr sizeof(statetop_t), sort_dstip); 1187145510Sdarrenr break; 1188145510Sdarrenr case STSORT_DSTPT: 1189145510Sdarrenr qsort(tstable, tsentry + 1, 1190145510Sdarrenr sizeof(statetop_t), sort_dstpt); 1191145510Sdarrenr break; 1192145510Sdarrenr default: 1193145510Sdarrenr break; 1194145510Sdarrenr } 1195145510Sdarrenr } 1196145510Sdarrenr 1197145510Sdarrenr /* handle window resizes */ 1198145510Sdarrenr if (handle_resize) { 1199145510Sdarrenr endwin(); 1200145510Sdarrenr initscr(); 1201145510Sdarrenr cbreak(); 1202145510Sdarrenr noecho(); 1203145510Sdarrenr curs_set(0); 1204145510Sdarrenr timeout(0); 1205145510Sdarrenr getmaxyx(stdscr, maxy, maxx); 1206145510Sdarrenr redraw = 1; 1207145510Sdarrenr handle_resize = 0; 1208145510Sdarrenr } 1209145510Sdarrenr 1210145510Sdarrenr /* stop program? */ 1211145510Sdarrenr if (handle_break) 1212145510Sdarrenr break; 1213145510Sdarrenr 1214145510Sdarrenr /* print title */ 1215145510Sdarrenr erase(); 1216145510Sdarrenr attron(A_BOLD); 1217145510Sdarrenr winy = 0; 1218145510Sdarrenr move(winy,0); 1219145510Sdarrenr sprintf(str1, "%s - %s - state top", hostnm, IPL_VERSION); 1220145510Sdarrenr for (j = 0 ; j < (maxx - 8 - strlen(str1)) / 2; j++) 1221145510Sdarrenr printw(" "); 1222145510Sdarrenr printw("%s", str1); 1223145510Sdarrenr attroff(A_BOLD); 1224145510Sdarrenr 1225145510Sdarrenr /* just for fun add a clock */ 1226145510Sdarrenr move(winy, maxx - 8); 1227145510Sdarrenr t = time(NULL); 1228145510Sdarrenr strftime(str1, 80, "%T", localtime(&t)); 1229145510Sdarrenr printw("%s\n", str1); 1230145510Sdarrenr 1231145510Sdarrenr /* 1232145510Sdarrenr * print the display filters, this is placed in the loop, 1233145510Sdarrenr * because someday I might add code for changing these 1234145510Sdarrenr * while the programming is running :-) 1235145510Sdarrenr */ 1236145510Sdarrenr if (sport >= 0) 1237145510Sdarrenr sprintf(str1, "%s,%d", getip(ver, &saddr), sport); 1238145510Sdarrenr else 1239145510Sdarrenr sprintf(str1, "%s", getip(ver, &saddr)); 1240145510Sdarrenr 1241145510Sdarrenr if (dport >= 0) 1242145510Sdarrenr sprintf(str2, "%s,%d", getip(ver, &daddr), dport); 1243145510Sdarrenr else 1244145510Sdarrenr sprintf(str2, "%s", getip(ver, &daddr)); 1245145510Sdarrenr 1246145510Sdarrenr if (protocol < 0) 1247145510Sdarrenr strcpy(str3, "any"); 1248145510Sdarrenr else if ((proto = getprotobynumber(protocol)) != NULL) 1249145510Sdarrenr sprintf(str3, "%s", proto->p_name); 1250145510Sdarrenr else 1251145510Sdarrenr sprintf(str3, "%d", protocol); 1252145510Sdarrenr 1253145510Sdarrenr switch (sorting) 1254145510Sdarrenr { 1255145510Sdarrenr case STSORT_PR: 1256145510Sdarrenr sprintf(str4, "proto"); 1257145510Sdarrenr break; 1258145510Sdarrenr case STSORT_PKTS: 1259145510Sdarrenr sprintf(str4, "# pkts"); 1260145510Sdarrenr break; 1261145510Sdarrenr case STSORT_BYTES: 1262145510Sdarrenr sprintf(str4, "# bytes"); 1263145510Sdarrenr break; 1264145510Sdarrenr case STSORT_TTL: 1265145510Sdarrenr sprintf(str4, "ttl"); 1266145510Sdarrenr break; 1267145510Sdarrenr case STSORT_SRCIP: 1268145510Sdarrenr sprintf(str4, "src ip"); 1269145510Sdarrenr break; 1270145510Sdarrenr case STSORT_SRCPT: 1271145510Sdarrenr sprintf(str4, "src port"); 1272145510Sdarrenr break; 1273145510Sdarrenr case STSORT_DSTIP: 1274145510Sdarrenr sprintf(str4, "dest ip"); 1275145510Sdarrenr break; 1276145510Sdarrenr case STSORT_DSTPT: 1277145510Sdarrenr sprintf(str4, "dest port"); 1278145510Sdarrenr break; 1279145510Sdarrenr default: 1280145510Sdarrenr sprintf(str4, "unknown"); 1281145510Sdarrenr break; 1282145510Sdarrenr } 1283145510Sdarrenr 1284145510Sdarrenr if (reverse) 1285145510Sdarrenr strcat(str4, " (reverse)"); 1286145510Sdarrenr 1287145510Sdarrenr winy += 2; 1288145510Sdarrenr move(winy,0); 1289145510Sdarrenr printw("Src: %s, Dest: %s, Proto: %s, Sorted by: %s\n\n", 1290145510Sdarrenr str1, str2, str3, str4); 1291145510Sdarrenr 1292145510Sdarrenr /* 1293145510Sdarrenr * For an IPv4 IP address we need at most 15 characters, 1294145510Sdarrenr * 4 tuples of 3 digits, separated by 3 dots. Enforce this 1295145510Sdarrenr * length, so the colums do not change positions based 1296145510Sdarrenr * on the size of the IP address. This length makes the 1297145510Sdarrenr * output fit in a 80 column terminal. 1298145510Sdarrenr * We are lacking a good solution for IPv6 addresses (that 1299145510Sdarrenr * can be longer that 15 characters), so we do not enforce 1300145510Sdarrenr * a maximum on the IP field size. 1301145510Sdarrenr */ 1302145510Sdarrenr if (srclen < 15) 1303145510Sdarrenr srclen = 15; 1304145510Sdarrenr if (dstlen < 15) 1305145510Sdarrenr dstlen = 15; 1306145510Sdarrenr 1307145510Sdarrenr /* print column description */ 1308145510Sdarrenr winy += 2; 1309145510Sdarrenr move(winy,0); 1310145510Sdarrenr attron(A_BOLD); 1311145510Sdarrenr printw("%-*s %-*s %3s %4s %7s %9s %9s\n", 1312145510Sdarrenr srclen + 6, "Source IP", dstlen + 6, "Destination IP", 1313145510Sdarrenr "ST", "PR", "#pkts", "#bytes", "ttl"); 1314145510Sdarrenr attroff(A_BOLD); 1315145510Sdarrenr 1316145510Sdarrenr /* print all the entries */ 1317145510Sdarrenr tp = tstable; 1318145510Sdarrenr if (reverse) 1319145510Sdarrenr tp += tsentry; 1320145510Sdarrenr 1321145510Sdarrenr if (tsentry > maxy - 6) 1322145510Sdarrenr tsentry = maxy - 6; 1323145510Sdarrenr for (i = 0; i <= tsentry; i++) { 1324145510Sdarrenr /* print src/dest and port */ 1325145510Sdarrenr if ((tp->st_p == IPPROTO_TCP) || 1326145510Sdarrenr (tp->st_p == IPPROTO_UDP)) { 1327145510Sdarrenr sprintf(str1, "%s,%hu", 1328145510Sdarrenr getip(tp->st_v, &tp->st_src), 1329145510Sdarrenr ntohs(tp->st_sport)); 1330145510Sdarrenr sprintf(str2, "%s,%hu", 1331145510Sdarrenr getip(tp->st_v, &tp->st_dst), 1332145510Sdarrenr ntohs(tp->st_dport)); 1333145510Sdarrenr } else { 1334145510Sdarrenr sprintf(str1, "%s", getip(tp->st_v, 1335145510Sdarrenr &tp->st_src)); 1336145510Sdarrenr sprintf(str2, "%s", getip(tp->st_v, 1337145510Sdarrenr &tp->st_dst)); 1338145510Sdarrenr } 1339145510Sdarrenr winy++; 1340145510Sdarrenr move(winy, 0); 1341145510Sdarrenr printw("%-*s %-*s", srclen + 6, str1, dstlen + 6, str2); 1342145510Sdarrenr 1343145510Sdarrenr /* print state */ 1344145510Sdarrenr sprintf(str1, "%X/%X", tp->st_state[0], 1345145510Sdarrenr tp->st_state[1]); 1346145510Sdarrenr printw(" %3s", str1); 1347145510Sdarrenr 1348145510Sdarrenr /* print protocol */ 1349145510Sdarrenr proto = getprotobynumber(tp->st_p); 1350145510Sdarrenr if (proto) { 1351145510Sdarrenr strncpy(str1, proto->p_name, 4); 1352145510Sdarrenr str1[4] = '\0'; 1353145510Sdarrenr } else { 1354145510Sdarrenr sprintf(str1, "%d", tp->st_p); 1355145510Sdarrenr } 1356145510Sdarrenr /* just print icmp for IPv6-ICMP */ 1357145510Sdarrenr if (tp->st_p == IPPROTO_ICMPV6) 1358145510Sdarrenr strcpy(str1, "icmp"); 1359145510Sdarrenr printw(" %4s", str1); 1360145510Sdarrenr 1361145510Sdarrenr /* print #pkt/#bytes */ 1362145510Sdarrenr#ifdef USE_QUAD_T 1363145510Sdarrenr printw(" %7qu %9qu", (unsigned long long) tp->st_pkts, 1364145510Sdarrenr (unsigned long long) tp->st_bytes); 1365145510Sdarrenr#else 1366145510Sdarrenr printw(" %7lu %9lu", tp->st_pkts, tp->st_bytes); 1367145510Sdarrenr#endif 1368145510Sdarrenr printw(" %9s", ttl_to_string(tp->st_age)); 1369145510Sdarrenr 1370145510Sdarrenr if (reverse) 1371145510Sdarrenr tp--; 1372145510Sdarrenr else 1373145510Sdarrenr tp++; 1374145510Sdarrenr } 1375145510Sdarrenr 1376145510Sdarrenr /* screen data structure is filled, now update the screen */ 1377145510Sdarrenr if (redraw) 1378145510Sdarrenr clearok(stdscr,1); 1379145510Sdarrenr 1380145510Sdarrenr if (refresh() == ERR) 1381145510Sdarrenr break; 1382145510Sdarrenr if (redraw) { 1383145510Sdarrenr clearok(stdscr,0); 1384145510Sdarrenr redraw = 0; 1385145510Sdarrenr } 1386145510Sdarrenr 1387145510Sdarrenr /* wait for key press or a 1 second time out period */ 1388145510Sdarrenr selecttimeout.tv_sec = refreshtime; 1389145510Sdarrenr selecttimeout.tv_usec = 0; 1390145510Sdarrenr FD_ZERO(&readfd); 1391145510Sdarrenr FD_SET(0, &readfd); 1392145510Sdarrenr select(1, &readfd, NULL, NULL, &selecttimeout); 1393145510Sdarrenr 1394145510Sdarrenr /* if key pressed, read all waiting keys */ 1395145510Sdarrenr if (FD_ISSET(0, &readfd)) { 1396145510Sdarrenr c = wgetch(stdscr); 1397145510Sdarrenr if (c == ERR) 1398145510Sdarrenr continue; 1399145510Sdarrenr 1400145510Sdarrenr if (ISALPHA(c) && ISUPPER(c)) 1401145510Sdarrenr c = TOLOWER(c); 1402145510Sdarrenr if (c == 'l') { 1403145510Sdarrenr redraw = 1; 1404145510Sdarrenr } else if (c == 'q') { 1405145510Sdarrenr break; 1406145510Sdarrenr } else if (c == 'r') { 1407145510Sdarrenr reverse = !reverse; 1408145510Sdarrenr } else if (c == 'b') { 1409145510Sdarrenr forward = 0; 1410145510Sdarrenr } else if (c == 'f') { 1411145510Sdarrenr forward = 1; 1412145510Sdarrenr } else if (c == 's') { 1413145510Sdarrenr if (++sorting > STSORT_MAX) 1414145510Sdarrenr sorting = 0; 1415145510Sdarrenr } 1416145510Sdarrenr } 1417145510Sdarrenr } /* while */ 1418145510Sdarrenr 1419145510Sdarrenr printw("\n"); 1420145510Sdarrenr curs_set(1); 1421145510Sdarrenr nocbreak(); 1422145510Sdarrenr endwin(); 1423145510Sdarrenr 1424145510Sdarrenr free(tstable); 1425145510Sdarrenr} 1426145510Sdarrenr#endif 1427145510Sdarrenr 1428145510Sdarrenr 1429145510Sdarrenr/* 1430145510Sdarrenr * Show fragment cache information that's held in the kernel. 1431145510Sdarrenr */ 1432145510Sdarrenrstatic void showfrstates(ifsp) 1433145510Sdarrenripfrstat_t *ifsp; 1434145510Sdarrenr{ 1435145510Sdarrenr struct ipfr *ipfrtab[IPFT_SIZE], ifr; 1436145510Sdarrenr int i; 1437145510Sdarrenr 1438145510Sdarrenr /* 1439145510Sdarrenr * print out the numeric statistics 1440145510Sdarrenr */ 1441145510Sdarrenr PRINTF("IP fragment states:\n\t%lu new\n\t%lu expired\n\t%lu hits\n", 1442145510Sdarrenr ifsp->ifs_new, ifsp->ifs_expire, ifsp->ifs_hits); 1443145510Sdarrenr PRINTF("\t%lu retrans\n\t%lu too short\n", 1444145510Sdarrenr ifsp->ifs_retrans0, ifsp->ifs_short); 1445145510Sdarrenr PRINTF("\t%lu no memory\n\t%lu already exist\n", 1446145510Sdarrenr ifsp->ifs_nomem, ifsp->ifs_exists); 1447145510Sdarrenr PRINTF("\t%lu inuse\n", ifsp->ifs_inuse); 1448145510Sdarrenr if (kmemcpy((char *)ipfrtab, (u_long)ifsp->ifs_table, sizeof(ipfrtab))) 1449145510Sdarrenr return; 1450145510Sdarrenr 1451145510Sdarrenr /* 1452145510Sdarrenr * Print out the contents (if any) of the fragment cache table. 1453145510Sdarrenr */ 1454145510Sdarrenr PRINTF("\n"); 1455145510Sdarrenr for (i = 0; i < IPFT_SIZE; i++) 1456145510Sdarrenr while (ipfrtab[i] != NULL) { 1457145510Sdarrenr if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i], 1458145510Sdarrenr sizeof(ifr)) == -1) 1459145510Sdarrenr break; 1460145510Sdarrenr printfraginfo("", &ifr); 1461145510Sdarrenr ipfrtab[i] = ifr.ipfr_next; 1462145510Sdarrenr } 1463145510Sdarrenr /* 1464145510Sdarrenr * Print out the contents (if any) of the NAT fragment cache table. 1465145510Sdarrenr */ 1466145510Sdarrenr if (kmemcpy((char *)ipfrtab, (u_long)ifsp->ifs_nattab,sizeof(ipfrtab))) 1467145510Sdarrenr return; 1468145510Sdarrenr for (i = 0; i < IPFT_SIZE; i++) 1469145510Sdarrenr while (ipfrtab[i] != NULL) { 1470145510Sdarrenr if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i], 1471145510Sdarrenr sizeof(ifr)) == -1) 1472145510Sdarrenr break; 1473145510Sdarrenr printfraginfo("NAT: ", &ifr); 1474145510Sdarrenr ipfrtab[i] = ifr.ipfr_next; 1475145510Sdarrenr } 1476145510Sdarrenr} 1477145510Sdarrenr 1478145510Sdarrenr 1479145510Sdarrenr/* 1480145510Sdarrenr * Show stats on how auth within IPFilter has been used 1481145510Sdarrenr */ 1482145510Sdarrenrstatic void showauthstates(asp) 1483145510Sdarrenrfr_authstat_t *asp; 1484145510Sdarrenr{ 1485145510Sdarrenr frauthent_t *frap, fra; 1486145510Sdarrenr 1487145510Sdarrenr#ifdef USE_QUAD_T 1488145510Sdarrenr printf("Authorisation hits: %qu\tmisses %qu\n", 1489145510Sdarrenr (unsigned long long) asp->fas_hits, 1490145510Sdarrenr (unsigned long long) asp->fas_miss); 1491145510Sdarrenr#else 1492145510Sdarrenr printf("Authorisation hits: %ld\tmisses %ld\n", asp->fas_hits, 1493145510Sdarrenr asp->fas_miss); 1494145510Sdarrenr#endif 1495145510Sdarrenr printf("nospace %ld\nadded %ld\nsendfail %ld\nsendok %ld\n", 1496145510Sdarrenr asp->fas_nospace, asp->fas_added, asp->fas_sendfail, 1497145510Sdarrenr asp->fas_sendok); 1498145510Sdarrenr printf("queok %ld\nquefail %ld\nexpire %ld\n", 1499145510Sdarrenr asp->fas_queok, asp->fas_quefail, asp->fas_expire); 1500145510Sdarrenr 1501145510Sdarrenr frap = asp->fas_faelist; 1502145510Sdarrenr while (frap) { 1503145510Sdarrenr if (kmemcpy((char *)&fra, (u_long)frap, sizeof(fra)) == -1) 1504145510Sdarrenr break; 1505145510Sdarrenr 1506145510Sdarrenr printf("age %ld\t", fra.fae_age); 1507145510Sdarrenr printfr(&fra.fae_fr, ioctl); 1508145510Sdarrenr frap = fra.fae_next; 1509145510Sdarrenr } 1510145510Sdarrenr} 1511145510Sdarrenr 1512145510Sdarrenr 1513145510Sdarrenr/* 1514145510Sdarrenr * Display groups used for each of filter rules, accounting rules and 1515145510Sdarrenr * authentication, separately. 1516145510Sdarrenr */ 1517145510Sdarrenrstatic void showgroups(fiop) 1518145510Sdarrenrstruct friostat *fiop; 1519145510Sdarrenr{ 1520145510Sdarrenr static char *gnames[3] = { "Filter", "Accounting", "Authentication" }; 1521145510Sdarrenr static int gnums[3] = { IPL_LOGIPF, IPL_LOGCOUNT, IPL_LOGAUTH }; 1522145510Sdarrenr frgroup_t *fp, grp; 1523145510Sdarrenr int on, off, i; 1524145510Sdarrenr 1525145510Sdarrenr on = fiop->f_active; 1526145510Sdarrenr off = 1 - on; 1527145510Sdarrenr 1528145510Sdarrenr for (i = 0; i < 3; i++) { 1529145510Sdarrenr printf("%s groups (active):\n", gnames[i]); 1530145510Sdarrenr for (fp = fiop->f_groups[gnums[i]][on]; fp != NULL; 1531145510Sdarrenr fp = grp.fg_next) 1532145510Sdarrenr if (kmemcpy((char *)&grp, (u_long)fp, sizeof(grp))) 1533145510Sdarrenr break; 1534145510Sdarrenr else 1535145510Sdarrenr printf("%s\n", grp.fg_name); 1536145510Sdarrenr printf("%s groups (inactive):\n", gnames[i]); 1537145510Sdarrenr for (fp = fiop->f_groups[gnums[i]][off]; fp != NULL; 1538145510Sdarrenr fp = grp.fg_next) 1539145510Sdarrenr if (kmemcpy((char *)&grp, (u_long)fp, sizeof(grp))) 1540145510Sdarrenr break; 1541145510Sdarrenr else 1542145510Sdarrenr printf("%s\n", grp.fg_name); 1543145510Sdarrenr } 1544145510Sdarrenr} 1545145510Sdarrenr 1546145510Sdarrenrstatic void parse_ipportstr(argument, ip, port) 1547145510Sdarrenrconst char *argument; 1548145510Sdarrenri6addr_t *ip; 1549145510Sdarrenrint *port; 1550145510Sdarrenr{ 1551145510Sdarrenr char *s, *comma; 1552145510Sdarrenr int ok = 0; 1553145510Sdarrenr 1554145510Sdarrenr /* make working copy of argument, Theoretically you must be able 1555145510Sdarrenr * to write to optarg, but that seems very ugly to me.... 1556145510Sdarrenr */ 1557145510Sdarrenr s = strdup(argument); 1558145510Sdarrenr if (s == NULL) 1559145510Sdarrenr return; 1560145510Sdarrenr 1561145510Sdarrenr /* get port */ 1562145510Sdarrenr if ((comma = strchr(s, ',')) != NULL) { 1563145510Sdarrenr if (!strcasecmp(comma + 1, "any")) { 1564145510Sdarrenr *port = -1; 1565145510Sdarrenr } else if (!sscanf(comma + 1, "%d", port) || 1566145510Sdarrenr (*port < 0) || (*port > 65535)) { 1567145510Sdarrenr fprintf(stderr, "Invalid port specfication in %s\n", 1568145510Sdarrenr argument); 1569145510Sdarrenr free(s); 1570145510Sdarrenr exit(-2); 1571145510Sdarrenr } 1572145510Sdarrenr *comma = '\0'; 1573145510Sdarrenr } 1574145510Sdarrenr 1575145510Sdarrenr 1576145510Sdarrenr /* get ip address */ 1577145510Sdarrenr if (!strcasecmp(s, "any")) { 1578145510Sdarrenr ip->in4.s_addr = INADDR_ANY; 1579145510Sdarrenr#ifdef USE_INET6 1580145510Sdarrenr ip->in6 = in6addr_any; 1581145510Sdarrenr } else if (use_inet6 && inet_pton(AF_INET6, s, &ip->in6)) { 1582145510Sdarrenr ok = 1; 1583145510Sdarrenr#endif 1584145510Sdarrenr } else if (inet_aton(s, &ip->in4)) 1585145510Sdarrenr ok = 1; 1586145510Sdarrenr 1587145510Sdarrenr if (ok == 0) { 1588145510Sdarrenr fprintf(stderr, "Invalid IP address: %s\n", s); 1589145510Sdarrenr free(s); 1590145510Sdarrenr exit(-2); 1591145510Sdarrenr } 1592145510Sdarrenr 1593145510Sdarrenr /* free allocated memory */ 1594145510Sdarrenr free(s); 1595145510Sdarrenr} 1596145510Sdarrenr 1597145510Sdarrenr 1598145510Sdarrenr#ifdef STATETOP 1599145510Sdarrenrstatic void sig_resize(s) 1600145510Sdarrenrint s; 1601145510Sdarrenr{ 1602145510Sdarrenr handle_resize = 1; 1603145510Sdarrenr} 1604145510Sdarrenr 1605145510Sdarrenrstatic void sig_break(s) 1606145510Sdarrenrint s; 1607145510Sdarrenr{ 1608145510Sdarrenr handle_break = 1; 1609145510Sdarrenr} 1610145510Sdarrenr 1611145510Sdarrenrstatic char *getip(v, addr) 1612145510Sdarrenrint v; 1613145510Sdarrenri6addr_t *addr; 1614145510Sdarrenr{ 1615145510Sdarrenr static char hostbuf[MAXHOSTNAMELEN+1]; 1616145510Sdarrenr 1617145510Sdarrenr if (v == 4) 1618145510Sdarrenr return inet_ntoa(addr->in4); 1619145510Sdarrenr 1620145510Sdarrenr#ifdef USE_INET6 1621145510Sdarrenr (void) inet_ntop(AF_INET6, &addr->in6, hostbuf, sizeof(hostbuf) - 1); 1622145510Sdarrenr hostbuf[MAXHOSTNAMELEN] = '\0'; 1623145510Sdarrenr return hostbuf; 1624145510Sdarrenr#else 1625145510Sdarrenr return "IPv6"; 1626145510Sdarrenr#endif 1627145510Sdarrenr} 1628145510Sdarrenr 1629145510Sdarrenr 1630145510Sdarrenrstatic char *ttl_to_string(ttl) 1631145510Sdarrenrlong int ttl; 1632145510Sdarrenr{ 1633145510Sdarrenr static char ttlbuf[STSTRSIZE]; 1634145510Sdarrenr int hours, minutes, seconds; 1635145510Sdarrenr 1636145510Sdarrenr /* ttl is in half seconds */ 1637145510Sdarrenr ttl /= 2; 1638145510Sdarrenr 1639145510Sdarrenr hours = ttl / 3600; 1640145510Sdarrenr ttl = ttl % 3600; 1641145510Sdarrenr minutes = ttl / 60; 1642145510Sdarrenr seconds = ttl % 60; 1643145510Sdarrenr 1644145510Sdarrenr if (hours > 0) 1645145510Sdarrenr sprintf(ttlbuf, "%2d:%02d:%02d", hours, minutes, seconds); 1646145510Sdarrenr else 1647145510Sdarrenr sprintf(ttlbuf, "%2d:%02d", minutes, seconds); 1648145510Sdarrenr return ttlbuf; 1649145510Sdarrenr} 1650145510Sdarrenr 1651145510Sdarrenr 1652145510Sdarrenrstatic int sort_pkts(a, b) 1653145510Sdarrenrconst void *a; 1654145510Sdarrenrconst void *b; 1655145510Sdarrenr{ 1656145510Sdarrenr 1657145510Sdarrenr register const statetop_t *ap = a; 1658145510Sdarrenr register const statetop_t *bp = b; 1659145510Sdarrenr 1660145510Sdarrenr if (ap->st_pkts == bp->st_pkts) 1661145510Sdarrenr return 0; 1662145510Sdarrenr else if (ap->st_pkts < bp->st_pkts) 1663145510Sdarrenr return 1; 1664145510Sdarrenr return -1; 1665145510Sdarrenr} 1666145510Sdarrenr 1667145510Sdarrenr 1668145510Sdarrenrstatic int sort_bytes(a, b) 1669145510Sdarrenrconst void *a; 1670145510Sdarrenrconst void *b; 1671145510Sdarrenr{ 1672145510Sdarrenr register const statetop_t *ap = a; 1673145510Sdarrenr register const statetop_t *bp = b; 1674145510Sdarrenr 1675145510Sdarrenr if (ap->st_bytes == bp->st_bytes) 1676145510Sdarrenr return 0; 1677145510Sdarrenr else if (ap->st_bytes < bp->st_bytes) 1678145510Sdarrenr return 1; 1679145510Sdarrenr return -1; 1680145510Sdarrenr} 1681145510Sdarrenr 1682145510Sdarrenr 1683145510Sdarrenrstatic int sort_p(a, b) 1684145510Sdarrenrconst void *a; 1685145510Sdarrenrconst void *b; 1686145510Sdarrenr{ 1687145510Sdarrenr register const statetop_t *ap = a; 1688145510Sdarrenr register const statetop_t *bp = b; 1689145510Sdarrenr 1690145510Sdarrenr if (ap->st_p == bp->st_p) 1691145510Sdarrenr return 0; 1692145510Sdarrenr else if (ap->st_p < bp->st_p) 1693145510Sdarrenr return 1; 1694145510Sdarrenr return -1; 1695145510Sdarrenr} 1696145510Sdarrenr 1697145510Sdarrenr 1698145510Sdarrenrstatic int sort_ttl(a, b) 1699145510Sdarrenrconst void *a; 1700145510Sdarrenrconst void *b; 1701145510Sdarrenr{ 1702145510Sdarrenr register const statetop_t *ap = a; 1703145510Sdarrenr register const statetop_t *bp = b; 1704145510Sdarrenr 1705145510Sdarrenr if (ap->st_age == bp->st_age) 1706145510Sdarrenr return 0; 1707145510Sdarrenr else if (ap->st_age < bp->st_age) 1708145510Sdarrenr return 1; 1709145510Sdarrenr return -1; 1710145510Sdarrenr} 1711145510Sdarrenr 1712145510Sdarrenrstatic int sort_srcip(a, b) 1713145510Sdarrenrconst void *a; 1714145510Sdarrenrconst void *b; 1715145510Sdarrenr{ 1716145510Sdarrenr register const statetop_t *ap = a; 1717145510Sdarrenr register const statetop_t *bp = b; 1718145510Sdarrenr 1719145510Sdarrenr#ifdef USE_INET6 1720145510Sdarrenr if (use_inet6) { 1721145510Sdarrenr if (IP6_EQ(&ap->st_src, &bp->st_src)) 1722145510Sdarrenr return 0; 1723145510Sdarrenr else if (IP6_GT(&ap->st_src, &bp->st_src)) 1724145510Sdarrenr return 1; 1725145510Sdarrenr } else 1726145510Sdarrenr#endif 1727145510Sdarrenr { 1728145510Sdarrenr if (ntohl(ap->st_src.in4.s_addr) == 1729145510Sdarrenr ntohl(bp->st_src.in4.s_addr)) 1730145510Sdarrenr return 0; 1731145510Sdarrenr else if (ntohl(ap->st_src.in4.s_addr) > 1732145510Sdarrenr ntohl(bp->st_src.in4.s_addr)) 1733145510Sdarrenr return 1; 1734145510Sdarrenr } 1735145510Sdarrenr return -1; 1736145510Sdarrenr} 1737145510Sdarrenr 1738145510Sdarrenrstatic int sort_srcpt(a, b) 1739145510Sdarrenrconst void *a; 1740145510Sdarrenrconst void *b; 1741145510Sdarrenr{ 1742145510Sdarrenr register const statetop_t *ap = a; 1743145510Sdarrenr register const statetop_t *bp = b; 1744145510Sdarrenr 1745145510Sdarrenr if (htons(ap->st_sport) == htons(bp->st_sport)) 1746145510Sdarrenr return 0; 1747145510Sdarrenr else if (htons(ap->st_sport) > htons(bp->st_sport)) 1748145510Sdarrenr return 1; 1749145510Sdarrenr return -1; 1750145510Sdarrenr} 1751145510Sdarrenr 1752145510Sdarrenrstatic int sort_dstip(a, b) 1753145510Sdarrenrconst void *a; 1754145510Sdarrenrconst void *b; 1755145510Sdarrenr{ 1756145510Sdarrenr register const statetop_t *ap = a; 1757145510Sdarrenr register const statetop_t *bp = b; 1758145510Sdarrenr 1759145510Sdarrenr#ifdef USE_INET6 1760145510Sdarrenr if (use_inet6) { 1761145510Sdarrenr if (IP6_EQ(&ap->st_dst, &bp->st_dst)) 1762145510Sdarrenr return 0; 1763145510Sdarrenr else if (IP6_GT(&ap->st_dst, &bp->st_dst)) 1764145510Sdarrenr return 1; 1765145510Sdarrenr } else 1766145510Sdarrenr#endif 1767145510Sdarrenr { 1768145510Sdarrenr if (ntohl(ap->st_dst.in4.s_addr) == 1769145510Sdarrenr ntohl(bp->st_dst.in4.s_addr)) 1770145510Sdarrenr return 0; 1771145510Sdarrenr else if (ntohl(ap->st_dst.in4.s_addr) > 1772145510Sdarrenr ntohl(bp->st_dst.in4.s_addr)) 1773145510Sdarrenr return 1; 1774145510Sdarrenr } 1775145510Sdarrenr return -1; 1776145510Sdarrenr} 1777145510Sdarrenr 1778145510Sdarrenrstatic int sort_dstpt(a, b) 1779145510Sdarrenrconst void *a; 1780145510Sdarrenrconst void *b; 1781145510Sdarrenr{ 1782145510Sdarrenr register const statetop_t *ap = a; 1783145510Sdarrenr register const statetop_t *bp = b; 1784145510Sdarrenr 1785145510Sdarrenr if (htons(ap->st_dport) == htons(bp->st_dport)) 1786145510Sdarrenr return 0; 1787145510Sdarrenr else if (htons(ap->st_dport) > htons(bp->st_dport)) 1788145510Sdarrenr return 1; 1789145510Sdarrenr return -1; 1790145510Sdarrenr} 1791145510Sdarrenr 1792145510Sdarrenr#endif 1793