1145519Sdarrenr/* $FreeBSD$ */ 2145510Sdarrenr 3145510Sdarrenr/* 4255332Scy * Copyright (C) 2012 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> 18255332Scy#include <ctype.h> 19145510Sdarrenr#include <fcntl.h> 20145510Sdarrenr#ifdef linux 21145510Sdarrenr# include <linux/a.out.h> 22145510Sdarrenr#else 23145510Sdarrenr# include <nlist.h> 24145510Sdarrenr#endif 25145510Sdarrenr#include <ctype.h> 26145510Sdarrenr#if defined(sun) && (defined(__svr4__) || defined(__SVR4)) 27145510Sdarrenr# include <stddef.h> 28145510Sdarrenr#endif 29145510Sdarrenr#include "ipf.h" 30145510Sdarrenr#include "netinet/ipl.h" 31145510Sdarrenr#if defined(STATETOP) 32145510Sdarrenr# if defined(_BSDI_VERSION) 33145510Sdarrenr# undef STATETOP 34145510Sdarrenr# endif 35145510Sdarrenr# if defined(__FreeBSD__) && \ 36145510Sdarrenr (!defined(__FreeBSD_version) || (__FreeBSD_version < 430000)) 37145510Sdarrenr# undef STATETOP 38145510Sdarrenr# endif 39145510Sdarrenr# if defined(__NetBSD_Version__) && (__NetBSD_Version__ < 105000000) 40145510Sdarrenr# undef STATETOP 41145510Sdarrenr# endif 42145510Sdarrenr# if defined(sun) 43145510Sdarrenr# if defined(__svr4__) || defined(__SVR4) 44145510Sdarrenr# include <sys/select.h> 45145510Sdarrenr# else 46145510Sdarrenr# undef STATETOP /* NOT supported on SunOS4 */ 47145510Sdarrenr# endif 48145510Sdarrenr# endif 49145510Sdarrenr#endif 50145510Sdarrenr#if defined(STATETOP) && !defined(linux) 51145510Sdarrenr# include <netinet/ip_var.h> 52145510Sdarrenr# include <netinet/tcp_fsm.h> 53145510Sdarrenr#endif 54145510Sdarrenr#ifdef STATETOP 55145510Sdarrenr# include <ctype.h> 56145510Sdarrenr# include <signal.h> 57170268Sdarrenr# include <time.h> 58145510Sdarrenr# if SOLARIS || defined(__NetBSD__) || defined(_BSDI_VERSION) || \ 59145510Sdarrenr defined(__sgi) 60145510Sdarrenr# ifdef ERR 61145510Sdarrenr# undef ERR 62145510Sdarrenr# endif 63145510Sdarrenr# include <curses.h> 64145510Sdarrenr# else /* SOLARIS */ 65145510Sdarrenr# include <ncurses.h> 66145510Sdarrenr# endif /* SOLARIS */ 67145510Sdarrenr#endif /* STATETOP */ 68145510Sdarrenr#include "kmem.h" 69145510Sdarrenr#if defined(__NetBSD__) || (__OpenBSD__) 70145510Sdarrenr# include <paths.h> 71145510Sdarrenr#endif 72145510Sdarrenr 73145510Sdarrenr#if !defined(lint) 74145510Sdarrenrstatic const char sccsid[] = "@(#)fils.c 1.21 4/20/96 (C) 1993-2000 Darren Reed"; 75255332Scystatic const char rcsid[] = "@(#)$Id$"; 76145510Sdarrenr#endif 77145510Sdarrenr 78145510Sdarrenr#ifdef __hpux 79145510Sdarrenr# define nlist nlist64 80145510Sdarrenr#endif 81145510Sdarrenr 82145510Sdarrenrextern char *optarg; 83145510Sdarrenrextern int optind; 84145510Sdarrenrextern int opterr; 85145510Sdarrenr 86145510Sdarrenr#define PRINTF (void)printf 87145510Sdarrenr#define FPRINTF (void)fprintf 88145510Sdarrenrstatic char *filters[4] = { "ipfilter(in)", "ipfilter(out)", 89145510Sdarrenr "ipacct(in)", "ipacct(out)" }; 90145510Sdarrenrstatic int state_logging = -1; 91255332Scystatic wordtab_t *state_fields = NULL; 92145510Sdarrenr 93255332Scyint nohdrfields = 0; 94145510Sdarrenrint opts = 0; 95145510Sdarrenrint use_inet6 = 0; 96145510Sdarrenrint live_kernel = 1; 97145510Sdarrenrint state_fd = -1; 98145510Sdarrenrint ipf_fd = -1; 99170268Sdarrenrint auth_fd = -1; 100170268Sdarrenrint nat_fd = -1; 101170268Sdarrenrfrgroup_t *grtop = NULL; 102170268Sdarrenrfrgroup_t *grtail = NULL; 103145510Sdarrenr 104255332Scychar *blockreasons[FRB_MAX_VALUE + 1] = { 105255332Scy "packet blocked", 106255332Scy "log rule failure", 107255332Scy "pps rate exceeded", 108255332Scy "jumbogram", 109255332Scy "makefrip failed", 110255332Scy "cannot add state", 111255332Scy "IP ID update failed", 112255332Scy "log-or-block failed", 113255332Scy "decapsulate failure", 114255332Scy "cannot create new auth entry", 115255332Scy "packet queued for auth", 116255332Scy "buffer coalesce failure", 117255332Scy "buffer pullup failure", 118255332Scy "auth feedback", 119255332Scy "bad fragment", 120255332Scy "IPv4 NAT failure", 121255332Scy "IPv6 NAT failure" 122255332Scy}; 123255332Scy 124145510Sdarrenr#ifdef STATETOP 125145510Sdarrenr#define STSTRSIZE 80 126145510Sdarrenr#define STGROWSIZE 16 127145510Sdarrenr#define HOSTNMLEN 40 128145510Sdarrenr 129145510Sdarrenr#define STSORT_PR 0 130145510Sdarrenr#define STSORT_PKTS 1 131145510Sdarrenr#define STSORT_BYTES 2 132145510Sdarrenr#define STSORT_TTL 3 133145510Sdarrenr#define STSORT_SRCIP 4 134145510Sdarrenr#define STSORT_SRCPT 5 135145510Sdarrenr#define STSORT_DSTIP 6 136145510Sdarrenr#define STSORT_DSTPT 7 137145510Sdarrenr#define STSORT_MAX STSORT_DSTPT 138145510Sdarrenr#define STSORT_DEFAULT STSORT_BYTES 139145510Sdarrenr 140145510Sdarrenr 141145510Sdarrenrtypedef struct statetop { 142145510Sdarrenr i6addr_t st_src; 143145510Sdarrenr i6addr_t st_dst; 144145510Sdarrenr u_short st_sport; 145145510Sdarrenr u_short st_dport; 146145510Sdarrenr u_char st_p; 147145510Sdarrenr u_char st_v; 148145510Sdarrenr u_char st_state[2]; 149145510Sdarrenr U_QUAD_T st_pkts; 150145510Sdarrenr U_QUAD_T st_bytes; 151145510Sdarrenr u_long st_age; 152145510Sdarrenr} statetop_t; 153145510Sdarrenr#endif 154145510Sdarrenr 155145510Sdarrenrint main __P((int, char *[])); 156145510Sdarrenr 157170268Sdarrenrstatic int fetchfrag __P((int, int, ipfr_t *)); 158145510Sdarrenrstatic void showstats __P((friostat_t *, u_32_t)); 159170268Sdarrenrstatic void showfrstates __P((ipfrstat_t *, u_long)); 160145510Sdarrenrstatic void showlist __P((friostat_t *)); 161255332Scystatic void showstatestats __P((ips_stat_t *)); 162255332Scystatic void showipstates __P((ips_stat_t *, int *)); 163255332Scystatic void showauthstates __P((ipf_authstat_t *)); 164255332Scystatic void showtqtable_live __P((int)); 165145510Sdarrenrstatic void showgroups __P((friostat_t *)); 166145510Sdarrenrstatic void usage __P((char *)); 167255332Scystatic int state_matcharray __P((ipstate_t *, int *)); 168255332Scystatic int printlivelist __P((friostat_t *, int, int, frentry_t *, 169255332Scy char *, char *)); 170255332Scystatic void printdeadlist __P((friostat_t *, int, int, frentry_t *, 171255332Scy char *, char *)); 172255332Scystatic void printside __P((char *, ipf_statistics_t *)); 173145510Sdarrenrstatic void parse_ipportstr __P((const char *, i6addr_t *, int *)); 174145510Sdarrenrstatic void ipfstate_live __P((char *, friostat_t **, ips_stat_t **, 175255332Scy ipfrstat_t **, ipf_authstat_t **, u_32_t *)); 176145510Sdarrenrstatic void ipfstate_dead __P((char *, friostat_t **, ips_stat_t **, 177255332Scy ipfrstat_t **, ipf_authstat_t **, u_32_t *)); 178170268Sdarrenrstatic ipstate_t *fetchstate __P((ipstate_t *, ipstate_t *)); 179145510Sdarrenr#ifdef STATETOP 180145510Sdarrenrstatic void topipstates __P((i6addr_t, i6addr_t, int, int, int, 181255332Scy int, int, int, int *)); 182145510Sdarrenrstatic void sig_break __P((int)); 183145510Sdarrenrstatic void sig_resize __P((int)); 184145510Sdarrenrstatic char *getip __P((int, i6addr_t *)); 185145510Sdarrenrstatic char *ttl_to_string __P((long)); 186145510Sdarrenrstatic int sort_p __P((const void *, const void *)); 187145510Sdarrenrstatic int sort_pkts __P((const void *, const void *)); 188145510Sdarrenrstatic int sort_bytes __P((const void *, const void *)); 189145510Sdarrenrstatic int sort_ttl __P((const void *, const void *)); 190145510Sdarrenrstatic int sort_srcip __P((const void *, const void *)); 191145510Sdarrenrstatic int sort_srcpt __P((const void *, const void *)); 192145510Sdarrenrstatic int sort_dstip __P((const void *, const void *)); 193145510Sdarrenrstatic int sort_dstpt __P((const void *, const void *)); 194145510Sdarrenr#endif 195145510Sdarrenr 196145510Sdarrenr 197145510Sdarrenrstatic void usage(name) 198255332Scy char *name; 199145510Sdarrenr{ 200145510Sdarrenr#ifdef USE_INET6 201145510Sdarrenr fprintf(stderr, "Usage: %s [-6aAdfghIilnoRsv]\n", name); 202145510Sdarrenr#else 203145510Sdarrenr fprintf(stderr, "Usage: %s [-aAdfghIilnoRsv]\n", name); 204145510Sdarrenr#endif 205145510Sdarrenr fprintf(stderr, " %s [-M corefile] [-N symbol-list]\n", name); 206145510Sdarrenr#ifdef USE_INET6 207145510Sdarrenr fprintf(stderr, " %s -t [-6C] ", name); 208145510Sdarrenr#else 209145510Sdarrenr fprintf(stderr, " %s -t [-C] ", name); 210145510Sdarrenr#endif 211145510Sdarrenr fprintf(stderr, "[-D destination address] [-P protocol] [-S source address] [-T refresh time]\n"); 212145510Sdarrenr exit(1); 213145510Sdarrenr} 214145510Sdarrenr 215145510Sdarrenr 216145510Sdarrenrint main(argc,argv) 217255332Scy int argc; 218255332Scy char *argv[]; 219145510Sdarrenr{ 220255332Scy ipf_authstat_t frauthst; 221255332Scy ipf_authstat_t *frauthstp = &frauthst; 222145510Sdarrenr friostat_t fio; 223145510Sdarrenr friostat_t *fiop = &fio; 224145510Sdarrenr ips_stat_t ipsst; 225145510Sdarrenr ips_stat_t *ipsstp = &ipsst; 226145510Sdarrenr ipfrstat_t ifrst; 227145510Sdarrenr ipfrstat_t *ifrstp = &ifrst; 228255332Scy char *options; 229255332Scy char *kern = NULL; 230255332Scy char *memf = NULL; 231255332Scy int c; 232255332Scy int myoptind; 233255332Scy int *filter = NULL; 234145510Sdarrenr 235145510Sdarrenr int protocol = -1; /* -1 = wild card for any protocol */ 236145510Sdarrenr int refreshtime = 1; /* default update time */ 237145510Sdarrenr int sport = -1; /* -1 = wild card for any source port */ 238145510Sdarrenr int dport = -1; /* -1 = wild card for any dest port */ 239145510Sdarrenr int topclosed = 0; /* do not show closed tcp sessions */ 240145510Sdarrenr i6addr_t saddr, daddr; 241145510Sdarrenr u_32_t frf; 242145510Sdarrenr 243145510Sdarrenr#ifdef USE_INET6 244255332Scy options = "6aACdfghIilnostvD:m:M:N:O:P:RS:T:"; 245145510Sdarrenr#else 246255332Scy options = "aACdfghIilnostvD:m:M:N:O:P:RS:T:"; 247145510Sdarrenr#endif 248145510Sdarrenr 249145510Sdarrenr saddr.in4.s_addr = INADDR_ANY; /* default any v4 source addr */ 250145510Sdarrenr daddr.in4.s_addr = INADDR_ANY; /* default any v4 dest addr */ 251145510Sdarrenr#ifdef USE_INET6 252145510Sdarrenr saddr.in6 = in6addr_any; /* default any v6 source addr */ 253145510Sdarrenr daddr.in6 = in6addr_any; /* default any v6 dest addr */ 254145510Sdarrenr#endif 255145510Sdarrenr 256145510Sdarrenr /* Don't warn about invalid flags when we run getopt for the 1st time */ 257145510Sdarrenr opterr = 0; 258145510Sdarrenr 259145510Sdarrenr /* 260145510Sdarrenr * Parse these two arguments now lest there be any buffer overflows 261145510Sdarrenr * in the parsing of the rest. 262145510Sdarrenr */ 263145510Sdarrenr myoptind = optind; 264145510Sdarrenr while ((c = getopt(argc, argv, options)) != -1) { 265145510Sdarrenr switch (c) 266145510Sdarrenr { 267145510Sdarrenr case 'M' : 268145510Sdarrenr memf = optarg; 269145510Sdarrenr live_kernel = 0; 270145510Sdarrenr break; 271145510Sdarrenr case 'N' : 272145510Sdarrenr kern = optarg; 273145510Sdarrenr live_kernel = 0; 274145510Sdarrenr break; 275145510Sdarrenr } 276145510Sdarrenr } 277145510Sdarrenr optind = myoptind; 278145510Sdarrenr 279145510Sdarrenr if (live_kernel == 1) { 280145510Sdarrenr if ((state_fd = open(IPSTATE_NAME, O_RDONLY)) == -1) { 281145510Sdarrenr perror("open(IPSTATE_NAME)"); 282145510Sdarrenr exit(-1); 283145510Sdarrenr } 284170268Sdarrenr if ((auth_fd = open(IPAUTH_NAME, O_RDONLY)) == -1) { 285170268Sdarrenr perror("open(IPAUTH_NAME)"); 286170268Sdarrenr exit(-1); 287170268Sdarrenr } 288170268Sdarrenr if ((nat_fd = open(IPNAT_NAME, O_RDONLY)) == -1) { 289170268Sdarrenr perror("open(IPAUTH_NAME)"); 290170268Sdarrenr exit(-1); 291170268Sdarrenr } 292170268Sdarrenr if ((ipf_fd = open(IPL_NAME, O_RDONLY)) == -1) { 293170268Sdarrenr fprintf(stderr, "open(%s)", IPL_NAME); 294145510Sdarrenr perror(""); 295145510Sdarrenr exit(-1); 296145510Sdarrenr } 297145510Sdarrenr } 298145510Sdarrenr 299145510Sdarrenr if (kern != NULL || memf != NULL) { 300145510Sdarrenr (void)setgid(getgid()); 301145510Sdarrenr (void)setuid(getuid()); 302145510Sdarrenr } 303145510Sdarrenr 304170268Sdarrenr if (live_kernel == 1) { 305170268Sdarrenr (void) checkrev(IPL_NAME); 306170268Sdarrenr } else { 307170268Sdarrenr if (openkmem(kern, memf) == -1) 308170268Sdarrenr exit(-1); 309170268Sdarrenr } 310145510Sdarrenr 311145510Sdarrenr (void)setgid(getgid()); 312145510Sdarrenr (void)setuid(getuid()); 313145510Sdarrenr 314145510Sdarrenr opterr = 1; 315145510Sdarrenr 316145510Sdarrenr while ((c = getopt(argc, argv, options)) != -1) 317145510Sdarrenr { 318145510Sdarrenr switch (c) 319145510Sdarrenr { 320145510Sdarrenr#ifdef USE_INET6 321145510Sdarrenr case '6' : 322145510Sdarrenr use_inet6 = 1; 323145510Sdarrenr break; 324145510Sdarrenr#endif 325145510Sdarrenr case 'a' : 326145510Sdarrenr opts |= OPT_ACCNT|OPT_SHOWLIST; 327145510Sdarrenr break; 328145510Sdarrenr case 'A' : 329145510Sdarrenr opts |= OPT_AUTHSTATS; 330145510Sdarrenr break; 331145510Sdarrenr case 'C' : 332145510Sdarrenr topclosed = 1; 333145510Sdarrenr break; 334145510Sdarrenr case 'd' : 335145510Sdarrenr opts |= OPT_DEBUG; 336145510Sdarrenr break; 337145510Sdarrenr case 'D' : 338145510Sdarrenr parse_ipportstr(optarg, &daddr, &dport); 339145510Sdarrenr break; 340145510Sdarrenr case 'f' : 341145510Sdarrenr opts |= OPT_FRSTATES; 342145510Sdarrenr break; 343145510Sdarrenr case 'g' : 344145510Sdarrenr opts |= OPT_GROUPS; 345145510Sdarrenr break; 346145510Sdarrenr case 'h' : 347145510Sdarrenr opts |= OPT_HITS; 348145510Sdarrenr break; 349145510Sdarrenr case 'i' : 350145510Sdarrenr opts |= OPT_INQUE|OPT_SHOWLIST; 351145510Sdarrenr break; 352145510Sdarrenr case 'I' : 353145510Sdarrenr opts |= OPT_INACTIVE; 354145510Sdarrenr break; 355145510Sdarrenr case 'l' : 356145510Sdarrenr opts |= OPT_SHOWLIST; 357145510Sdarrenr break; 358255332Scy case 'm' : 359255332Scy filter = parseipfexpr(optarg, NULL); 360255332Scy if (filter == NULL) { 361255332Scy fprintf(stderr, "Error parseing '%s'\n", 362255332Scy optarg); 363255332Scy exit(1); 364255332Scy } 365255332Scy break; 366145510Sdarrenr case 'M' : 367145510Sdarrenr break; 368145510Sdarrenr case 'N' : 369145510Sdarrenr break; 370145510Sdarrenr case 'n' : 371145510Sdarrenr opts |= OPT_SHOWLINENO; 372145510Sdarrenr break; 373145510Sdarrenr case 'o' : 374145510Sdarrenr opts |= OPT_OUTQUE|OPT_SHOWLIST; 375145510Sdarrenr break; 376255332Scy case 'O' : 377255332Scy state_fields = parsefields(statefields, optarg); 378255332Scy break; 379145510Sdarrenr case 'P' : 380145510Sdarrenr protocol = getproto(optarg); 381145510Sdarrenr if (protocol == -1) { 382145510Sdarrenr fprintf(stderr, "%s: Invalid protocol: %s\n", 383145510Sdarrenr argv[0], optarg); 384145510Sdarrenr exit(-2); 385145510Sdarrenr } 386145510Sdarrenr break; 387145510Sdarrenr case 'R' : 388145510Sdarrenr opts |= OPT_NORESOLVE; 389145510Sdarrenr break; 390145510Sdarrenr case 's' : 391145510Sdarrenr opts |= OPT_IPSTATES; 392145510Sdarrenr break; 393145510Sdarrenr case 'S' : 394145510Sdarrenr parse_ipportstr(optarg, &saddr, &sport); 395145510Sdarrenr break; 396145510Sdarrenr case 't' : 397145510Sdarrenr#ifdef STATETOP 398145510Sdarrenr opts |= OPT_STATETOP; 399145510Sdarrenr break; 400145510Sdarrenr#else 401145510Sdarrenr fprintf(stderr, 402145510Sdarrenr "%s: state top facility not compiled in\n", 403145510Sdarrenr argv[0]); 404145510Sdarrenr exit(-2); 405145510Sdarrenr#endif 406145510Sdarrenr case 'T' : 407145510Sdarrenr if (!sscanf(optarg, "%d", &refreshtime) || 408145510Sdarrenr (refreshtime <= 0)) { 409145510Sdarrenr fprintf(stderr, 410145510Sdarrenr "%s: Invalid refreshtime < 1 : %s\n", 411145510Sdarrenr argv[0], optarg); 412145510Sdarrenr exit(-2); 413145510Sdarrenr } 414145510Sdarrenr break; 415145510Sdarrenr case 'v' : 416145510Sdarrenr opts |= OPT_VERBOSE; 417145510Sdarrenr break; 418145510Sdarrenr default : 419145510Sdarrenr usage(argv[0]); 420145510Sdarrenr break; 421145510Sdarrenr } 422145510Sdarrenr } 423145510Sdarrenr 424145510Sdarrenr if (live_kernel == 1) { 425145510Sdarrenr bzero((char *)&fio, sizeof(fio)); 426145510Sdarrenr bzero((char *)&ipsst, sizeof(ipsst)); 427145510Sdarrenr bzero((char *)&ifrst, sizeof(ifrst)); 428145510Sdarrenr 429170268Sdarrenr ipfstate_live(IPL_NAME, &fiop, &ipsstp, &ifrstp, 430145510Sdarrenr &frauthstp, &frf); 431255332Scy } else { 432145510Sdarrenr ipfstate_dead(kern, &fiop, &ipsstp, &ifrstp, &frauthstp, &frf); 433255332Scy } 434145510Sdarrenr 435145510Sdarrenr if (opts & OPT_IPSTATES) { 436255332Scy showipstates(ipsstp, filter); 437145510Sdarrenr } else if (opts & OPT_SHOWLIST) { 438145510Sdarrenr showlist(fiop); 439145510Sdarrenr if ((opts & OPT_OUTQUE) && (opts & OPT_INQUE)){ 440145510Sdarrenr opts &= ~OPT_OUTQUE; 441145510Sdarrenr showlist(fiop); 442145510Sdarrenr } 443145510Sdarrenr } else if (opts & OPT_FRSTATES) 444170268Sdarrenr showfrstates(ifrstp, fiop->f_ticks); 445145510Sdarrenr#ifdef STATETOP 446145510Sdarrenr else if (opts & OPT_STATETOP) 447145510Sdarrenr topipstates(saddr, daddr, sport, dport, protocol, 448255332Scy use_inet6 ? 6 : 4, refreshtime, topclosed, filter); 449145510Sdarrenr#endif 450145510Sdarrenr else if (opts & OPT_AUTHSTATS) 451145510Sdarrenr showauthstates(frauthstp); 452145510Sdarrenr else if (opts & OPT_GROUPS) 453145510Sdarrenr showgroups(fiop); 454145510Sdarrenr else 455145510Sdarrenr showstats(fiop, frf); 456145510Sdarrenr 457145510Sdarrenr return 0; 458145510Sdarrenr} 459145510Sdarrenr 460145510Sdarrenr 461145510Sdarrenr/* 462145510Sdarrenr * Fill in the stats structures from the live kernel, using a combination 463145510Sdarrenr * of ioctl's and copying directly from kernel memory. 464145510Sdarrenr */ 465145510Sdarrenrstatic void ipfstate_live(device, fiopp, ipsstpp, ifrstpp, frauthstpp, frfp) 466255332Scy char *device; 467255332Scy friostat_t **fiopp; 468255332Scy ips_stat_t **ipsstpp; 469255332Scy ipfrstat_t **ifrstpp; 470255332Scy ipf_authstat_t **frauthstpp; 471255332Scy u_32_t *frfp; 472145510Sdarrenr{ 473145510Sdarrenr ipfobj_t ipfo; 474145510Sdarrenr 475145510Sdarrenr if (checkrev(device) == -1) { 476145510Sdarrenr fprintf(stderr, "User/kernel version check failed\n"); 477145510Sdarrenr exit(1); 478145510Sdarrenr } 479145510Sdarrenr 480145510Sdarrenr if ((opts & OPT_AUTHSTATS) == 0) { 481145510Sdarrenr bzero((caddr_t)&ipfo, sizeof(ipfo)); 482145510Sdarrenr ipfo.ipfo_rev = IPFILTER_VERSION; 483170268Sdarrenr ipfo.ipfo_type = IPFOBJ_IPFSTAT; 484145510Sdarrenr ipfo.ipfo_size = sizeof(friostat_t); 485145510Sdarrenr ipfo.ipfo_ptr = (void *)*fiopp; 486145510Sdarrenr 487145510Sdarrenr if (ioctl(ipf_fd, SIOCGETFS, &ipfo) == -1) { 488255332Scy ipferror(ipf_fd, "ioctl(ipf:SIOCGETFS)"); 489145510Sdarrenr exit(-1); 490145510Sdarrenr } 491145510Sdarrenr 492145510Sdarrenr if (ioctl(ipf_fd, SIOCGETFF, frfp) == -1) 493255332Scy ipferror(ipf_fd, "ioctl(SIOCGETFF)"); 494145510Sdarrenr } 495145510Sdarrenr 496145510Sdarrenr if ((opts & OPT_IPSTATES) != 0) { 497145510Sdarrenr 498145510Sdarrenr bzero((caddr_t)&ipfo, sizeof(ipfo)); 499145510Sdarrenr ipfo.ipfo_rev = IPFILTER_VERSION; 500170268Sdarrenr ipfo.ipfo_type = IPFOBJ_STATESTAT; 501145510Sdarrenr ipfo.ipfo_size = sizeof(ips_stat_t); 502145510Sdarrenr ipfo.ipfo_ptr = (void *)*ipsstpp; 503145510Sdarrenr 504145510Sdarrenr if ((ioctl(state_fd, SIOCGETFS, &ipfo) == -1)) { 505255332Scy ipferror(state_fd, "ioctl(state:SIOCGETFS)"); 506145510Sdarrenr exit(-1); 507145510Sdarrenr } 508145510Sdarrenr if (ioctl(state_fd, SIOCGETLG, &state_logging) == -1) { 509255332Scy ipferror(state_fd, "ioctl(state:SIOCGETLG)"); 510145510Sdarrenr exit(-1); 511145510Sdarrenr } 512145510Sdarrenr } 513145510Sdarrenr 514145510Sdarrenr if ((opts & OPT_FRSTATES) != 0) { 515145510Sdarrenr bzero((caddr_t)&ipfo, sizeof(ipfo)); 516145510Sdarrenr ipfo.ipfo_rev = IPFILTER_VERSION; 517170268Sdarrenr ipfo.ipfo_type = IPFOBJ_FRAGSTAT; 518145510Sdarrenr ipfo.ipfo_size = sizeof(ipfrstat_t); 519145510Sdarrenr ipfo.ipfo_ptr = (void *)*ifrstpp; 520255332Scy 521145510Sdarrenr if (ioctl(ipf_fd, SIOCGFRST, &ipfo) == -1) { 522255332Scy ipferror(ipf_fd, "ioctl(SIOCGFRST)"); 523145510Sdarrenr exit(-1); 524145510Sdarrenr } 525145510Sdarrenr } 526145510Sdarrenr 527170268Sdarrenr if (opts & OPT_DEBUG) 528145510Sdarrenr PRINTF("opts %#x name %s\n", opts, device); 529145510Sdarrenr 530145510Sdarrenr if ((opts & OPT_AUTHSTATS) != 0) { 531145510Sdarrenr bzero((caddr_t)&ipfo, sizeof(ipfo)); 532145510Sdarrenr ipfo.ipfo_rev = IPFILTER_VERSION; 533170268Sdarrenr ipfo.ipfo_type = IPFOBJ_AUTHSTAT; 534255332Scy ipfo.ipfo_size = sizeof(ipf_authstat_t); 535145510Sdarrenr ipfo.ipfo_ptr = (void *)*frauthstpp; 536145510Sdarrenr 537170268Sdarrenr if (ioctl(auth_fd, SIOCATHST, &ipfo) == -1) { 538255332Scy ipferror(auth_fd, "ioctl(SIOCATHST)"); 539145510Sdarrenr exit(-1); 540145510Sdarrenr } 541145510Sdarrenr } 542145510Sdarrenr} 543145510Sdarrenr 544145510Sdarrenr 545145510Sdarrenr/* 546145510Sdarrenr * Build up the stats structures from data held in the "core" memory. 547145510Sdarrenr * This is mainly useful when looking at data in crash dumps and ioctl's 548145510Sdarrenr * just won't work any more. 549145510Sdarrenr */ 550145510Sdarrenrstatic void ipfstate_dead(kernel, fiopp, ipsstpp, ifrstpp, frauthstpp, frfp) 551255332Scy char *kernel; 552255332Scy friostat_t **fiopp; 553255332Scy ips_stat_t **ipsstpp; 554255332Scy ipfrstat_t **ifrstpp; 555255332Scy ipf_authstat_t **frauthstpp; 556255332Scy u_32_t *frfp; 557145510Sdarrenr{ 558255332Scy static ipf_authstat_t frauthst, *frauthstp; 559255332Scy static ipftq_t ipstcptab[IPF_TCP_NSTATES]; 560145510Sdarrenr static ips_stat_t ipsst, *ipsstp; 561145510Sdarrenr static ipfrstat_t ifrst, *ifrstp; 562145510Sdarrenr static friostat_t fio, *fiop; 563145510Sdarrenr int temp; 564145510Sdarrenr 565145510Sdarrenr void *rules[2][2]; 566170268Sdarrenr struct nlist deadlist[44] = { 567255332Scy { "ipf_auth_stats", 0, 0, 0, 0 }, /* 0 */ 568255332Scy { "fae_list", 0, 0, 0, 0 }, 569255332Scy { "ipauth", 0, 0, 0, 0 }, 570255332Scy { "ipf_auth_list", 0, 0, 0, 0 }, 571255332Scy { "ipf_auth_start", 0, 0, 0, 0 }, 572255332Scy { "ipf_auth_end", 0, 0, 0, 0 }, /* 5 */ 573255332Scy { "ipf_auth_next", 0, 0, 0, 0 }, 574255332Scy { "ipf_auth", 0, 0, 0, 0 }, 575255332Scy { "ipf_auth_used", 0, 0, 0, 0 }, 576255332Scy { "ipf_auth_size", 0, 0, 0, 0 }, 577255332Scy { "ipf_auth_defaultage", 0, 0, 0, 0 }, /* 10 */ 578255332Scy { "ipf_auth_pkts", 0, 0, 0, 0 }, 579255332Scy { "ipf_auth_lock", 0, 0, 0, 0 }, 580255332Scy { "frstats", 0, 0, 0, 0 }, 581255332Scy { "ips_stats", 0, 0, 0, 0 }, 582255332Scy { "ips_num", 0, 0, 0, 0 }, /* 15 */ 583255332Scy { "ips_wild", 0, 0, 0, 0 }, 584255332Scy { "ips_list", 0, 0, 0, 0 }, 585255332Scy { "ips_table", 0, 0, 0, 0 }, 586255332Scy { "ipf_state_max", 0, 0, 0, 0 }, 587255332Scy { "ipf_state_size", 0, 0, 0, 0 }, /* 20 */ 588255332Scy { "ipf_state_doflush", 0, 0, 0, 0 }, 589255332Scy { "ipf_state_lock", 0, 0, 0, 0 }, 590255332Scy { "ipfr_heads", 0, 0, 0, 0 }, 591255332Scy { "ipfr_nattab", 0, 0, 0, 0 }, 592255332Scy { "ipfr_stats", 0, 0, 0, 0 }, /* 25 */ 593255332Scy { "ipfr_inuse", 0, 0, 0, 0 }, 594255332Scy { "ipf_ipfrttl", 0, 0, 0, 0 }, 595255332Scy { "ipf_frag_lock", 0, 0, 0, 0 }, 596255332Scy { "ipfr_timer_id", 0, 0, 0, 0 }, 597255332Scy { "ipf_nat_lock", 0, 0, 0, 0 }, /* 30 */ 598255332Scy { "ipf_rules", 0, 0, 0, 0 }, 599255332Scy { "ipf_acct", 0, 0, 0, 0 }, 600255332Scy { "ipl_frouteok", 0, 0, 0, 0 }, 601255332Scy { "ipf_running", 0, 0, 0, 0 }, 602255332Scy { "ipf_groups", 0, 0, 0, 0 }, /* 35 */ 603255332Scy { "ipf_active", 0, 0, 0, 0 }, 604255332Scy { "ipf_pass", 0, 0, 0, 0 }, 605255332Scy { "ipf_flags", 0, 0, 0, 0 }, 606255332Scy { "ipf_state_logging", 0, 0, 0, 0 }, 607255332Scy { "ips_tqtqb", 0, 0, 0, 0 }, /* 40 */ 608255332Scy { NULL, 0, 0, 0, 0 } 609145510Sdarrenr }; 610145510Sdarrenr 611145510Sdarrenr 612145510Sdarrenr frauthstp = &frauthst; 613145510Sdarrenr ipsstp = &ipsst; 614145510Sdarrenr ifrstp = &ifrst; 615145510Sdarrenr fiop = &fio; 616145510Sdarrenr 617145510Sdarrenr *frfp = 0; 618145510Sdarrenr *fiopp = fiop; 619145510Sdarrenr *ipsstpp = ipsstp; 620145510Sdarrenr *ifrstpp = ifrstp; 621145510Sdarrenr *frauthstpp = frauthstp; 622145510Sdarrenr 623145510Sdarrenr bzero((char *)fiop, sizeof(*fiop)); 624145510Sdarrenr bzero((char *)ipsstp, sizeof(*ipsstp)); 625145510Sdarrenr bzero((char *)ifrstp, sizeof(*ifrstp)); 626145510Sdarrenr bzero((char *)frauthstp, sizeof(*frauthstp)); 627145510Sdarrenr 628145510Sdarrenr if (nlist(kernel, deadlist) == -1) { 629145510Sdarrenr fprintf(stderr, "nlist error\n"); 630145510Sdarrenr return; 631145510Sdarrenr } 632145510Sdarrenr 633145510Sdarrenr /* 634145510Sdarrenr * This is for SIOCGETFF. 635145510Sdarrenr */ 636145510Sdarrenr kmemcpy((char *)frfp, (u_long)deadlist[40].n_value, sizeof(*frfp)); 637145510Sdarrenr 638145510Sdarrenr /* 639145510Sdarrenr * f_locks is a combination of the lock variable from each part of 640145510Sdarrenr * ipfilter (state, auth, nat, fragments). 641145510Sdarrenr */ 642145510Sdarrenr kmemcpy((char *)fiop, (u_long)deadlist[13].n_value, sizeof(*fiop)); 643145510Sdarrenr kmemcpy((char *)&fiop->f_locks[0], (u_long)deadlist[22].n_value, 644145510Sdarrenr sizeof(fiop->f_locks[0])); 645145510Sdarrenr kmemcpy((char *)&fiop->f_locks[0], (u_long)deadlist[30].n_value, 646145510Sdarrenr sizeof(fiop->f_locks[1])); 647145510Sdarrenr kmemcpy((char *)&fiop->f_locks[2], (u_long)deadlist[28].n_value, 648145510Sdarrenr sizeof(fiop->f_locks[2])); 649145510Sdarrenr kmemcpy((char *)&fiop->f_locks[3], (u_long)deadlist[12].n_value, 650145510Sdarrenr sizeof(fiop->f_locks[3])); 651145510Sdarrenr 652145510Sdarrenr /* 653145510Sdarrenr * Get pointers to each list of rules (active, inactive, in, out) 654145510Sdarrenr */ 655145510Sdarrenr kmemcpy((char *)&rules, (u_long)deadlist[31].n_value, sizeof(rules)); 656145510Sdarrenr fiop->f_fin[0] = rules[0][0]; 657145510Sdarrenr fiop->f_fin[1] = rules[0][1]; 658145510Sdarrenr fiop->f_fout[0] = rules[1][0]; 659145510Sdarrenr fiop->f_fout[1] = rules[1][1]; 660145510Sdarrenr 661145510Sdarrenr /* 662145510Sdarrenr * Now get accounting rules pointers. 663145510Sdarrenr */ 664145510Sdarrenr kmemcpy((char *)&rules, (u_long)deadlist[33].n_value, sizeof(rules)); 665145510Sdarrenr fiop->f_acctin[0] = rules[0][0]; 666145510Sdarrenr fiop->f_acctin[1] = rules[0][1]; 667145510Sdarrenr fiop->f_acctout[0] = rules[1][0]; 668145510Sdarrenr fiop->f_acctout[1] = rules[1][1]; 669145510Sdarrenr 670145510Sdarrenr /* 671145510Sdarrenr * A collection of "global" variables used inside the kernel which 672145510Sdarrenr * are all collected in friostat_t via ioctl. 673145510Sdarrenr */ 674255332Scy kmemcpy((char *)&fiop->f_froute, (u_long)deadlist[33].n_value, 675145510Sdarrenr sizeof(fiop->f_froute)); 676255332Scy kmemcpy((char *)&fiop->f_running, (u_long)deadlist[34].n_value, 677145510Sdarrenr sizeof(fiop->f_running)); 678255332Scy kmemcpy((char *)&fiop->f_groups, (u_long)deadlist[35].n_value, 679145510Sdarrenr sizeof(fiop->f_groups)); 680255332Scy kmemcpy((char *)&fiop->f_active, (u_long)deadlist[36].n_value, 681145510Sdarrenr sizeof(fiop->f_active)); 682255332Scy kmemcpy((char *)&fiop->f_defpass, (u_long)deadlist[37].n_value, 683145510Sdarrenr sizeof(fiop->f_defpass)); 684145510Sdarrenr 685145510Sdarrenr /* 686145510Sdarrenr * Build up the state information stats structure. 687145510Sdarrenr */ 688145510Sdarrenr kmemcpy((char *)ipsstp, (u_long)deadlist[14].n_value, sizeof(*ipsstp)); 689145510Sdarrenr kmemcpy((char *)&temp, (u_long)deadlist[15].n_value, sizeof(temp)); 690255332Scy kmemcpy((char *)ipstcptab, (u_long)deadlist[40].n_value, 691255332Scy sizeof(ipstcptab)); 692145510Sdarrenr ipsstp->iss_active = temp; 693145510Sdarrenr ipsstp->iss_table = (void *)deadlist[18].n_value; 694145510Sdarrenr ipsstp->iss_list = (void *)deadlist[17].n_value; 695255332Scy ipsstp->iss_tcptab = ipstcptab; 696145510Sdarrenr 697145510Sdarrenr /* 698145510Sdarrenr * Build up the authentiation information stats structure. 699145510Sdarrenr */ 700145510Sdarrenr kmemcpy((char *)frauthstp, (u_long)deadlist[0].n_value, 701145510Sdarrenr sizeof(*frauthstp)); 702145510Sdarrenr frauthstp->fas_faelist = (void *)deadlist[1].n_value; 703145510Sdarrenr 704145510Sdarrenr /* 705145510Sdarrenr * Build up the fragment information stats structure. 706145510Sdarrenr */ 707145510Sdarrenr kmemcpy((char *)ifrstp, (u_long)deadlist[25].n_value, 708145510Sdarrenr sizeof(*ifrstp)); 709145510Sdarrenr ifrstp->ifs_table = (void *)deadlist[23].n_value; 710145510Sdarrenr ifrstp->ifs_nattab = (void *)deadlist[24].n_value; 711145510Sdarrenr kmemcpy((char *)&ifrstp->ifs_inuse, (u_long)deadlist[26].n_value, 712145510Sdarrenr sizeof(ifrstp->ifs_inuse)); 713145510Sdarrenr 714145510Sdarrenr /* 715145510Sdarrenr * Get logging on/off switches 716145510Sdarrenr */ 717145510Sdarrenr kmemcpy((char *)&state_logging, (u_long)deadlist[41].n_value, 718145510Sdarrenr sizeof(state_logging)); 719145510Sdarrenr} 720145510Sdarrenr 721145510Sdarrenr 722255332Scystatic void printside(side, frs) 723255332Scy char *side; 724255332Scy ipf_statistics_t *frs; 725255332Scy{ 726255332Scy int i; 727255332Scy 728255332Scy PRINTF("%lu\t%s bad packets\n", frs->fr_bad, side); 729255332Scy#ifdef USE_INET6 730255332Scy PRINTF("%lu\t%s IPv6 packets\n", frs->fr_ipv6, side); 731255332Scy#endif 732255332Scy PRINTF("%lu\t%s packets blocked\n", frs->fr_block, side); 733255332Scy PRINTF("%lu\t%s packets passed\n", frs->fr_pass, side); 734255332Scy PRINTF("%lu\t%s packets not matched\n", frs->fr_nom, side); 735255332Scy PRINTF("%lu\t%s packets counted\n", frs->fr_acct, side); 736255332Scy PRINTF("%lu\t%s packets short\n", frs->fr_short, side); 737255332Scy PRINTF("%lu\t%s packets logged and blocked\n", frs->fr_bpkl, side); 738255332Scy PRINTF("%lu\t%s packets logged and passed\n", frs->fr_ppkl, side); 739255332Scy PRINTF("%lu\t%s fragment state kept\n", frs->fr_nfr, side); 740255332Scy PRINTF("%lu\t%s fragment state lost\n", frs->fr_bnfr, side); 741255332Scy PRINTF("%lu\t%s packet state kept\n", frs->fr_ads, side); 742255332Scy PRINTF("%lu\t%s packet state lost\n", frs->fr_bads, side); 743255332Scy PRINTF("%lu\t%s invalid source\n", frs->fr_v4_badsrc, side); 744255332Scy PRINTF("%lu\t%s cache hits\n", frs->fr_chit, side); 745255332Scy PRINTF("%lu\t%s cache misses\n", frs->fr_cmiss, side); 746255332Scy PRINTF("%lu\t%s bad coalesces\n", frs->fr_badcoalesces, side); 747255332Scy PRINTF("%lu\t%s pullups succeeded\n", frs->fr_pull[0], side); 748255332Scy PRINTF("%lu\t%s pullups failed\n", frs->fr_pull[1], side); 749255332Scy PRINTF("%lu\t%s TCP checksum failures\n", frs->fr_tcpbad, side); 750255332Scy for (i = 0; i <= FRB_MAX_VALUE; i++) 751255332Scy PRINTF("%lu\t%s block reason %s\n", 752255332Scy frs->fr_blocked[i], side, blockreasons[i]); 753255332Scy} 754255332Scy 755255332Scy 756145510Sdarrenr/* 757145510Sdarrenr * Display the kernel stats for packets blocked and passed and other 758145510Sdarrenr * associated running totals which are kept. 759145510Sdarrenr */ 760145510Sdarrenrstatic void showstats(fp, frf) 761255332Scy struct friostat *fp; 762255332Scy u_32_t frf; 763145510Sdarrenr{ 764255332Scy printside("input", &fp->f_st[0]); 765255332Scy printside("output", &fp->f_st[1]); 766145510Sdarrenr 767255332Scy PRINTF("%lu\tpackets logged\n", fp->f_log_ok); 768255332Scy PRINTF("%lu\tlog failures\n", fp->f_log_fail); 769255332Scy PRINTF("%lu\tred-black no memory\n", fp->f_rb_no_mem); 770255332Scy PRINTF("%lu\tred-black node maximum\n", fp->f_rb_node_max); 771255332Scy PRINTF("%lu\tICMP replies sent\n", fp->f_st[0].fr_ret); 772255332Scy PRINTF("%lu\tTCP RSTs sent\n", fp->f_st[1].fr_ret); 773255332Scy PRINTF("%lu\tfastroute successes\n", fp->f_froute[0]); 774255332Scy PRINTF("%lu\tfastroute failures\n", fp->f_froute[1]); 775255332Scy PRINTF("%u\tIPF Ticks\n", fp->f_ticks); 776145510Sdarrenr 777255332Scy PRINTF("%x\tPacket log flags set:\n", frf); 778145510Sdarrenr if (frf & FF_LOGPASS) 779145510Sdarrenr PRINTF("\tpackets passed through filter\n"); 780145510Sdarrenr if (frf & FF_LOGBLOCK) 781145510Sdarrenr PRINTF("\tpackets blocked by filter\n"); 782145510Sdarrenr if (frf & FF_LOGNOMATCH) 783145510Sdarrenr PRINTF("\tpackets not matched by filter\n"); 784145510Sdarrenr if (!frf) 785145510Sdarrenr PRINTF("\tnone\n"); 786145510Sdarrenr} 787145510Sdarrenr 788145510Sdarrenr 789145510Sdarrenr/* 790145510Sdarrenr * Print out a list of rules from the kernel, starting at the one passed. 791145510Sdarrenr */ 792255332Scystatic int 793255332Scyprintlivelist(fiop, out, set, fp, group, comment) 794255332Scy struct friostat *fiop; 795255332Scy int out, set; 796255332Scy frentry_t *fp; 797255332Scy char *group, *comment; 798145510Sdarrenr{ 799170268Sdarrenr struct frentry fb; 800170268Sdarrenr ipfruleiter_t rule; 801170268Sdarrenr frentry_t zero; 802170268Sdarrenr frgroup_t *g; 803170268Sdarrenr ipfobj_t obj; 804255332Scy int rules; 805255332Scy int num; 806145510Sdarrenr 807255332Scy rules = 0; 808170268Sdarrenr 809170268Sdarrenr rule.iri_inout = out; 810170268Sdarrenr rule.iri_active = set; 811170268Sdarrenr rule.iri_rule = &fb; 812170268Sdarrenr rule.iri_nrules = 1; 813170268Sdarrenr if (group != NULL) 814170268Sdarrenr strncpy(rule.iri_group, group, FR_GROUPLEN); 815170268Sdarrenr else 816170268Sdarrenr rule.iri_group[0] = '\0'; 817170268Sdarrenr 818170268Sdarrenr bzero((char *)&zero, sizeof(zero)); 819170268Sdarrenr 820170268Sdarrenr bzero((char *)&obj, sizeof(obj)); 821170268Sdarrenr obj.ipfo_rev = IPFILTER_VERSION; 822170268Sdarrenr obj.ipfo_type = IPFOBJ_IPFITER; 823170268Sdarrenr obj.ipfo_size = sizeof(rule); 824170268Sdarrenr obj.ipfo_ptr = &rule; 825170268Sdarrenr 826255332Scy while (rule.iri_rule != NULL) { 827170268Sdarrenr u_long array[1000]; 828170268Sdarrenr 829170268Sdarrenr memset(array, 0xff, sizeof(array)); 830170268Sdarrenr fp = (frentry_t *)array; 831170268Sdarrenr rule.iri_rule = fp; 832170268Sdarrenr if (ioctl(ipf_fd, SIOCIPFITER, &obj) == -1) { 833255332Scy ipferror(ipf_fd, "ioctl(SIOCIPFITER)"); 834255332Scy num = IPFGENITER_IPF; 835255332Scy (void) ioctl(ipf_fd,SIOCIPFDELTOK, &num); 836255332Scy return rules; 837145510Sdarrenr } 838170268Sdarrenr if (bcmp(fp, &zero, sizeof(zero)) == 0) 839170268Sdarrenr break; 840255332Scy if (rule.iri_rule == NULL) 841255332Scy break; 842255332Scy#ifdef USE_INET6 843255332Scy if (use_inet6 != 0) { 844255332Scy if (fp->fr_family != 0 && fp->fr_family != AF_INET6) 845255332Scy continue; 846255332Scy } else 847255332Scy#endif 848255332Scy { 849255332Scy if (fp->fr_family != 0 && fp->fr_family != AF_INET) 850255332Scy continue; 851255332Scy } 852170268Sdarrenr if (fp->fr_data != NULL) 853255332Scy fp->fr_data = (char *)fp + fp->fr_size; 854170268Sdarrenr 855255332Scy rules++; 856170268Sdarrenr 857255332Scy if (opts & (OPT_HITS|OPT_DEBUG)) 858145510Sdarrenr#ifdef USE_QUAD_T 859255332Scy PRINTF("%"PRIu64" ", (unsigned long long) fp->fr_hits); 860145510Sdarrenr#else 861145510Sdarrenr PRINTF("%lu ", fp->fr_hits); 862145510Sdarrenr#endif 863255332Scy if (opts & (OPT_ACCNT|OPT_DEBUG)) 864145510Sdarrenr#ifdef USE_QUAD_T 865255332Scy PRINTF("%"PRIu64" ", (unsigned long long) fp->fr_bytes); 866145510Sdarrenr#else 867145510Sdarrenr PRINTF("%lu ", fp->fr_bytes); 868145510Sdarrenr#endif 869145510Sdarrenr if (opts & OPT_SHOWLINENO) 870255332Scy PRINTF("@%d ", rules); 871170268Sdarrenr 872255332Scy if (fp->fr_die != 0) 873255332Scy fp->fr_die -= fiop->f_ticks; 874255332Scy 875170268Sdarrenr printfr(fp, ioctl); 876170268Sdarrenr if (opts & OPT_DEBUG) { 877255332Scy binprint(fp, fp->fr_size); 878170268Sdarrenr if (fp->fr_data != NULL && fp->fr_dsize > 0) 879170268Sdarrenr binprint(fp->fr_data, fp->fr_dsize); 880170268Sdarrenr } 881255332Scy if (fp->fr_grhead != -1) { 882170268Sdarrenr for (g = grtop; g != NULL; g = g->fg_next) { 883255332Scy if (!strncmp(fp->fr_names + fp->fr_grhead, 884255332Scy g->fg_name, 885170268Sdarrenr FR_GROUPLEN)) 886170268Sdarrenr break; 887170268Sdarrenr } 888170268Sdarrenr if (g == NULL) { 889170268Sdarrenr g = calloc(1, sizeof(*g)); 890170268Sdarrenr 891170268Sdarrenr if (g != NULL) { 892255332Scy strncpy(g->fg_name, 893255332Scy fp->fr_names + fp->fr_grhead, 894170268Sdarrenr FR_GROUPLEN); 895170268Sdarrenr if (grtop == NULL) { 896170268Sdarrenr grtop = g; 897170268Sdarrenr grtail = g; 898170268Sdarrenr } else { 899170268Sdarrenr grtail->fg_next = g; 900170268Sdarrenr grtail = g; 901170268Sdarrenr } 902170268Sdarrenr } 903170268Sdarrenr } 904170268Sdarrenr } 905170268Sdarrenr if (fp->fr_type == FR_T_CALLFUNC) { 906255332Scy rules += printlivelist(fiop, out, set, fp->fr_data, 907255332Scy group, "# callfunc: "); 908170268Sdarrenr } 909255332Scy } 910170268Sdarrenr 911255332Scy num = IPFGENITER_IPF; 912255332Scy (void) ioctl(ipf_fd,SIOCIPFDELTOK, &num); 913170268Sdarrenr 914255332Scy return rules; 915170268Sdarrenr} 916170268Sdarrenr 917170268Sdarrenr 918255332Scystatic void printdeadlist(fiop, out, set, fp, group, comment) 919255332Scy friostat_t *fiop; 920255332Scy int out, set; 921255332Scy frentry_t *fp; 922255332Scy char *group, *comment; 923170268Sdarrenr{ 924170268Sdarrenr frgroup_t *grtop, *grtail, *g; 925170268Sdarrenr struct frentry fb; 926170268Sdarrenr char *data; 927170268Sdarrenr u_32_t type; 928170268Sdarrenr int n; 929170268Sdarrenr 930170268Sdarrenr fb.fr_next = fp; 931170268Sdarrenr n = 0; 932170268Sdarrenr grtop = NULL; 933170268Sdarrenr grtail = NULL; 934170268Sdarrenr 935255332Scy for (n = 1; fp; fp = fb.fr_next, n++) { 936170268Sdarrenr if (kmemcpy((char *)&fb, (u_long)fb.fr_next, 937255332Scy fb.fr_size) == -1) { 938170268Sdarrenr perror("kmemcpy"); 939170268Sdarrenr return; 940170268Sdarrenr } 941255332Scy fp = &fb; 942255332Scy if (use_inet6 != 0) { 943255332Scy if (fp->fr_family != 0 && fp->fr_family != 6) 944255332Scy continue; 945255332Scy } else { 946255332Scy if (fp->fr_family != 0 && fp->fr_family != 4) 947255332Scy continue; 948255332Scy } 949170268Sdarrenr 950145510Sdarrenr data = NULL; 951170268Sdarrenr type = fb.fr_type & ~FR_T_BUILTIN; 952145510Sdarrenr if (type == FR_T_IPF || type == FR_T_BPFOPC) { 953170268Sdarrenr if (fb.fr_dsize) { 954170268Sdarrenr data = malloc(fb.fr_dsize); 955145510Sdarrenr 956170268Sdarrenr if (kmemcpy(data, (u_long)fb.fr_data, 957170268Sdarrenr fb.fr_dsize) == -1) { 958145510Sdarrenr perror("kmemcpy"); 959145510Sdarrenr return; 960145510Sdarrenr } 961170268Sdarrenr fb.fr_data = data; 962145510Sdarrenr } 963145510Sdarrenr } 964145510Sdarrenr 965255332Scy if (opts & OPT_HITS) 966170268Sdarrenr#ifdef USE_QUAD_T 967255332Scy PRINTF("%"PRIu64" ", (unsigned long long) fb.fr_hits); 968170268Sdarrenr#else 969170268Sdarrenr PRINTF("%lu ", fb.fr_hits); 970170268Sdarrenr#endif 971255332Scy if (opts & OPT_ACCNT) 972170268Sdarrenr#ifdef USE_QUAD_T 973255332Scy PRINTF("%"PRIu64" ", (unsigned long long) fb.fr_bytes); 974170268Sdarrenr#else 975170268Sdarrenr PRINTF("%lu ", fb.fr_bytes); 976170268Sdarrenr#endif 977170268Sdarrenr if (opts & OPT_SHOWLINENO) 978170268Sdarrenr PRINTF("@%d ", n); 979170268Sdarrenr 980145510Sdarrenr printfr(fp, ioctl); 981145510Sdarrenr if (opts & OPT_DEBUG) { 982255332Scy binprint(fp, fp->fr_size); 983170268Sdarrenr if (fb.fr_data != NULL && fb.fr_dsize > 0) 984170268Sdarrenr binprint(fb.fr_data, fb.fr_dsize); 985145510Sdarrenr } 986145510Sdarrenr if (data != NULL) 987145510Sdarrenr free(data); 988255332Scy if (fb.fr_grhead != -1) { 989170268Sdarrenr g = calloc(1, sizeof(*g)); 990170268Sdarrenr 991170268Sdarrenr if (g != NULL) { 992255332Scy strncpy(g->fg_name, fb.fr_names + fb.fr_grhead, 993170268Sdarrenr FR_GROUPLEN); 994170268Sdarrenr if (grtop == NULL) { 995170268Sdarrenr grtop = g; 996170268Sdarrenr grtail = g; 997170268Sdarrenr } else { 998170268Sdarrenr grtail->fg_next = g; 999170268Sdarrenr grtail = g; 1000170268Sdarrenr } 1001170268Sdarrenr } 1002145510Sdarrenr } 1003145510Sdarrenr if (type == FR_T_CALLFUNC) { 1004255332Scy printdeadlist(fiop, out, set, fb.fr_data, group, 1005170268Sdarrenr "# callfunc: "); 1006145510Sdarrenr } 1007255332Scy } 1008170268Sdarrenr 1009170268Sdarrenr while ((g = grtop) != NULL) { 1010255332Scy printdeadlist(fiop, out, set, NULL, g->fg_name, comment); 1011170268Sdarrenr grtop = g->fg_next; 1012170268Sdarrenr free(g); 1013145510Sdarrenr } 1014145510Sdarrenr} 1015145510Sdarrenr 1016145510Sdarrenr/* 1017145510Sdarrenr * print out all of the asked for rule sets, using the stats struct as 1018145510Sdarrenr * the base from which to get the pointers. 1019145510Sdarrenr */ 1020145510Sdarrenrstatic void showlist(fiop) 1021255332Scy struct friostat *fiop; 1022145510Sdarrenr{ 1023145510Sdarrenr struct frentry *fp = NULL; 1024145510Sdarrenr int i, set; 1025145510Sdarrenr 1026145510Sdarrenr set = fiop->f_active; 1027145510Sdarrenr if (opts & OPT_INACTIVE) 1028145510Sdarrenr set = 1 - set; 1029145510Sdarrenr if (opts & OPT_ACCNT) { 1030145510Sdarrenr if (opts & OPT_OUTQUE) { 1031145510Sdarrenr i = F_ACOUT; 1032145510Sdarrenr fp = (struct frentry *)fiop->f_acctout[set]; 1033145510Sdarrenr } else if (opts & OPT_INQUE) { 1034145510Sdarrenr i = F_ACIN; 1035145510Sdarrenr fp = (struct frentry *)fiop->f_acctin[set]; 1036145510Sdarrenr } else { 1037145510Sdarrenr FPRINTF(stderr, "No -i or -o given with -a\n"); 1038145510Sdarrenr return; 1039145510Sdarrenr } 1040145510Sdarrenr } else { 1041145510Sdarrenr if (opts & OPT_OUTQUE) { 1042145510Sdarrenr i = F_OUT; 1043145510Sdarrenr fp = (struct frentry *)fiop->f_fout[set]; 1044145510Sdarrenr } else if (opts & OPT_INQUE) { 1045145510Sdarrenr i = F_IN; 1046145510Sdarrenr fp = (struct frentry *)fiop->f_fin[set]; 1047145510Sdarrenr } else 1048145510Sdarrenr return; 1049145510Sdarrenr } 1050170268Sdarrenr if (opts & OPT_DEBUG) 1051145510Sdarrenr FPRINTF(stderr, "showlist:opts %#x i %d\n", opts, i); 1052145510Sdarrenr 1053170268Sdarrenr if (opts & OPT_DEBUG) 1054145510Sdarrenr PRINTF("fp %p set %d\n", fp, set); 1055255332Scy 1056255332Scy if (live_kernel == 1) { 1057255332Scy int printed; 1058255332Scy 1059255332Scy printed = printlivelist(fiop, i, set, fp, NULL, NULL); 1060255332Scy if (printed == 0) { 1061255332Scy FPRINTF(stderr, "# empty list for %s%s\n", 1062255332Scy (opts & OPT_INACTIVE) ? "inactive " : "", 1063255332Scy filters[i]); 1064255332Scy } 1065255332Scy } else { 1066255332Scy if (!fp) { 1067255332Scy FPRINTF(stderr, "# empty list for %s%s\n", 1068255332Scy (opts & OPT_INACTIVE) ? "inactive " : "", 1069255332Scy filters[i]); 1070255332Scy } else { 1071255332Scy printdeadlist(fiop, i, set, fp, NULL, NULL); 1072255332Scy } 1073145510Sdarrenr } 1074145510Sdarrenr} 1075145510Sdarrenr 1076145510Sdarrenr 1077145510Sdarrenr/* 1078145510Sdarrenr * Display ipfilter stateful filtering information 1079145510Sdarrenr */ 1080255332Scystatic void showipstates(ipsp, filter) 1081255332Scy ips_stat_t *ipsp; 1082255332Scy int *filter; 1083145510Sdarrenr{ 1084255332Scy ipstate_t *is; 1085255332Scy int i; 1086145510Sdarrenr 1087145510Sdarrenr /* 1088145510Sdarrenr * If a list of states hasn't been asked for, only print out stats 1089145510Sdarrenr */ 1090145510Sdarrenr if (!(opts & OPT_SHOWLIST)) { 1091255332Scy showstatestats(ipsp); 1092255332Scy return; 1093255332Scy } 1094170268Sdarrenr 1095255332Scy if ((state_fields != NULL) && (nohdrfields == 0)) { 1096255332Scy for (i = 0; state_fields[i].w_value != 0; i++) { 1097255332Scy printfieldhdr(statefields, state_fields + i); 1098255332Scy if (state_fields[i + 1].w_value != 0) 1099255332Scy printf("\t"); 1100255332Scy } 1101255332Scy printf("\n"); 1102255332Scy } 1103170268Sdarrenr 1104255332Scy /* 1105255332Scy * Print out all the state information currently held in the kernel. 1106255332Scy */ 1107255332Scy for (is = ipsp->iss_list; is != NULL; ) { 1108255332Scy ipstate_t ips; 1109170268Sdarrenr 1110255332Scy is = fetchstate(is, &ips); 1111170268Sdarrenr 1112255332Scy if (is == NULL) 1113255332Scy break; 1114255332Scy 1115255332Scy is = ips.is_next; 1116255332Scy if ((filter != NULL) && 1117255332Scy (state_matcharray(&ips, filter) == 0)) { 1118255332Scy continue; 1119255332Scy } 1120255332Scy if (state_fields != NULL) { 1121255332Scy for (i = 0; state_fields[i].w_value != 0; i++) { 1122255332Scy printstatefield(&ips, state_fields[i].w_value); 1123255332Scy if (state_fields[i + 1].w_value != 0) 1124255332Scy printf("\t"); 1125170268Sdarrenr } 1126255332Scy printf("\n"); 1127170268Sdarrenr } else { 1128255332Scy printstate(&ips, opts, ipsp->iss_ticks); 1129170268Sdarrenr } 1130255332Scy } 1131255332Scy} 1132170268Sdarrenr 1133145510Sdarrenr 1134255332Scystatic void showstatestats(ipsp) 1135255332Scy ips_stat_t *ipsp; 1136255332Scy{ 1137255332Scy int minlen, maxlen, totallen; 1138255332Scy ipftable_t table; 1139255332Scy u_int *buckets; 1140255332Scy ipfobj_t obj; 1141255332Scy int i, sz; 1142145510Sdarrenr 1143255332Scy /* 1144255332Scy * If a list of states hasn't been asked for, only print out stats 1145255332Scy */ 1146145510Sdarrenr 1147255332Scy sz = sizeof(*buckets) * ipsp->iss_state_size; 1148255332Scy buckets = (u_int *)malloc(sz); 1149145510Sdarrenr 1150255332Scy obj.ipfo_rev = IPFILTER_VERSION; 1151255332Scy obj.ipfo_type = IPFOBJ_GTABLE; 1152255332Scy obj.ipfo_size = sizeof(table); 1153255332Scy obj.ipfo_ptr = &table; 1154255332Scy 1155255332Scy table.ita_type = IPFTABLE_BUCKETS; 1156255332Scy table.ita_table = buckets; 1157255332Scy 1158255332Scy if (live_kernel == 1) { 1159255332Scy if (ioctl(state_fd, SIOCGTABL, &obj) != 0) { 1160255332Scy free(buckets); 1161255332Scy return; 1162145510Sdarrenr } 1163255332Scy } else { 1164255332Scy if (kmemcpy((char *)buckets, 1165255332Scy (u_long)ipsp->iss_bucketlen, sz)) { 1166255332Scy free(buckets); 1167255332Scy return; 1168255332Scy } 1169255332Scy } 1170145510Sdarrenr 1171255332Scy PRINTF("%u\tactive state table entries\n",ipsp->iss_active); 1172255332Scy PRINTF("%lu\tadd bad\n", ipsp->iss_add_bad); 1173255332Scy PRINTF("%lu\tadd duplicate\n", ipsp->iss_add_dup); 1174255332Scy PRINTF("%lu\tadd locked\n", ipsp->iss_add_locked); 1175255332Scy PRINTF("%lu\tadd oow\n", ipsp->iss_add_oow); 1176255332Scy PRINTF("%lu\tbucket full\n", ipsp->iss_bucket_full); 1177255332Scy PRINTF("%lu\tcheck bad\n", ipsp->iss_check_bad); 1178255332Scy PRINTF("%lu\tcheck miss\n", ipsp->iss_check_miss); 1179255332Scy PRINTF("%lu\tcheck nattag\n", ipsp->iss_check_nattag); 1180255332Scy PRINTF("%lu\tclone nomem\n", ipsp->iss_clone_nomem); 1181255332Scy PRINTF("%lu\tcheck notag\n", ipsp->iss_check_notag); 1182255332Scy PRINTF("%lu\tcheck success\n", ipsp->iss_hits); 1183255332Scy PRINTF("%lu\tcloned\n", ipsp->iss_cloned); 1184255332Scy PRINTF("%lu\texpired\n", ipsp->iss_expire); 1185255332Scy PRINTF("%lu\tflush all\n", ipsp->iss_flush_all); 1186255332Scy PRINTF("%lu\tflush closing\n", ipsp->iss_flush_closing); 1187255332Scy PRINTF("%lu\tflush queue\n", ipsp->iss_flush_queue); 1188255332Scy PRINTF("%lu\tflush state\n", ipsp->iss_flush_state); 1189255332Scy PRINTF("%lu\tflush timeout\n", ipsp->iss_flush_timeout); 1190255332Scy PRINTF("%u\thash buckets in use\n", ipsp->iss_inuse); 1191255332Scy PRINTF("%lu\tICMP bad\n", ipsp->iss_icmp_bad); 1192255332Scy PRINTF("%lu\tICMP banned\n", ipsp->iss_icmp_banned); 1193255332Scy PRINTF("%lu\tICMP errors\n", ipsp->iss_icmp_icmperr); 1194255332Scy PRINTF("%lu\tICMP head block\n", ipsp->iss_icmp_headblock); 1195255332Scy PRINTF("%lu\tICMP hits\n", ipsp->iss_icmp_hits); 1196255332Scy PRINTF("%lu\tICMP not query\n", ipsp->iss_icmp_notquery); 1197255332Scy PRINTF("%lu\tICMP short\n", ipsp->iss_icmp_short); 1198255332Scy PRINTF("%lu\tICMP too many\n", ipsp->iss_icmp_toomany); 1199255332Scy PRINTF("%lu\tICMPv6 errors\n", ipsp->iss_icmp6_icmperr); 1200255332Scy PRINTF("%lu\tICMPv6 miss\n", ipsp->iss_icmp6_miss); 1201255332Scy PRINTF("%lu\tICMPv6 not info\n", ipsp->iss_icmp6_notinfo); 1202255332Scy PRINTF("%lu\tICMPv6 not query\n", ipsp->iss_icmp6_notquery); 1203255332Scy PRINTF("%lu\tlog fail\n", ipsp->iss_log_fail); 1204255332Scy PRINTF("%lu\tlog ok\n", ipsp->iss_log_ok); 1205255332Scy PRINTF("%lu\tlookup interface mismatch\n", ipsp->iss_lookup_badifp); 1206255332Scy PRINTF("%lu\tlookup mask mismatch\n", ipsp->iss_miss_mask); 1207255332Scy PRINTF("%lu\tlookup port mismatch\n", ipsp->iss_lookup_badport); 1208255332Scy PRINTF("%lu\tlookup miss\n", ipsp->iss_lookup_miss); 1209255332Scy PRINTF("%lu\tmaximum rule references\n", ipsp->iss_max_ref); 1210255332Scy PRINTF("%lu\tmaximum hosts per rule\n", ipsp->iss_max_track); 1211255332Scy PRINTF("%lu\tno memory\n", ipsp->iss_nomem); 1212255332Scy PRINTF("%lu\tout of window\n", ipsp->iss_oow); 1213255332Scy PRINTF("%lu\torphans\n", ipsp->iss_orphan); 1214255332Scy PRINTF("%lu\tscan block\n", ipsp->iss_scan_block); 1215255332Scy PRINTF("%lu\tstate table maximum reached\n", ipsp->iss_max); 1216255332Scy PRINTF("%lu\tTCP closing\n", ipsp->iss_tcp_closing); 1217255332Scy PRINTF("%lu\tTCP OOW\n", ipsp->iss_tcp_oow); 1218255332Scy PRINTF("%lu\tTCP RST add\n", ipsp->iss_tcp_rstadd); 1219255332Scy PRINTF("%lu\tTCP too small\n", ipsp->iss_tcp_toosmall); 1220255332Scy PRINTF("%lu\tTCP bad options\n", ipsp->iss_tcp_badopt); 1221255332Scy PRINTF("%lu\tTCP removed\n", ipsp->iss_fin); 1222255332Scy PRINTF("%lu\tTCP FSM\n", ipsp->iss_tcp_fsm); 1223255332Scy PRINTF("%lu\tTCP strict\n", ipsp->iss_tcp_strict); 1224255332Scy PRINTF("%lu\tTCP wild\n", ipsp->iss_wild); 1225255332Scy PRINTF("%lu\tMicrosoft Windows SACK\n", ipsp->iss_winsack); 1226145510Sdarrenr 1227255332Scy PRINTF("State logging %sabled\n", state_logging ? "en" : "dis"); 1228145510Sdarrenr 1229255332Scy PRINTF("IP states added:\n"); 1230255332Scy for (i = 0; i < 256; i++) { 1231255332Scy if (ipsp->iss_proto[i] != 0) { 1232255332Scy struct protoent *proto; 1233255332Scy 1234255332Scy proto = getprotobynumber(i); 1235255332Scy PRINTF("%lu", ipsp->iss_proto[i]); 1236255332Scy if (proto != NULL) 1237255332Scy PRINTF("\t%s\n", proto->p_name); 1238255332Scy else 1239255332Scy PRINTF("\t%d\n", i); 1240145510Sdarrenr } 1241255332Scy } 1242145510Sdarrenr 1243255332Scy PRINTF("\nState table bucket statistics:\n"); 1244255332Scy PRINTF("%u\tin use\n", ipsp->iss_inuse); 1245170268Sdarrenr 1246255332Scy minlen = ipsp->iss_max; 1247255332Scy totallen = 0; 1248255332Scy maxlen = 0; 1249170268Sdarrenr 1250255332Scy for (i = 0; i < ipsp->iss_state_size; i++) { 1251255332Scy if (buckets[i] > maxlen) 1252255332Scy maxlen = buckets[i]; 1253255332Scy if (buckets[i] < minlen) 1254255332Scy minlen = buckets[i]; 1255255332Scy totallen += buckets[i]; 1256145510Sdarrenr } 1257145510Sdarrenr 1258255332Scy PRINTF("%d\thash efficiency\n", 1259255332Scy totallen ? ipsp->iss_inuse * 100 / totallen : 0); 1260255332Scy PRINTF("%2.2f%%\tbucket usage\n%u\tminimal length\n", 1261255332Scy ((float)ipsp->iss_inuse / ipsp->iss_state_size) * 100.0, 1262255332Scy minlen); 1263255332Scy PRINTF("%u\tmaximal length\n%.3f\taverage length\n", 1264255332Scy maxlen, 1265255332Scy ipsp->iss_inuse ? (float) totallen/ ipsp->iss_inuse : 1266255332Scy 0.0); 1267170268Sdarrenr 1268255332Scy#define ENTRIES_PER_LINE 5 1269170268Sdarrenr 1270255332Scy if (opts & OPT_VERBOSE) { 1271255332Scy PRINTF("\nCurrent bucket sizes :\n"); 1272255332Scy for (i = 0; i < ipsp->iss_state_size; i++) { 1273255332Scy if ((i % ENTRIES_PER_LINE) == 0) 1274255332Scy PRINTF("\t"); 1275255332Scy PRINTF("%4d -> %4u", i, buckets[i]); 1276255332Scy if ((i % ENTRIES_PER_LINE) == 1277255332Scy (ENTRIES_PER_LINE - 1)) 1278255332Scy PRINTF("\n"); 1279255332Scy else 1280255332Scy PRINTF(" "); 1281170268Sdarrenr } 1282255332Scy PRINTF("\n"); 1283145510Sdarrenr } 1284255332Scy PRINTF("\n"); 1285255332Scy 1286255332Scy free(buckets); 1287255332Scy 1288255332Scy if (live_kernel == 1) { 1289255332Scy showtqtable_live(state_fd); 1290255332Scy } else { 1291255332Scy printtqtable(ipsp->iss_tcptab); 1292255332Scy } 1293145510Sdarrenr} 1294145510Sdarrenr 1295145510Sdarrenr 1296145510Sdarrenr#ifdef STATETOP 1297145510Sdarrenrstatic int handle_resize = 0, handle_break = 0; 1298145510Sdarrenr 1299145510Sdarrenrstatic void topipstates(saddr, daddr, sport, dport, protocol, ver, 1300255332Scy refreshtime, topclosed, filter) 1301255332Scy i6addr_t saddr; 1302255332Scy i6addr_t daddr; 1303255332Scy int sport; 1304255332Scy int dport; 1305255332Scy int protocol; 1306255332Scy int ver; 1307255332Scy int refreshtime; 1308255332Scy int topclosed; 1309255332Scy int *filter; 1310145510Sdarrenr{ 1311145510Sdarrenr char str1[STSTRSIZE], str2[STSTRSIZE], str3[STSTRSIZE], str4[STSTRSIZE]; 1312145510Sdarrenr int maxtsentries = 0, reverse = 0, sorting = STSORT_DEFAULT; 1313153881Sguido int i, j, winy, tsentry, maxx, maxy, redraw = 0, ret = 0; 1314145510Sdarrenr int len, srclen, dstlen, forward = 1, c = 0; 1315145510Sdarrenr ips_stat_t ipsst, *ipsstp = &ipsst; 1316255332Scy int token_type = IPFGENITER_STATE; 1317145510Sdarrenr statetop_t *tstable = NULL, *tp; 1318153881Sguido const char *errstr = ""; 1319145510Sdarrenr ipstate_t ips; 1320145510Sdarrenr ipfobj_t ipfo; 1321145510Sdarrenr struct timeval selecttimeout; 1322145510Sdarrenr char hostnm[HOSTNMLEN]; 1323145510Sdarrenr struct protoent *proto; 1324145510Sdarrenr fd_set readfd; 1325145510Sdarrenr time_t t; 1326145510Sdarrenr 1327145510Sdarrenr /* install signal handlers */ 1328145510Sdarrenr signal(SIGINT, sig_break); 1329145510Sdarrenr signal(SIGQUIT, sig_break); 1330145510Sdarrenr signal(SIGTERM, sig_break); 1331145510Sdarrenr signal(SIGWINCH, sig_resize); 1332145510Sdarrenr 1333145510Sdarrenr /* init ncurses stuff */ 1334145510Sdarrenr initscr(); 1335145510Sdarrenr cbreak(); 1336145510Sdarrenr noecho(); 1337145510Sdarrenr curs_set(0); 1338145510Sdarrenr timeout(0); 1339145510Sdarrenr getmaxyx(stdscr, maxy, maxx); 1340145510Sdarrenr 1341145510Sdarrenr /* init hostname */ 1342145510Sdarrenr gethostname(hostnm, sizeof(hostnm) - 1); 1343145510Sdarrenr hostnm[sizeof(hostnm) - 1] = '\0'; 1344145510Sdarrenr 1345145510Sdarrenr /* init ipfobj_t stuff */ 1346145510Sdarrenr bzero((caddr_t)&ipfo, sizeof(ipfo)); 1347145510Sdarrenr ipfo.ipfo_rev = IPFILTER_VERSION; 1348170268Sdarrenr ipfo.ipfo_type = IPFOBJ_STATESTAT; 1349145510Sdarrenr ipfo.ipfo_size = sizeof(*ipsstp); 1350145510Sdarrenr ipfo.ipfo_ptr = (void *)ipsstp; 1351145510Sdarrenr 1352145510Sdarrenr /* repeat until user aborts */ 1353145510Sdarrenr while ( 1 ) { 1354145510Sdarrenr 1355145510Sdarrenr /* get state table */ 1356145510Sdarrenr bzero((char *)&ipsst, sizeof(ipsst)); 1357145510Sdarrenr if ((ioctl(state_fd, SIOCGETFS, &ipfo) == -1)) { 1358153881Sguido errstr = "ioctl(SIOCGETFS)"; 1359153881Sguido ret = -1; 1360153881Sguido goto out; 1361145510Sdarrenr } 1362145510Sdarrenr 1363145510Sdarrenr /* clear the history */ 1364145510Sdarrenr tsentry = -1; 1365145510Sdarrenr 1366145510Sdarrenr /* reset max str len */ 1367145510Sdarrenr srclen = dstlen = 0; 1368145510Sdarrenr 1369145510Sdarrenr /* read the state table and store in tstable */ 1370145510Sdarrenr for (; ipsstp->iss_list; ipsstp->iss_list = ips.is_next) { 1371145510Sdarrenr 1372170268Sdarrenr ipsstp->iss_list = fetchstate(ipsstp->iss_list, &ips); 1373170268Sdarrenr if (ipsstp->iss_list == NULL) 1374145510Sdarrenr break; 1375145510Sdarrenr 1376145510Sdarrenr if (ips.is_v != ver) 1377145510Sdarrenr continue; 1378145510Sdarrenr 1379255332Scy if ((filter != NULL) && 1380255332Scy (state_matcharray(&ips, filter) == 0)) 1381255332Scy continue; 1382255332Scy 1383145510Sdarrenr /* check v4 src/dest addresses */ 1384145510Sdarrenr if (ips.is_v == 4) { 1385145510Sdarrenr if ((saddr.in4.s_addr != INADDR_ANY && 1386145510Sdarrenr saddr.in4.s_addr != ips.is_saddr) || 1387145510Sdarrenr (daddr.in4.s_addr != INADDR_ANY && 1388145510Sdarrenr daddr.in4.s_addr != ips.is_daddr)) 1389145510Sdarrenr continue; 1390145510Sdarrenr } 1391145510Sdarrenr#ifdef USE_INET6 1392145510Sdarrenr /* check v6 src/dest addresses */ 1393145510Sdarrenr if (ips.is_v == 6) { 1394145510Sdarrenr if ((IP6_NEQ(&saddr, &in6addr_any) && 1395145510Sdarrenr IP6_NEQ(&saddr, &ips.is_src)) || 1396145510Sdarrenr (IP6_NEQ(&daddr, &in6addr_any) && 1397145510Sdarrenr IP6_NEQ(&daddr, &ips.is_dst))) 1398145510Sdarrenr continue; 1399145510Sdarrenr } 1400145510Sdarrenr#endif 1401145510Sdarrenr /* check protocol */ 1402145510Sdarrenr if (protocol > 0 && protocol != ips.is_p) 1403145510Sdarrenr continue; 1404145510Sdarrenr 1405145510Sdarrenr /* check ports if protocol is TCP or UDP */ 1406145510Sdarrenr if (((ips.is_p == IPPROTO_TCP) || 1407145510Sdarrenr (ips.is_p == IPPROTO_UDP)) && 1408145510Sdarrenr (((sport > 0) && (htons(sport) != ips.is_sport)) || 1409145510Sdarrenr ((dport > 0) && (htons(dport) != ips.is_dport)))) 1410145510Sdarrenr continue; 1411145510Sdarrenr 1412145510Sdarrenr /* show closed TCP sessions ? */ 1413145510Sdarrenr if ((topclosed == 0) && (ips.is_p == IPPROTO_TCP) && 1414145510Sdarrenr (ips.is_state[0] >= IPF_TCPS_LAST_ACK) && 1415145510Sdarrenr (ips.is_state[1] >= IPF_TCPS_LAST_ACK)) 1416145510Sdarrenr continue; 1417145510Sdarrenr 1418145510Sdarrenr /* 1419145510Sdarrenr * if necessary make room for this state 1420145510Sdarrenr * entry 1421145510Sdarrenr */ 1422145510Sdarrenr tsentry++; 1423145510Sdarrenr if (!maxtsentries || tsentry == maxtsentries) { 1424145510Sdarrenr maxtsentries += STGROWSIZE; 1425145510Sdarrenr tstable = realloc(tstable, 1426145510Sdarrenr maxtsentries * sizeof(statetop_t)); 1427145510Sdarrenr if (tstable == NULL) { 1428145510Sdarrenr perror("realloc"); 1429145510Sdarrenr exit(-1); 1430145510Sdarrenr } 1431145510Sdarrenr } 1432145510Sdarrenr 1433145510Sdarrenr /* get max src/dest address string length */ 1434145510Sdarrenr len = strlen(getip(ips.is_v, &ips.is_src)); 1435145510Sdarrenr if (srclen < len) 1436145510Sdarrenr srclen = len; 1437145510Sdarrenr len = strlen(getip(ips.is_v, &ips.is_dst)); 1438145510Sdarrenr if (dstlen < len) 1439145510Sdarrenr dstlen = len; 1440145510Sdarrenr 1441145510Sdarrenr /* fill structure */ 1442145510Sdarrenr tp = tstable + tsentry; 1443145510Sdarrenr tp->st_src = ips.is_src; 1444145510Sdarrenr tp->st_dst = ips.is_dst; 1445145510Sdarrenr tp->st_p = ips.is_p; 1446145510Sdarrenr tp->st_v = ips.is_v; 1447145510Sdarrenr tp->st_state[0] = ips.is_state[0]; 1448145510Sdarrenr tp->st_state[1] = ips.is_state[1]; 1449145510Sdarrenr if (forward) { 1450145510Sdarrenr tp->st_pkts = ips.is_pkts[0]+ips.is_pkts[1]; 1451145510Sdarrenr tp->st_bytes = ips.is_bytes[0]+ips.is_bytes[1]; 1452145510Sdarrenr } else { 1453145510Sdarrenr tp->st_pkts = ips.is_pkts[2]+ips.is_pkts[3]; 1454145510Sdarrenr tp->st_bytes = ips.is_bytes[2]+ips.is_bytes[3]; 1455145510Sdarrenr } 1456145510Sdarrenr tp->st_age = ips.is_die - ipsstp->iss_ticks; 1457145510Sdarrenr if ((ips.is_p == IPPROTO_TCP) || 1458145510Sdarrenr (ips.is_p == IPPROTO_UDP)) { 1459145510Sdarrenr tp->st_sport = ips.is_sport; 1460145510Sdarrenr tp->st_dport = ips.is_dport; 1461145510Sdarrenr } 1462145510Sdarrenr } 1463145510Sdarrenr 1464255332Scy (void) ioctl(state_fd, SIOCIPFDELTOK, &token_type); 1465145510Sdarrenr 1466145510Sdarrenr /* sort the array */ 1467145510Sdarrenr if (tsentry != -1) { 1468145510Sdarrenr switch (sorting) 1469145510Sdarrenr { 1470145510Sdarrenr case STSORT_PR: 1471145510Sdarrenr qsort(tstable, tsentry + 1, 1472145510Sdarrenr sizeof(statetop_t), sort_p); 1473145510Sdarrenr break; 1474145510Sdarrenr case STSORT_PKTS: 1475145510Sdarrenr qsort(tstable, tsentry + 1, 1476145510Sdarrenr sizeof(statetop_t), sort_pkts); 1477145510Sdarrenr break; 1478145510Sdarrenr case STSORT_BYTES: 1479145510Sdarrenr qsort(tstable, tsentry + 1, 1480145510Sdarrenr sizeof(statetop_t), sort_bytes); 1481145510Sdarrenr break; 1482145510Sdarrenr case STSORT_TTL: 1483145510Sdarrenr qsort(tstable, tsentry + 1, 1484145510Sdarrenr sizeof(statetop_t), sort_ttl); 1485145510Sdarrenr break; 1486145510Sdarrenr case STSORT_SRCIP: 1487145510Sdarrenr qsort(tstable, tsentry + 1, 1488145510Sdarrenr sizeof(statetop_t), sort_srcip); 1489145510Sdarrenr break; 1490145510Sdarrenr case STSORT_SRCPT: 1491145510Sdarrenr qsort(tstable, tsentry +1, 1492145510Sdarrenr sizeof(statetop_t), sort_srcpt); 1493145510Sdarrenr break; 1494145510Sdarrenr case STSORT_DSTIP: 1495145510Sdarrenr qsort(tstable, tsentry + 1, 1496145510Sdarrenr sizeof(statetop_t), sort_dstip); 1497145510Sdarrenr break; 1498145510Sdarrenr case STSORT_DSTPT: 1499145510Sdarrenr qsort(tstable, tsentry + 1, 1500145510Sdarrenr sizeof(statetop_t), sort_dstpt); 1501145510Sdarrenr break; 1502145510Sdarrenr default: 1503145510Sdarrenr break; 1504145510Sdarrenr } 1505145510Sdarrenr } 1506145510Sdarrenr 1507145510Sdarrenr /* handle window resizes */ 1508145510Sdarrenr if (handle_resize) { 1509145510Sdarrenr endwin(); 1510145510Sdarrenr initscr(); 1511145510Sdarrenr cbreak(); 1512145510Sdarrenr noecho(); 1513145510Sdarrenr curs_set(0); 1514145510Sdarrenr timeout(0); 1515145510Sdarrenr getmaxyx(stdscr, maxy, maxx); 1516145510Sdarrenr redraw = 1; 1517145510Sdarrenr handle_resize = 0; 1518145510Sdarrenr } 1519145510Sdarrenr 1520145510Sdarrenr /* stop program? */ 1521145510Sdarrenr if (handle_break) 1522145510Sdarrenr break; 1523145510Sdarrenr 1524145510Sdarrenr /* print title */ 1525145510Sdarrenr erase(); 1526145510Sdarrenr attron(A_BOLD); 1527145510Sdarrenr winy = 0; 1528145510Sdarrenr move(winy,0); 1529145510Sdarrenr sprintf(str1, "%s - %s - state top", hostnm, IPL_VERSION); 1530145510Sdarrenr for (j = 0 ; j < (maxx - 8 - strlen(str1)) / 2; j++) 1531145510Sdarrenr printw(" "); 1532145510Sdarrenr printw("%s", str1); 1533145510Sdarrenr attroff(A_BOLD); 1534145510Sdarrenr 1535145510Sdarrenr /* just for fun add a clock */ 1536145510Sdarrenr move(winy, maxx - 8); 1537145510Sdarrenr t = time(NULL); 1538145510Sdarrenr strftime(str1, 80, "%T", localtime(&t)); 1539145510Sdarrenr printw("%s\n", str1); 1540145510Sdarrenr 1541145510Sdarrenr /* 1542145510Sdarrenr * print the display filters, this is placed in the loop, 1543145510Sdarrenr * because someday I might add code for changing these 1544145510Sdarrenr * while the programming is running :-) 1545145510Sdarrenr */ 1546145510Sdarrenr if (sport >= 0) 1547145510Sdarrenr sprintf(str1, "%s,%d", getip(ver, &saddr), sport); 1548145510Sdarrenr else 1549145510Sdarrenr sprintf(str1, "%s", getip(ver, &saddr)); 1550145510Sdarrenr 1551145510Sdarrenr if (dport >= 0) 1552145510Sdarrenr sprintf(str2, "%s,%d", getip(ver, &daddr), dport); 1553145510Sdarrenr else 1554145510Sdarrenr sprintf(str2, "%s", getip(ver, &daddr)); 1555145510Sdarrenr 1556145510Sdarrenr if (protocol < 0) 1557145510Sdarrenr strcpy(str3, "any"); 1558145510Sdarrenr else if ((proto = getprotobynumber(protocol)) != NULL) 1559145510Sdarrenr sprintf(str3, "%s", proto->p_name); 1560145510Sdarrenr else 1561145510Sdarrenr sprintf(str3, "%d", protocol); 1562145510Sdarrenr 1563145510Sdarrenr switch (sorting) 1564145510Sdarrenr { 1565145510Sdarrenr case STSORT_PR: 1566145510Sdarrenr sprintf(str4, "proto"); 1567145510Sdarrenr break; 1568145510Sdarrenr case STSORT_PKTS: 1569145510Sdarrenr sprintf(str4, "# pkts"); 1570145510Sdarrenr break; 1571145510Sdarrenr case STSORT_BYTES: 1572145510Sdarrenr sprintf(str4, "# bytes"); 1573145510Sdarrenr break; 1574145510Sdarrenr case STSORT_TTL: 1575145510Sdarrenr sprintf(str4, "ttl"); 1576145510Sdarrenr break; 1577145510Sdarrenr case STSORT_SRCIP: 1578145510Sdarrenr sprintf(str4, "src ip"); 1579145510Sdarrenr break; 1580145510Sdarrenr case STSORT_SRCPT: 1581145510Sdarrenr sprintf(str4, "src port"); 1582145510Sdarrenr break; 1583145510Sdarrenr case STSORT_DSTIP: 1584145510Sdarrenr sprintf(str4, "dest ip"); 1585145510Sdarrenr break; 1586145510Sdarrenr case STSORT_DSTPT: 1587145510Sdarrenr sprintf(str4, "dest port"); 1588145510Sdarrenr break; 1589145510Sdarrenr default: 1590145510Sdarrenr sprintf(str4, "unknown"); 1591145510Sdarrenr break; 1592145510Sdarrenr } 1593145510Sdarrenr 1594145510Sdarrenr if (reverse) 1595145510Sdarrenr strcat(str4, " (reverse)"); 1596145510Sdarrenr 1597145510Sdarrenr winy += 2; 1598145510Sdarrenr move(winy,0); 1599145510Sdarrenr printw("Src: %s, Dest: %s, Proto: %s, Sorted by: %s\n\n", 1600145510Sdarrenr str1, str2, str3, str4); 1601145510Sdarrenr 1602255332Scy /* 1603145510Sdarrenr * For an IPv4 IP address we need at most 15 characters, 1604145510Sdarrenr * 4 tuples of 3 digits, separated by 3 dots. Enforce this 1605145510Sdarrenr * length, so the colums do not change positions based 1606145510Sdarrenr * on the size of the IP address. This length makes the 1607255332Scy * output fit in a 80 column terminal. 1608145510Sdarrenr * We are lacking a good solution for IPv6 addresses (that 1609255332Scy * can be longer that 15 characters), so we do not enforce 1610145510Sdarrenr * a maximum on the IP field size. 1611145510Sdarrenr */ 1612145510Sdarrenr if (srclen < 15) 1613145510Sdarrenr srclen = 15; 1614145510Sdarrenr if (dstlen < 15) 1615145510Sdarrenr dstlen = 15; 1616145510Sdarrenr 1617145510Sdarrenr /* print column description */ 1618145510Sdarrenr winy += 2; 1619145510Sdarrenr move(winy,0); 1620145510Sdarrenr attron(A_BOLD); 1621145510Sdarrenr printw("%-*s %-*s %3s %4s %7s %9s %9s\n", 1622145510Sdarrenr srclen + 6, "Source IP", dstlen + 6, "Destination IP", 1623145510Sdarrenr "ST", "PR", "#pkts", "#bytes", "ttl"); 1624145510Sdarrenr attroff(A_BOLD); 1625145510Sdarrenr 1626145510Sdarrenr /* print all the entries */ 1627145510Sdarrenr tp = tstable; 1628145510Sdarrenr if (reverse) 1629145510Sdarrenr tp += tsentry; 1630145510Sdarrenr 1631145510Sdarrenr if (tsentry > maxy - 6) 1632145510Sdarrenr tsentry = maxy - 6; 1633145510Sdarrenr for (i = 0; i <= tsentry; i++) { 1634145510Sdarrenr /* print src/dest and port */ 1635145510Sdarrenr if ((tp->st_p == IPPROTO_TCP) || 1636145510Sdarrenr (tp->st_p == IPPROTO_UDP)) { 1637145510Sdarrenr sprintf(str1, "%s,%hu", 1638145510Sdarrenr getip(tp->st_v, &tp->st_src), 1639145510Sdarrenr ntohs(tp->st_sport)); 1640145510Sdarrenr sprintf(str2, "%s,%hu", 1641145510Sdarrenr getip(tp->st_v, &tp->st_dst), 1642145510Sdarrenr ntohs(tp->st_dport)); 1643145510Sdarrenr } else { 1644145510Sdarrenr sprintf(str1, "%s", getip(tp->st_v, 1645145510Sdarrenr &tp->st_src)); 1646145510Sdarrenr sprintf(str2, "%s", getip(tp->st_v, 1647145510Sdarrenr &tp->st_dst)); 1648145510Sdarrenr } 1649145510Sdarrenr winy++; 1650145510Sdarrenr move(winy, 0); 1651145510Sdarrenr printw("%-*s %-*s", srclen + 6, str1, dstlen + 6, str2); 1652145510Sdarrenr 1653145510Sdarrenr /* print state */ 1654145510Sdarrenr sprintf(str1, "%X/%X", tp->st_state[0], 1655145510Sdarrenr tp->st_state[1]); 1656145510Sdarrenr printw(" %3s", str1); 1657145510Sdarrenr 1658145510Sdarrenr /* print protocol */ 1659145510Sdarrenr proto = getprotobynumber(tp->st_p); 1660145510Sdarrenr if (proto) { 1661145510Sdarrenr strncpy(str1, proto->p_name, 4); 1662145510Sdarrenr str1[4] = '\0'; 1663145510Sdarrenr } else { 1664145510Sdarrenr sprintf(str1, "%d", tp->st_p); 1665145510Sdarrenr } 1666145510Sdarrenr /* just print icmp for IPv6-ICMP */ 1667145510Sdarrenr if (tp->st_p == IPPROTO_ICMPV6) 1668145510Sdarrenr strcpy(str1, "icmp"); 1669145510Sdarrenr printw(" %4s", str1); 1670145510Sdarrenr 1671145510Sdarrenr /* print #pkt/#bytes */ 1672145510Sdarrenr#ifdef USE_QUAD_T 1673145510Sdarrenr printw(" %7qu %9qu", (unsigned long long) tp->st_pkts, 1674145510Sdarrenr (unsigned long long) tp->st_bytes); 1675145510Sdarrenr#else 1676145510Sdarrenr printw(" %7lu %9lu", tp->st_pkts, tp->st_bytes); 1677145510Sdarrenr#endif 1678145510Sdarrenr printw(" %9s", ttl_to_string(tp->st_age)); 1679145510Sdarrenr 1680145510Sdarrenr if (reverse) 1681145510Sdarrenr tp--; 1682145510Sdarrenr else 1683145510Sdarrenr tp++; 1684145510Sdarrenr } 1685145510Sdarrenr 1686145510Sdarrenr /* screen data structure is filled, now update the screen */ 1687145510Sdarrenr if (redraw) 1688145510Sdarrenr clearok(stdscr,1); 1689145510Sdarrenr 1690145510Sdarrenr if (refresh() == ERR) 1691145510Sdarrenr break; 1692145510Sdarrenr if (redraw) { 1693145510Sdarrenr clearok(stdscr,0); 1694145510Sdarrenr redraw = 0; 1695145510Sdarrenr } 1696145510Sdarrenr 1697145510Sdarrenr /* wait for key press or a 1 second time out period */ 1698145510Sdarrenr selecttimeout.tv_sec = refreshtime; 1699145510Sdarrenr selecttimeout.tv_usec = 0; 1700145510Sdarrenr FD_ZERO(&readfd); 1701145510Sdarrenr FD_SET(0, &readfd); 1702145510Sdarrenr select(1, &readfd, NULL, NULL, &selecttimeout); 1703145510Sdarrenr 1704145510Sdarrenr /* if key pressed, read all waiting keys */ 1705145510Sdarrenr if (FD_ISSET(0, &readfd)) { 1706145510Sdarrenr c = wgetch(stdscr); 1707145510Sdarrenr if (c == ERR) 1708145510Sdarrenr continue; 1709145510Sdarrenr 1710145510Sdarrenr if (ISALPHA(c) && ISUPPER(c)) 1711145510Sdarrenr c = TOLOWER(c); 1712145510Sdarrenr if (c == 'l') { 1713145510Sdarrenr redraw = 1; 1714145510Sdarrenr } else if (c == 'q') { 1715145510Sdarrenr break; 1716145510Sdarrenr } else if (c == 'r') { 1717145510Sdarrenr reverse = !reverse; 1718145510Sdarrenr } else if (c == 'b') { 1719145510Sdarrenr forward = 0; 1720145510Sdarrenr } else if (c == 'f') { 1721145510Sdarrenr forward = 1; 1722145510Sdarrenr } else if (c == 's') { 1723145510Sdarrenr if (++sorting > STSORT_MAX) 1724145510Sdarrenr sorting = 0; 1725145510Sdarrenr } 1726145510Sdarrenr } 1727145510Sdarrenr } /* while */ 1728145510Sdarrenr 1729153881Sguidoout: 1730145510Sdarrenr printw("\n"); 1731145510Sdarrenr curs_set(1); 1732153881Sguido /* nocbreak(); XXX - endwin() should make this redundant */ 1733145510Sdarrenr endwin(); 1734145510Sdarrenr 1735145510Sdarrenr free(tstable); 1736153881Sguido if (ret != 0) 1737153881Sguido perror(errstr); 1738145510Sdarrenr} 1739145510Sdarrenr#endif 1740145510Sdarrenr 1741145510Sdarrenr 1742145510Sdarrenr/* 1743145510Sdarrenr * Show fragment cache information that's held in the kernel. 1744145510Sdarrenr */ 1745170268Sdarrenrstatic void showfrstates(ifsp, ticks) 1746255332Scy ipfrstat_t *ifsp; 1747255332Scy u_long ticks; 1748145510Sdarrenr{ 1749145510Sdarrenr struct ipfr *ipfrtab[IPFT_SIZE], ifr; 1750145510Sdarrenr int i; 1751145510Sdarrenr 1752145510Sdarrenr /* 1753145510Sdarrenr * print out the numeric statistics 1754145510Sdarrenr */ 1755255332Scy PRINTF("IP fragment states:\n%lu\tnew\n%lu\texpired\n%lu\thits\n", 1756145510Sdarrenr ifsp->ifs_new, ifsp->ifs_expire, ifsp->ifs_hits); 1757255332Scy PRINTF("%lu\tretrans\n%lu\ttoo short\n", 1758145510Sdarrenr ifsp->ifs_retrans0, ifsp->ifs_short); 1759255332Scy PRINTF("%lu\tno memory\n%lu\talready exist\n", 1760145510Sdarrenr ifsp->ifs_nomem, ifsp->ifs_exists); 1761255332Scy PRINTF("%lu\tinuse\n", ifsp->ifs_inuse); 1762170268Sdarrenr PRINTF("\n"); 1763145510Sdarrenr 1764170268Sdarrenr if (live_kernel == 0) { 1765170268Sdarrenr if (kmemcpy((char *)ipfrtab, (u_long)ifsp->ifs_table, 1766170268Sdarrenr sizeof(ipfrtab))) 1767170268Sdarrenr return; 1768170268Sdarrenr } 1769170268Sdarrenr 1770145510Sdarrenr /* 1771145510Sdarrenr * Print out the contents (if any) of the fragment cache table. 1772145510Sdarrenr */ 1773170268Sdarrenr if (live_kernel == 1) { 1774170268Sdarrenr do { 1775170268Sdarrenr if (fetchfrag(ipf_fd, IPFGENITER_FRAG, &ifr) != 0) 1776145510Sdarrenr break; 1777170268Sdarrenr if (ifr.ipfr_ifp == NULL) 1778170268Sdarrenr break; 1779170268Sdarrenr ifr.ipfr_ttl -= ticks; 1780145510Sdarrenr printfraginfo("", &ifr); 1781255332Scy } while (ifr.ipfr_next != NULL); 1782170268Sdarrenr } else { 1783170268Sdarrenr for (i = 0; i < IPFT_SIZE; i++) 1784170268Sdarrenr while (ipfrtab[i] != NULL) { 1785170268Sdarrenr if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i], 1786170268Sdarrenr sizeof(ifr)) == -1) 1787170268Sdarrenr break; 1788170268Sdarrenr printfraginfo("", &ifr); 1789170268Sdarrenr ipfrtab[i] = ifr.ipfr_next; 1790170268Sdarrenr } 1791170268Sdarrenr } 1792145510Sdarrenr /* 1793145510Sdarrenr * Print out the contents (if any) of the NAT fragment cache table. 1794145510Sdarrenr */ 1795170268Sdarrenr 1796170268Sdarrenr if (live_kernel == 0) { 1797170268Sdarrenr if (kmemcpy((char *)ipfrtab, (u_long)ifsp->ifs_nattab, 1798170268Sdarrenr sizeof(ipfrtab))) 1799170268Sdarrenr return; 1800170268Sdarrenr } 1801170268Sdarrenr 1802170268Sdarrenr if (live_kernel == 1) { 1803170268Sdarrenr do { 1804170268Sdarrenr if (fetchfrag(nat_fd, IPFGENITER_NATFRAG, &ifr) != 0) 1805145510Sdarrenr break; 1806170268Sdarrenr if (ifr.ipfr_ifp == NULL) 1807170268Sdarrenr break; 1808170268Sdarrenr ifr.ipfr_ttl -= ticks; 1809145510Sdarrenr printfraginfo("NAT: ", &ifr); 1810255332Scy } while (ifr.ipfr_next != NULL); 1811170268Sdarrenr } else { 1812170268Sdarrenr for (i = 0; i < IPFT_SIZE; i++) 1813170268Sdarrenr while (ipfrtab[i] != NULL) { 1814170268Sdarrenr if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i], 1815170268Sdarrenr sizeof(ifr)) == -1) 1816170268Sdarrenr break; 1817170268Sdarrenr printfraginfo("NAT: ", &ifr); 1818170268Sdarrenr ipfrtab[i] = ifr.ipfr_next; 1819170268Sdarrenr } 1820170268Sdarrenr } 1821145510Sdarrenr} 1822145510Sdarrenr 1823145510Sdarrenr 1824145510Sdarrenr/* 1825145510Sdarrenr * Show stats on how auth within IPFilter has been used 1826145510Sdarrenr */ 1827145510Sdarrenrstatic void showauthstates(asp) 1828255332Scy ipf_authstat_t *asp; 1829145510Sdarrenr{ 1830145510Sdarrenr frauthent_t *frap, fra; 1831170268Sdarrenr ipfgeniter_t auth; 1832170268Sdarrenr ipfobj_t obj; 1833145510Sdarrenr 1834170268Sdarrenr obj.ipfo_rev = IPFILTER_VERSION; 1835170268Sdarrenr obj.ipfo_type = IPFOBJ_GENITER; 1836170268Sdarrenr obj.ipfo_size = sizeof(auth); 1837170268Sdarrenr obj.ipfo_ptr = &auth; 1838170268Sdarrenr 1839170268Sdarrenr auth.igi_type = IPFGENITER_AUTH; 1840170268Sdarrenr auth.igi_nitems = 1; 1841170268Sdarrenr auth.igi_data = &fra; 1842170268Sdarrenr 1843145510Sdarrenr#ifdef USE_QUAD_T 1844255332Scy printf("Authorisation hits: %"PRIu64"\tmisses %"PRIu64"\n", 1845145510Sdarrenr (unsigned long long) asp->fas_hits, 1846145510Sdarrenr (unsigned long long) asp->fas_miss); 1847145510Sdarrenr#else 1848145510Sdarrenr printf("Authorisation hits: %ld\tmisses %ld\n", asp->fas_hits, 1849145510Sdarrenr asp->fas_miss); 1850145510Sdarrenr#endif 1851145510Sdarrenr printf("nospace %ld\nadded %ld\nsendfail %ld\nsendok %ld\n", 1852145510Sdarrenr asp->fas_nospace, asp->fas_added, asp->fas_sendfail, 1853145510Sdarrenr asp->fas_sendok); 1854145510Sdarrenr printf("queok %ld\nquefail %ld\nexpire %ld\n", 1855145510Sdarrenr asp->fas_queok, asp->fas_quefail, asp->fas_expire); 1856145510Sdarrenr 1857145510Sdarrenr frap = asp->fas_faelist; 1858145510Sdarrenr while (frap) { 1859170268Sdarrenr if (live_kernel == 1) { 1860170268Sdarrenr if (ioctl(auth_fd, SIOCGENITER, &obj)) 1861170268Sdarrenr break; 1862170268Sdarrenr } else { 1863170268Sdarrenr if (kmemcpy((char *)&fra, (u_long)frap, 1864170268Sdarrenr sizeof(fra)) == -1) 1865170268Sdarrenr break; 1866170268Sdarrenr } 1867145510Sdarrenr printf("age %ld\t", fra.fae_age); 1868145510Sdarrenr printfr(&fra.fae_fr, ioctl); 1869145510Sdarrenr frap = fra.fae_next; 1870145510Sdarrenr } 1871145510Sdarrenr} 1872145510Sdarrenr 1873145510Sdarrenr 1874145510Sdarrenr/* 1875145510Sdarrenr * Display groups used for each of filter rules, accounting rules and 1876145510Sdarrenr * authentication, separately. 1877145510Sdarrenr */ 1878145510Sdarrenrstatic void showgroups(fiop) 1879255332Scy struct friostat *fiop; 1880145510Sdarrenr{ 1881145510Sdarrenr static char *gnames[3] = { "Filter", "Accounting", "Authentication" }; 1882145510Sdarrenr static int gnums[3] = { IPL_LOGIPF, IPL_LOGCOUNT, IPL_LOGAUTH }; 1883145510Sdarrenr frgroup_t *fp, grp; 1884145510Sdarrenr int on, off, i; 1885145510Sdarrenr 1886145510Sdarrenr on = fiop->f_active; 1887145510Sdarrenr off = 1 - on; 1888145510Sdarrenr 1889145510Sdarrenr for (i = 0; i < 3; i++) { 1890145510Sdarrenr printf("%s groups (active):\n", gnames[i]); 1891145510Sdarrenr for (fp = fiop->f_groups[gnums[i]][on]; fp != NULL; 1892145510Sdarrenr fp = grp.fg_next) 1893145510Sdarrenr if (kmemcpy((char *)&grp, (u_long)fp, sizeof(grp))) 1894145510Sdarrenr break; 1895145510Sdarrenr else 1896145510Sdarrenr printf("%s\n", grp.fg_name); 1897145510Sdarrenr printf("%s groups (inactive):\n", gnames[i]); 1898145510Sdarrenr for (fp = fiop->f_groups[gnums[i]][off]; fp != NULL; 1899145510Sdarrenr fp = grp.fg_next) 1900145510Sdarrenr if (kmemcpy((char *)&grp, (u_long)fp, sizeof(grp))) 1901145510Sdarrenr break; 1902145510Sdarrenr else 1903145510Sdarrenr printf("%s\n", grp.fg_name); 1904145510Sdarrenr } 1905145510Sdarrenr} 1906145510Sdarrenr 1907255332Scy 1908145510Sdarrenrstatic void parse_ipportstr(argument, ip, port) 1909255332Scy const char *argument; 1910255332Scy i6addr_t *ip; 1911255332Scy int *port; 1912145510Sdarrenr{ 1913145510Sdarrenr char *s, *comma; 1914145510Sdarrenr int ok = 0; 1915145510Sdarrenr 1916145510Sdarrenr /* make working copy of argument, Theoretically you must be able 1917145510Sdarrenr * to write to optarg, but that seems very ugly to me.... 1918145510Sdarrenr */ 1919145510Sdarrenr s = strdup(argument); 1920145510Sdarrenr if (s == NULL) 1921145510Sdarrenr return; 1922145510Sdarrenr 1923145510Sdarrenr /* get port */ 1924145510Sdarrenr if ((comma = strchr(s, ',')) != NULL) { 1925145510Sdarrenr if (!strcasecmp(comma + 1, "any")) { 1926145510Sdarrenr *port = -1; 1927145510Sdarrenr } else if (!sscanf(comma + 1, "%d", port) || 1928145510Sdarrenr (*port < 0) || (*port > 65535)) { 1929171017Sdarrenr fprintf(stderr, "Invalid port specification in %s\n", 1930145510Sdarrenr argument); 1931145510Sdarrenr free(s); 1932145510Sdarrenr exit(-2); 1933145510Sdarrenr } 1934145510Sdarrenr *comma = '\0'; 1935145510Sdarrenr } 1936145510Sdarrenr 1937145510Sdarrenr 1938145510Sdarrenr /* get ip address */ 1939145510Sdarrenr if (!strcasecmp(s, "any")) { 1940145510Sdarrenr ip->in4.s_addr = INADDR_ANY; 1941171017Sdarrenr ok = 1; 1942145510Sdarrenr#ifdef USE_INET6 1943145510Sdarrenr ip->in6 = in6addr_any; 1944145510Sdarrenr } else if (use_inet6 && inet_pton(AF_INET6, s, &ip->in6)) { 1945145510Sdarrenr ok = 1; 1946145510Sdarrenr#endif 1947145510Sdarrenr } else if (inet_aton(s, &ip->in4)) 1948145510Sdarrenr ok = 1; 1949145510Sdarrenr 1950145510Sdarrenr if (ok == 0) { 1951145510Sdarrenr fprintf(stderr, "Invalid IP address: %s\n", s); 1952145510Sdarrenr free(s); 1953145510Sdarrenr exit(-2); 1954145510Sdarrenr } 1955145510Sdarrenr 1956145510Sdarrenr /* free allocated memory */ 1957145510Sdarrenr free(s); 1958145510Sdarrenr} 1959145510Sdarrenr 1960145510Sdarrenr 1961145510Sdarrenr#ifdef STATETOP 1962145510Sdarrenrstatic void sig_resize(s) 1963255332Scy int s; 1964145510Sdarrenr{ 1965145510Sdarrenr handle_resize = 1; 1966145510Sdarrenr} 1967145510Sdarrenr 1968145510Sdarrenrstatic void sig_break(s) 1969255332Scy int s; 1970145510Sdarrenr{ 1971145510Sdarrenr handle_break = 1; 1972145510Sdarrenr} 1973145510Sdarrenr 1974145510Sdarrenrstatic char *getip(v, addr) 1975255332Scy int v; 1976255332Scy i6addr_t *addr; 1977145510Sdarrenr{ 1978153881Sguido#ifdef USE_INET6 1979145510Sdarrenr static char hostbuf[MAXHOSTNAMELEN+1]; 1980153881Sguido#endif 1981145510Sdarrenr 1982145510Sdarrenr if (v == 4) 1983145510Sdarrenr return inet_ntoa(addr->in4); 1984145510Sdarrenr 1985145510Sdarrenr#ifdef USE_INET6 1986145510Sdarrenr (void) inet_ntop(AF_INET6, &addr->in6, hostbuf, sizeof(hostbuf) - 1); 1987145510Sdarrenr hostbuf[MAXHOSTNAMELEN] = '\0'; 1988145510Sdarrenr return hostbuf; 1989145510Sdarrenr#else 1990145510Sdarrenr return "IPv6"; 1991145510Sdarrenr#endif 1992145510Sdarrenr} 1993145510Sdarrenr 1994145510Sdarrenr 1995145510Sdarrenrstatic char *ttl_to_string(ttl) 1996255332Scy long int ttl; 1997145510Sdarrenr{ 1998145510Sdarrenr static char ttlbuf[STSTRSIZE]; 1999145510Sdarrenr int hours, minutes, seconds; 2000145510Sdarrenr 2001145510Sdarrenr /* ttl is in half seconds */ 2002145510Sdarrenr ttl /= 2; 2003145510Sdarrenr 2004145510Sdarrenr hours = ttl / 3600; 2005145510Sdarrenr ttl = ttl % 3600; 2006145510Sdarrenr minutes = ttl / 60; 2007145510Sdarrenr seconds = ttl % 60; 2008145510Sdarrenr 2009145510Sdarrenr if (hours > 0) 2010145510Sdarrenr sprintf(ttlbuf, "%2d:%02d:%02d", hours, minutes, seconds); 2011145510Sdarrenr else 2012145510Sdarrenr sprintf(ttlbuf, "%2d:%02d", minutes, seconds); 2013145510Sdarrenr return ttlbuf; 2014145510Sdarrenr} 2015145510Sdarrenr 2016145510Sdarrenr 2017145510Sdarrenrstatic int sort_pkts(a, b) 2018255332Scy const void *a; 2019255332Scy const void *b; 2020145510Sdarrenr{ 2021145510Sdarrenr 2022145510Sdarrenr register const statetop_t *ap = a; 2023145510Sdarrenr register const statetop_t *bp = b; 2024145510Sdarrenr 2025145510Sdarrenr if (ap->st_pkts == bp->st_pkts) 2026145510Sdarrenr return 0; 2027145510Sdarrenr else if (ap->st_pkts < bp->st_pkts) 2028145510Sdarrenr return 1; 2029145510Sdarrenr return -1; 2030145510Sdarrenr} 2031145510Sdarrenr 2032145510Sdarrenr 2033145510Sdarrenrstatic int sort_bytes(a, b) 2034255332Scy const void *a; 2035255332Scy const void *b; 2036145510Sdarrenr{ 2037145510Sdarrenr register const statetop_t *ap = a; 2038145510Sdarrenr register const statetop_t *bp = b; 2039145510Sdarrenr 2040145510Sdarrenr if (ap->st_bytes == bp->st_bytes) 2041145510Sdarrenr return 0; 2042145510Sdarrenr else if (ap->st_bytes < bp->st_bytes) 2043145510Sdarrenr return 1; 2044145510Sdarrenr return -1; 2045145510Sdarrenr} 2046145510Sdarrenr 2047145510Sdarrenr 2048145510Sdarrenrstatic int sort_p(a, b) 2049255332Scy const void *a; 2050255332Scy const void *b; 2051145510Sdarrenr{ 2052145510Sdarrenr register const statetop_t *ap = a; 2053145510Sdarrenr register const statetop_t *bp = b; 2054145510Sdarrenr 2055145510Sdarrenr if (ap->st_p == bp->st_p) 2056145510Sdarrenr return 0; 2057145510Sdarrenr else if (ap->st_p < bp->st_p) 2058145510Sdarrenr return 1; 2059145510Sdarrenr return -1; 2060145510Sdarrenr} 2061145510Sdarrenr 2062145510Sdarrenr 2063145510Sdarrenrstatic int sort_ttl(a, b) 2064255332Scy const void *a; 2065255332Scy const void *b; 2066145510Sdarrenr{ 2067145510Sdarrenr register const statetop_t *ap = a; 2068145510Sdarrenr register const statetop_t *bp = b; 2069145510Sdarrenr 2070145510Sdarrenr if (ap->st_age == bp->st_age) 2071145510Sdarrenr return 0; 2072145510Sdarrenr else if (ap->st_age < bp->st_age) 2073145510Sdarrenr return 1; 2074145510Sdarrenr return -1; 2075145510Sdarrenr} 2076145510Sdarrenr 2077145510Sdarrenrstatic int sort_srcip(a, b) 2078255332Scy const void *a; 2079255332Scy const void *b; 2080145510Sdarrenr{ 2081145510Sdarrenr register const statetop_t *ap = a; 2082145510Sdarrenr register const statetop_t *bp = b; 2083145510Sdarrenr 2084145510Sdarrenr#ifdef USE_INET6 2085145510Sdarrenr if (use_inet6) { 2086145510Sdarrenr if (IP6_EQ(&ap->st_src, &bp->st_src)) 2087145510Sdarrenr return 0; 2088145510Sdarrenr else if (IP6_GT(&ap->st_src, &bp->st_src)) 2089145510Sdarrenr return 1; 2090145510Sdarrenr } else 2091145510Sdarrenr#endif 2092145510Sdarrenr { 2093145510Sdarrenr if (ntohl(ap->st_src.in4.s_addr) == 2094145510Sdarrenr ntohl(bp->st_src.in4.s_addr)) 2095145510Sdarrenr return 0; 2096145510Sdarrenr else if (ntohl(ap->st_src.in4.s_addr) > 2097145510Sdarrenr ntohl(bp->st_src.in4.s_addr)) 2098145510Sdarrenr return 1; 2099145510Sdarrenr } 2100145510Sdarrenr return -1; 2101145510Sdarrenr} 2102145510Sdarrenr 2103145510Sdarrenrstatic int sort_srcpt(a, b) 2104255332Scy const void *a; 2105255332Scy const void *b; 2106145510Sdarrenr{ 2107145510Sdarrenr register const statetop_t *ap = a; 2108145510Sdarrenr register const statetop_t *bp = b; 2109145510Sdarrenr 2110145510Sdarrenr if (htons(ap->st_sport) == htons(bp->st_sport)) 2111145510Sdarrenr return 0; 2112145510Sdarrenr else if (htons(ap->st_sport) > htons(bp->st_sport)) 2113145510Sdarrenr return 1; 2114145510Sdarrenr return -1; 2115145510Sdarrenr} 2116145510Sdarrenr 2117145510Sdarrenrstatic int sort_dstip(a, b) 2118255332Scy const void *a; 2119255332Scy const void *b; 2120145510Sdarrenr{ 2121145510Sdarrenr register const statetop_t *ap = a; 2122145510Sdarrenr register const statetop_t *bp = b; 2123145510Sdarrenr 2124145510Sdarrenr#ifdef USE_INET6 2125145510Sdarrenr if (use_inet6) { 2126145510Sdarrenr if (IP6_EQ(&ap->st_dst, &bp->st_dst)) 2127145510Sdarrenr return 0; 2128145510Sdarrenr else if (IP6_GT(&ap->st_dst, &bp->st_dst)) 2129145510Sdarrenr return 1; 2130145510Sdarrenr } else 2131145510Sdarrenr#endif 2132145510Sdarrenr { 2133145510Sdarrenr if (ntohl(ap->st_dst.in4.s_addr) == 2134145510Sdarrenr ntohl(bp->st_dst.in4.s_addr)) 2135145510Sdarrenr return 0; 2136145510Sdarrenr else if (ntohl(ap->st_dst.in4.s_addr) > 2137145510Sdarrenr ntohl(bp->st_dst.in4.s_addr)) 2138145510Sdarrenr return 1; 2139145510Sdarrenr } 2140145510Sdarrenr return -1; 2141145510Sdarrenr} 2142145510Sdarrenr 2143145510Sdarrenrstatic int sort_dstpt(a, b) 2144255332Scy const void *a; 2145255332Scy const void *b; 2146145510Sdarrenr{ 2147145510Sdarrenr register const statetop_t *ap = a; 2148145510Sdarrenr register const statetop_t *bp = b; 2149145510Sdarrenr 2150145510Sdarrenr if (htons(ap->st_dport) == htons(bp->st_dport)) 2151145510Sdarrenr return 0; 2152145510Sdarrenr else if (htons(ap->st_dport) > htons(bp->st_dport)) 2153145510Sdarrenr return 1; 2154145510Sdarrenr return -1; 2155145510Sdarrenr} 2156145510Sdarrenr 2157145510Sdarrenr#endif 2158170268Sdarrenr 2159170268Sdarrenr 2160170268Sdarrenripstate_t *fetchstate(src, dst) 2161255332Scy ipstate_t *src, *dst; 2162170268Sdarrenr{ 2163170268Sdarrenr 2164170268Sdarrenr if (live_kernel == 1) { 2165170268Sdarrenr ipfgeniter_t state; 2166170268Sdarrenr ipfobj_t obj; 2167170268Sdarrenr 2168170268Sdarrenr obj.ipfo_rev = IPFILTER_VERSION; 2169170268Sdarrenr obj.ipfo_type = IPFOBJ_GENITER; 2170170268Sdarrenr obj.ipfo_size = sizeof(state); 2171170268Sdarrenr obj.ipfo_ptr = &state; 2172170268Sdarrenr 2173170268Sdarrenr state.igi_type = IPFGENITER_STATE; 2174170268Sdarrenr state.igi_nitems = 1; 2175170268Sdarrenr state.igi_data = dst; 2176170268Sdarrenr 2177170268Sdarrenr if (ioctl(state_fd, SIOCGENITER, &obj) != 0) 2178170268Sdarrenr return NULL; 2179170268Sdarrenr if (dst->is_next == NULL) { 2180255332Scy int n = IPFGENITER_STATE; 2181255332Scy (void) ioctl(ipf_fd,SIOCIPFDELTOK, &n); 2182170268Sdarrenr } 2183170268Sdarrenr } else { 2184170268Sdarrenr if (kmemcpy((char *)dst, (u_long)src, sizeof(*dst))) 2185170268Sdarrenr return NULL; 2186170268Sdarrenr } 2187170268Sdarrenr return dst; 2188170268Sdarrenr} 2189170268Sdarrenr 2190170268Sdarrenr 2191170268Sdarrenrstatic int fetchfrag(fd, type, frp) 2192255332Scy int fd, type; 2193255332Scy ipfr_t *frp; 2194170268Sdarrenr{ 2195170268Sdarrenr ipfgeniter_t frag; 2196170268Sdarrenr ipfobj_t obj; 2197170268Sdarrenr 2198170268Sdarrenr obj.ipfo_rev = IPFILTER_VERSION; 2199170268Sdarrenr obj.ipfo_type = IPFOBJ_GENITER; 2200170268Sdarrenr obj.ipfo_size = sizeof(frag); 2201170268Sdarrenr obj.ipfo_ptr = &frag; 2202170268Sdarrenr 2203170268Sdarrenr frag.igi_type = type; 2204170268Sdarrenr frag.igi_nitems = 1; 2205170268Sdarrenr frag.igi_data = frp; 2206170268Sdarrenr 2207170268Sdarrenr if (ioctl(fd, SIOCGENITER, &obj)) 2208170268Sdarrenr return EFAULT; 2209170268Sdarrenr return 0; 2210170268Sdarrenr} 2211170268Sdarrenr 2212170268Sdarrenr 2213255332Scystatic int state_matcharray(stp, array) 2214255332Scy ipstate_t *stp; 2215255332Scy int *array; 2216255332Scy{ 2217255332Scy int i, n, *x, rv, p; 2218255332Scy ipfexp_t *e; 2219255332Scy 2220255332Scy rv = 0; 2221255332Scy 2222255332Scy for (n = array[0], x = array + 1; n > 0; x += e->ipfe_size) { 2223255332Scy e = (ipfexp_t *)x; 2224255332Scy if (e->ipfe_cmd == IPF_EXP_END) 2225255332Scy break; 2226255332Scy n -= e->ipfe_size; 2227255332Scy 2228255332Scy rv = 0; 2229255332Scy /* 2230255332Scy * The upper 16 bits currently store the protocol value. 2231255332Scy * This is currently used with TCP and UDP port compares and 2232255332Scy * allows "tcp.port = 80" without requiring an explicit 2233255332Scy " "ip.pr = tcp" first. 2234255332Scy */ 2235255332Scy p = e->ipfe_cmd >> 16; 2236255332Scy if ((p != 0) && (p != stp->is_p)) 2237255332Scy break; 2238255332Scy 2239255332Scy switch (e->ipfe_cmd) 2240255332Scy { 2241255332Scy case IPF_EXP_IP_PR : 2242255332Scy for (i = 0; !rv && i < e->ipfe_narg; i++) { 2243255332Scy rv |= (stp->is_p == e->ipfe_arg0[i]); 2244255332Scy } 2245255332Scy break; 2246255332Scy 2247255332Scy case IPF_EXP_IP_SRCADDR : 2248255332Scy if (stp->is_v != 4) 2249255332Scy break; 2250255332Scy for (i = 0; !rv && i < e->ipfe_narg; i++) { 2251255332Scy rv |= ((stp->is_saddr & 2252255332Scy e->ipfe_arg0[i * 2 + 1]) == 2253255332Scy e->ipfe_arg0[i * 2]); 2254255332Scy } 2255255332Scy break; 2256255332Scy 2257255332Scy case IPF_EXP_IP_DSTADDR : 2258255332Scy if (stp->is_v != 4) 2259255332Scy break; 2260255332Scy for (i = 0; !rv && i < e->ipfe_narg; i++) { 2261255332Scy rv |= ((stp->is_daddr & 2262255332Scy e->ipfe_arg0[i * 2 + 1]) == 2263255332Scy e->ipfe_arg0[i * 2]); 2264255332Scy } 2265255332Scy break; 2266255332Scy 2267255332Scy case IPF_EXP_IP_ADDR : 2268255332Scy if (stp->is_v != 4) 2269255332Scy break; 2270255332Scy for (i = 0; !rv && i < e->ipfe_narg; i++) { 2271255332Scy rv |= ((stp->is_saddr & 2272255332Scy e->ipfe_arg0[i * 2 + 1]) == 2273255332Scy e->ipfe_arg0[i * 2]) || 2274255332Scy ((stp->is_daddr & 2275255332Scy e->ipfe_arg0[i * 2 + 1]) == 2276255332Scy e->ipfe_arg0[i * 2]); 2277255332Scy } 2278255332Scy break; 2279255332Scy 2280255332Scy#ifdef USE_INET6 2281255332Scy case IPF_EXP_IP6_SRCADDR : 2282255332Scy if (stp->is_v != 6) 2283255332Scy break; 2284255332Scy for (i = 0; !rv && i < e->ipfe_narg; i++) { 2285255332Scy rv |= IP6_MASKEQ(&stp->is_src, 2286255332Scy &e->ipfe_arg0[i * 8 + 4], 2287255332Scy &e->ipfe_arg0[i * 8]); 2288255332Scy } 2289255332Scy break; 2290255332Scy 2291255332Scy case IPF_EXP_IP6_DSTADDR : 2292255332Scy if (stp->is_v != 6) 2293255332Scy break; 2294255332Scy for (i = 0; !rv && i < e->ipfe_narg; i++) { 2295255332Scy rv |= IP6_MASKEQ(&stp->is_dst, 2296255332Scy &e->ipfe_arg0[i * 8 + 4], 2297255332Scy &e->ipfe_arg0[i * 8]); 2298255332Scy } 2299255332Scy break; 2300255332Scy 2301255332Scy case IPF_EXP_IP6_ADDR : 2302255332Scy if (stp->is_v != 6) 2303255332Scy break; 2304255332Scy for (i = 0; !rv && i < e->ipfe_narg; i++) { 2305255332Scy rv |= IP6_MASKEQ(&stp->is_src, 2306255332Scy &e->ipfe_arg0[i * 8 + 4], 2307255332Scy &e->ipfe_arg0[i * 8]) || 2308255332Scy IP6_MASKEQ(&stp->is_dst, 2309255332Scy &e->ipfe_arg0[i * 8 + 4], 2310255332Scy &e->ipfe_arg0[i * 8]); 2311255332Scy } 2312255332Scy break; 2313255332Scy#endif 2314255332Scy 2315255332Scy case IPF_EXP_UDP_PORT : 2316255332Scy case IPF_EXP_TCP_PORT : 2317255332Scy for (i = 0; !rv && i < e->ipfe_narg; i++) { 2318255332Scy rv |= (stp->is_sport == e->ipfe_arg0[i]) || 2319255332Scy (stp->is_dport == e->ipfe_arg0[i]); 2320255332Scy } 2321255332Scy break; 2322255332Scy 2323255332Scy case IPF_EXP_UDP_SPORT : 2324255332Scy case IPF_EXP_TCP_SPORT : 2325255332Scy for (i = 0; !rv && i < e->ipfe_narg; i++) { 2326255332Scy rv |= (stp->is_sport == e->ipfe_arg0[i]); 2327255332Scy } 2328255332Scy break; 2329255332Scy 2330255332Scy case IPF_EXP_UDP_DPORT : 2331255332Scy case IPF_EXP_TCP_DPORT : 2332255332Scy for (i = 0; !rv && i < e->ipfe_narg; i++) { 2333255332Scy rv |= (stp->is_dport == e->ipfe_arg0[i]); 2334255332Scy } 2335255332Scy break; 2336255332Scy 2337255332Scy case IPF_EXP_IDLE_GT : 2338255332Scy for (i = 0; !rv && i < e->ipfe_narg; i++) { 2339255332Scy rv |= (stp->is_die < e->ipfe_arg0[i]); 2340255332Scy } 2341255332Scy break; 2342255332Scy 2343255332Scy case IPF_EXP_TCP_STATE : 2344255332Scy for (i = 0; !rv && i < e->ipfe_narg; i++) { 2345255332Scy rv |= (stp->is_state[0] == e->ipfe_arg0[i]) || 2346255332Scy (stp->is_state[1] == e->ipfe_arg0[i]); 2347255332Scy } 2348255332Scy break; 2349255332Scy } 2350255332Scy rv ^= e->ipfe_not; 2351255332Scy 2352255332Scy if (rv == 0) 2353255332Scy break; 2354255332Scy } 2355255332Scy 2356255332Scy return rv; 2357255332Scy} 2358255332Scy 2359255332Scy 2360170268Sdarrenrstatic void showtqtable_live(fd) 2361255332Scy int fd; 2362170268Sdarrenr{ 2363170268Sdarrenr ipftq_t table[IPF_TCP_NSTATES]; 2364170268Sdarrenr ipfobj_t obj; 2365170268Sdarrenr 2366170268Sdarrenr bzero((char *)&obj, sizeof(obj)); 2367170268Sdarrenr obj.ipfo_rev = IPFILTER_VERSION; 2368170268Sdarrenr obj.ipfo_size = sizeof(table); 2369170268Sdarrenr obj.ipfo_ptr = (void *)table; 2370170268Sdarrenr obj.ipfo_type = IPFOBJ_STATETQTAB; 2371170268Sdarrenr 2372170268Sdarrenr if (ioctl(fd, SIOCGTQTAB, &obj) == 0) { 2373170268Sdarrenr printtqtable(table); 2374170268Sdarrenr } 2375170268Sdarrenr} 2376