2 * Copyright (C) 1993-2001 by Darren Reed.
4 * See the IPFILTER.LICENCE file for details on licencing.
7 # ifndef __FreeBSD_cc_version
8 # include <osreldate.h>
10 # if __FreeBSD_cc_version < 430000
11 # include <osreldate.h>
15 #if defined(__sgi) && (IRIX > 602)
16 # include <sys/ptimers.h>
20 #if !defined(__SVR4) && !defined(__svr4__)
23 #include <sys/types.h>
25 #include <sys/param.h>
28 # if defined(_BSDI_VERSION)
31 # if defined(__FreeBSD__) && \
32 (!defined(__FreeBSD_version) || (__FreeBSD_version < 430000))
35 # if defined(__NetBSD_Version__)
36 # if (__NetBSD_Version__ < 105000000)
44 # if defined(__svr4__) || defined(__SVR4)
45 # include <sys/select.h>
47 # undef STATETOP /* NOT supported on SunOS4 */
56 #include <sys/socket.h>
57 #include <sys/ioctl.h>
58 #include <netinet/in.h>
59 #include <arpa/inet.h>
60 #include <netinet/in_systm.h>
61 #include <netinet/ip.h>
63 #if __FreeBSD_version >= 300000
64 # include <net/if_var.h>
67 #include <arpa/nameser.h>
69 #include <netinet/tcp.h>
70 #if defined(STATETOP) && !defined(linux)
71 # include <netinet/ip_var.h>
72 # include <netinet/tcp_fsm.h>
74 #include "netinet/ip_compat.h"
75 #include "netinet/ip_fil.h"
77 #include "netinet/ip_nat.h"
78 #include "netinet/ip_frag.h"
79 #include "netinet/ip_state.h"
80 #include "netinet/ip_proxy.h"
81 #include "netinet/ip_auth.h"
83 # include "netinet/ipl.h"
85 # if SOLARIS || defined(__NetBSD__) || defined(_BSDI_VERSION) || \
96 #if defined(__NetBSD__) || (__OpenBSD__)
101 static const char sccsid[] = "@(#)fils.c 1.21 4/20/96 (C) 1993-2000 Darren Reed";
102 static const char rcsid[] = "@(#)$Id: fils.c,v 2.21.2.45 2004/04/10 11:45:48 darrenr Exp $";
108 #define PRINTF (void)printf
109 #define FPRINTF (void)fprintf
114 static char *filters[4] = { "ipfilter(in)", "ipfilter(out)",
115 "ipacct(in)", "ipacct(out)" };
126 #define STGROWSIZE 16
130 #define STSORT_PKTS 1
131 #define STSORT_BYTES 2
133 #define STSORT_SRCIP 4
134 #define STSORT_DSTIP 5
135 #define STSORT_MAX STSORT_DSTIP
136 #define STSORT_DEFAULT STSORT_BYTES
139 typedef struct statetop {
152 extern int main __P((int, char *[]));
153 static void showstats __P((friostat_t *, u_32_t));
154 static void showfrstates __P((ipfrstat_t *));
155 static void showlist __P((friostat_t *));
156 static void showipstates __P((ips_stat_t *));
157 static void showauthstates __P((fr_authstat_t *));
158 static void showgroups __P((friostat_t *));
159 static void Usage __P((char *));
160 static void printlist __P((frentry_t *));
161 static void parse_ipportstr __P((const char *, struct in_addr *, int *));
162 static int ipfstate_live __P((char *, friostat_t **, ips_stat_t **,
163 ipfrstat_t **, fr_authstat_t **, u_32_t *));
164 static void ipfstate_dead __P((char *, friostat_t **, ips_stat_t **,
165 ipfrstat_t **, fr_authstat_t **, u_32_t *));
167 static void topipstates __P((struct in_addr, struct in_addr, int, int, int, int, int));
168 static char *ttl_to_string __P((long));
169 static int sort_p __P((const void *, const void *));
170 static int sort_pkts __P((const void *, const void *));
171 static int sort_bytes __P((const void *, const void *));
172 static int sort_ttl __P((const void *, const void *));
173 static int sort_srcip __P((const void *, const void *));
174 static int sort_dstip __P((const void *, const void *));
177 void showqiflist __P((char *));
181 static void Usage(name)
185 fprintf(stderr, "Usage: %s [-6aAfhIinosv] [-d <device>]\n", name);
187 fprintf(stderr, "Usage: %s [-aAfhIinosv] [-d <device>]\n", name);
189 fprintf(stderr, "\t\t[-M corefile] [-N symbol-list]\n");
190 fprintf(stderr, " %s -t [-S source address] [-D destination address] [-P protocol] [-T refreshtime] [-C] [-d <device>]\n", name);
199 fr_authstat_t frauthst;
200 fr_authstat_t *frauthstp = &frauthst;
202 friostat_t *fiop = &fio;
204 ips_stat_t *ipsstp = &ipsst;
206 ipfrstat_t *ifrstp = &ifrst;
207 char *device = IPL_NAME, *memf = NULL;
210 struct protoent *proto;
212 int protocol = -1; /* -1 = wild card for any protocol */
213 int refreshtime = 1; /* default update time */
214 int sport = -1; /* -1 = wild card for any source port */
215 int dport = -1; /* -1 = wild card for any dest port */
216 int topclosed = 0; /* do not show closed tcp sessions */
217 struct in_addr saddr, daddr;
220 saddr.s_addr = INADDR_ANY; /* default any source addr */
221 daddr.s_addr = INADDR_ANY; /* default any dest addr */
224 * Parse these two arguments now lest there be any buffer overflows
225 * in the parsing of the rest.
228 while ((c = getopt(argc, argv, "6aACfghIilnoqstvd:D:M:N:P:S:T:")) != -1)
242 if (live_kernel == 1) {
243 if ((state_fd = open(IPL_STATE, O_RDONLY)) == -1) {
247 if ((auth_fd = open(IPL_AUTH, O_RDONLY)) == -1) {
251 if ((ipf_fd = open(device, O_RDONLY)) == -1) {
257 if (kern != NULL || memf != NULL)
259 (void)setuid(getuid());
260 (void)setgid(getgid());
263 if (openkmem(kern, memf) == -1)
266 (void)setuid(getuid());
267 (void)setgid(getgid());
269 while ((c = getopt(argc, argv, "6aACfghIilnoqstvd:D:M:N:P:S:T:")) != -1)
279 opts |= OPT_ACCNT|OPT_SHOWLIST;
282 device = IPAUTH_NAME;
283 opts |= OPT_AUTHSTATS;
292 parse_ipportstr(optarg, &daddr, &dport);
295 opts |= OPT_FRSTATES;
304 opts |= OPT_INQUE|OPT_SHOWLIST;
307 opts |= OPT_INACTIVE;
310 opts |= OPT_SHOWLIST;
317 opts |= OPT_SHOWLINENO;
320 opts |= OPT_OUTQUE|OPT_SHOWLIST;
323 if ((proto = getprotobyname(optarg)) != NULL) {
324 protocol = proto->p_proto;
325 } else if (!sscanf(optarg, "%ud", &protocol) ||
327 fprintf(stderr, "%s : Invalid protocol: %s\n",
338 fprintf(stderr, "-q only availble on Solaris\n");
343 opts |= OPT_IPSTATES;
346 parse_ipportstr(optarg, &saddr, &sport);
350 opts |= OPT_STATETOP;
354 "%s : state top facility not compiled in\n",
359 if (!sscanf(optarg, "%d", &refreshtime) ||
360 (refreshtime <= 0)) {
362 "%s : Invalid refreshtime < 1 : %s\n",
376 if (live_kernel == 1) {
377 bzero((char *)&fio, sizeof(fio));
378 bzero((char *)&ipsst, sizeof(ipsst));
379 bzero((char *)&ifrst, sizeof(ifrst));
381 ipfstate_live(device, &fiop, &ipsstp, &ifrstp,
384 ipfstate_dead(kern, &fiop, &ipsstp, &ifrstp, &frauthstp, &frf);
386 if (opts & OPT_IPSTATES) {
387 showipstates(ipsstp);
388 } else if (opts & OPT_SHOWLIST) {
390 if ((opts & OPT_OUTQUE) && (opts & OPT_INQUE)){
395 if (opts & OPT_FRSTATES)
396 showfrstates(ifrstp);
398 else if (opts & OPT_STATETOP)
399 topipstates(saddr, daddr, sport, dport,
400 protocol, refreshtime, topclosed);
402 else if (opts & OPT_AUTHSTATS)
403 showauthstates(frauthstp);
404 else if (opts & OPT_GROUPS)
407 showstats(fiop, frf);
414 * Fill in the stats structures from the live kernel, using a combination
415 * of ioctl's and copying directly from kernel memory.
417 int ipfstate_live(device, fiopp, ipsstpp, ifrstpp, frauthstpp, frfp)
420 ips_stat_t **ipsstpp;
421 ipfrstat_t **ifrstpp;
422 fr_authstat_t **frauthstpp;
426 if (!(opts & OPT_AUTHSTATS) && ioctl(ipf_fd, SIOCGETFS, fiopp) == -1) {
427 perror("ioctl(ipf:SIOCGETFS)");
431 if ((opts & OPT_IPSTATES)) {
432 if ((ioctl(state_fd, SIOCGETFS, ipsstpp) == -1)) {
433 perror("ioctl(state:SIOCGETFS)");
437 if ((opts & OPT_FRSTATES) &&
438 (ioctl(ipf_fd, SIOCGFRST, ifrstpp) == -1)) {
439 perror("ioctl(SIOCGFRST)");
443 if (opts & OPT_VERBOSE)
444 PRINTF("opts %#x name %s\n", opts, device);
446 if ((opts & OPT_AUTHSTATS) &&
447 (ioctl(auth_fd, SIOCATHST, frauthstpp) == -1)) {
448 perror("ioctl(SIOCATHST)");
452 if (ioctl(ipf_fd, SIOCGETFF, frfp) == -1)
453 perror("ioctl(SIOCGETFF)");
460 * Build up the stats structures from data held in the "core" memory.
461 * This is mainly useful when looking at data in crash dumps and ioctl's
462 * just won't work any more.
464 void ipfstate_dead(kernel, fiopp, ipsstpp, ifrstpp, frauthstpp, frfp)
467 ips_stat_t **ipsstpp;
468 ipfrstat_t **ifrstpp;
469 fr_authstat_t **frauthstpp;
472 static fr_authstat_t frauthst, *frauthstp;
473 static ips_stat_t ipsst, *ipsstp;
474 static ipfrstat_t ifrst, *ifrstp;
475 static friostat_t fio, *fiop;
478 struct nlist deadlist[42] = {
479 { "fr_authstats" }, /* 0 */
484 { "fr_authend" }, /* 5 */
489 { "fr_defaultauthage" }, /* 10 */
494 { "ips_num" }, /* 15 */
499 { "fr_statesize" }, /* 20 */
500 { "fr_state_doflush" },
504 { "ipfr_stats" }, /* 25 */
509 { "fr_nat_lock" }, /* 30 */
514 { "ipl_frouteok" }, /* 35 */
519 { "fr_flags" }, /* 40 */
524 frauthstp = &frauthst;
533 *frauthstpp = frauthstp;
535 bzero((char *)fiop, sizeof(*fiop));
536 bzero((char *)ipsstp, sizeof(*ipsstp));
537 bzero((char *)ifrstp, sizeof(*ifrstp));
538 bzero((char *)frauthstp, sizeof(*frauthstp));
540 if (nlist(kernel, deadlist) == -1) {
541 fprintf(stderr, "nlist error\n");
546 * This is for SIOCGETFF.
548 kmemcpy((char *)frfp, (u_long)deadlist[40].n_value, sizeof(*frfp));
551 * f_locks is a combination of the lock variable from each part of
552 * ipfilter (state, auth, nat, fragments).
554 kmemcpy((char *)fiop, (u_long)deadlist[13].n_value, sizeof(*fiop));
555 kmemcpy((char *)&fiop->f_locks[0], (u_long)deadlist[22].n_value,
556 sizeof(fiop->f_locks[0]));
557 kmemcpy((char *)&fiop->f_locks[0], (u_long)deadlist[30].n_value,
558 sizeof(fiop->f_locks[1]));
559 kmemcpy((char *)&fiop->f_locks[2], (u_long)deadlist[28].n_value,
560 sizeof(fiop->f_locks[2]));
561 kmemcpy((char *)&fiop->f_locks[3], (u_long)deadlist[12].n_value,
562 sizeof(fiop->f_locks[3]));
565 * Get pointers to each list of rules (active, inactive, in, out)
567 kmemcpy((char *)&rules, (u_long)deadlist[31].n_value, sizeof(rules));
568 fiop->f_fin[0] = rules[0][0];
569 fiop->f_fin[1] = rules[0][1];
570 fiop->f_fout[0] = rules[1][0];
571 fiop->f_fout[1] = rules[1][1];
574 * Same for IPv6, except make them null if support for it is not
578 kmemcpy((char *)&rules, (u_long)deadlist[32].n_value, sizeof(rules));
579 fiop->f_fin6[0] = rules[0][0];
580 fiop->f_fin6[1] = rules[0][1];
581 fiop->f_fout6[0] = rules[1][0];
582 fiop->f_fout6[1] = rules[1][1];
584 fiop->f_fin6[0] = NULL;
585 fiop->f_fin6[1] = NULL;
586 fiop->f_fout6[0] = NULL;
587 fiop->f_fout6[1] = NULL;
591 * Now get accounting rules pointers.
593 kmemcpy((char *)&rules, (u_long)deadlist[33].n_value, sizeof(rules));
594 fiop->f_acctin[0] = rules[0][0];
595 fiop->f_acctin[1] = rules[0][1];
596 fiop->f_acctout[0] = rules[1][0];
597 fiop->f_acctout[1] = rules[1][1];
600 kmemcpy((char *)&rules, (u_long)deadlist[34].n_value, sizeof(rules));
601 fiop->f_acctin6[0] = rules[0][0];
602 fiop->f_acctin6[1] = rules[0][1];
603 fiop->f_acctout6[0] = rules[1][0];
604 fiop->f_acctout6[1] = rules[1][1];
606 fiop->f_acctin6[0] = NULL;
607 fiop->f_acctin6[1] = NULL;
608 fiop->f_acctout6[0] = NULL;
609 fiop->f_acctout6[1] = NULL;
613 * A collection of "global" variables used inside the kernel which
614 * are all collected in friostat_t via ioctl.
616 kmemcpy((char *)&fiop->f_froute, (u_long)deadlist[35].n_value,
617 sizeof(fiop->f_froute));
618 kmemcpy((char *)&fiop->f_running, (u_long)deadlist[36].n_value,
619 sizeof(fiop->f_running));
620 kmemcpy((char *)&fiop->f_groups, (u_long)deadlist[37].n_value,
621 sizeof(fiop->f_groups));
622 kmemcpy((char *)&fiop->f_active, (u_long)deadlist[38].n_value,
623 sizeof(fiop->f_active));
624 kmemcpy((char *)&fiop->f_defpass, (u_long)deadlist[39].n_value,
625 sizeof(fiop->f_defpass));
628 * Build up the state information stats structure.
630 kmemcpy((char *)ipsstp, (u_long)deadlist[14].n_value, sizeof(*ipsstp));
631 kmemcpy((char *)&ipsstp->iss_active, (u_long)deadlist[15].n_value,
632 sizeof(ipsstp->iss_active));
633 ipsstp->iss_table = (void *)deadlist[18].n_value;
634 ipsstp->iss_list = (void *)deadlist[17].n_value;
637 * Build up the authentiation information stats structure.
639 kmemcpy((char *)frauthstp, (u_long)deadlist[0].n_value,
641 frauthstp->fas_faelist = (void *)deadlist[1].n_value;
644 * Build up the fragment information stats structure.
646 kmemcpy((char *)ifrstp, (u_long)deadlist[25].n_value,
648 ifrstp->ifs_table = (void *)deadlist[23].n_value;
649 ifrstp->ifs_nattab = (void *)deadlist[24].n_value;
650 kmemcpy((char *)&ifrstp->ifs_inuse, (u_long)deadlist[26].n_value,
651 sizeof(ifrstp->ifs_inuse));
656 * Display the kernel stats for packets blocked and passed and other
657 * associated running totals which are kept.
659 static void showstats(fp, frf)
665 PRINTF("dropped packets:\tin %lu\tout %lu\n",
666 fp->f_st[0].fr_drop, fp->f_st[1].fr_drop);
667 PRINTF("non-data packets:\tin %lu\tout %lu\n",
668 fp->f_st[0].fr_notdata, fp->f_st[1].fr_notdata);
669 PRINTF("no-data packets:\tin %lu\tout %lu\n",
670 fp->f_st[0].fr_nodata, fp->f_st[1].fr_nodata);
671 PRINTF("non-ip packets:\t\tin %lu\tout %lu\n",
672 fp->f_st[0].fr_notip, fp->f_st[1].fr_notip);
673 PRINTF(" bad packets:\t\tin %lu\tout %lu\n",
674 fp->f_st[0].fr_bad, fp->f_st[1].fr_bad);
675 PRINTF("copied messages:\tin %lu\tout %lu\n",
676 fp->f_st[0].fr_copy, fp->f_st[1].fr_copy);
679 PRINTF(" IPv6 packets:\t\tin %lu out %lu\n",
680 fp->f_st[0].fr_ipv6[0], fp->f_st[0].fr_ipv6[1]);
682 PRINTF(" input packets:\t\tblocked %lu passed %lu nomatch %lu",
683 fp->f_st[0].fr_block, fp->f_st[0].fr_pass,
685 PRINTF(" counted %lu short %lu\n",
686 fp->f_st[0].fr_acct, fp->f_st[0].fr_short);
687 PRINTF("output packets:\t\tblocked %lu passed %lu nomatch %lu",
688 fp->f_st[1].fr_block, fp->f_st[1].fr_pass,
690 PRINTF(" counted %lu short %lu\n",
691 fp->f_st[1].fr_acct, fp->f_st[1].fr_short);
692 PRINTF(" input packets logged:\tblocked %lu passed %lu\n",
693 fp->f_st[0].fr_bpkl, fp->f_st[0].fr_ppkl);
694 PRINTF("output packets logged:\tblocked %lu passed %lu\n",
695 fp->f_st[1].fr_bpkl, fp->f_st[1].fr_ppkl);
696 PRINTF(" packets logged:\tinput %lu output %lu\n",
697 fp->f_st[0].fr_pkl, fp->f_st[1].fr_pkl);
698 PRINTF(" log failures:\t\tinput %lu output %lu\n",
699 fp->f_st[0].fr_skip, fp->f_st[1].fr_skip);
700 PRINTF("fragment state(in):\tkept %lu\tlost %lu\tnot fragmented %lu\n",
701 fp->f_st[0].fr_nfr, fp->f_st[0].fr_bnfr, fp->f_st[0].fr_cfr);
702 PRINTF("fragment state(out):\tkept %lu\tlost %lu\tnot fragmented %lu\n",
703 fp->f_st[1].fr_nfr, fp->f_st[1].fr_bnfr, fp->f_st[1].fr_cfr);
704 PRINTF("packet state(in):\tkept %lu\tlost %lu\n",
705 fp->f_st[0].fr_ads, fp->f_st[0].fr_bads);
706 PRINTF("packet state(out):\tkept %lu\tlost %lu\n",
707 fp->f_st[1].fr_ads, fp->f_st[1].fr_bads);
708 PRINTF("ICMP replies:\t%lu\tTCP RSTs sent:\t%lu\n",
709 fp->f_st[0].fr_ret, fp->f_st[1].fr_ret);
710 PRINTF("Invalid source(in):\t%lu\n", fp->f_st[0].fr_badsrc);
711 PRINTF("Result cache hits(in):\t%lu\t(out):\t%lu\n",
712 fp->f_st[0].fr_chit, fp->f_st[1].fr_chit);
713 PRINTF("IN Pullups succeeded:\t%lu\tfailed:\t%lu\n",
714 fp->f_st[0].fr_pull[0], fp->f_st[0].fr_pull[1]);
715 PRINTF("OUT Pullups succeeded:\t%lu\tfailed:\t%lu\n",
716 fp->f_st[1].fr_pull[0], fp->f_st[1].fr_pull[1]);
717 PRINTF("Fastroute successes:\t%lu\tfailures:\t%lu\n",
718 fp->f_froute[0], fp->f_froute[1]);
719 PRINTF("TCP cksum fails(in):\t%lu\t(out):\t%lu\n",
720 fp->f_st[0].fr_tcpbad, fp->f_st[1].fr_tcpbad);
722 PRINTF("Packet log flags set: (%#x)\n", frf);
723 if (frf & FF_LOGPASS)
724 PRINTF("\tpackets passed through filter\n");
725 if (frf & FF_LOGBLOCK)
726 PRINTF("\tpackets blocked by filter\n");
727 if (frf & FF_LOGNOMATCH)
728 PRINTF("\tpackets not matched by filter\n");
735 * Print out a list of rules from the kernel, starting at the one passed.
737 static void printlist(fp)
743 for (n = 1; fp; n++) {
744 if (kmemcpy((char *)&fb, (u_long)fp, sizeof(fb)) == -1) {
749 if (opts & OPT_OUTQUE)
750 fp->fr_flags |= FR_OUTQUE;
751 if (opts & (OPT_HITS|OPT_VERBOSE))
753 PRINTF("%qu ", (unsigned long long) fp->fr_hits);
755 PRINTF("%lu ", fp->fr_hits);
757 if (opts & (OPT_ACCNT|OPT_VERBOSE))
759 PRINTF("%qu ", (unsigned long long) fp->fr_bytes);
761 PRINTF("%lu ", fp->fr_bytes);
763 if (opts & OPT_SHOWLINENO)
766 if (opts & OPT_VERBOSE)
769 printlist(fp->fr_grp);
775 * print out all of the asked for rule sets, using the stats struct as
776 * the base from which to get the pointers.
778 static void showlist(fiop)
779 struct friostat *fiop;
781 struct frentry *fp = NULL;
784 set = fiop->f_active;
785 if (opts & OPT_INACTIVE)
787 if (opts & OPT_ACCNT) {
789 if ((use_inet6) && (opts & OPT_OUTQUE)) {
791 fp = (struct frentry *)fiop->f_acctout6[set];
792 } else if ((use_inet6) && (opts & OPT_INQUE)) {
794 fp = (struct frentry *)fiop->f_acctin6[set];
797 if (opts & OPT_OUTQUE) {
799 fp = (struct frentry *)fiop->f_acctout[set];
800 } else if (opts & OPT_INQUE) {
802 fp = (struct frentry *)fiop->f_acctin[set];
804 FPRINTF(stderr, "No -i or -o given with -a\n");
809 if ((use_inet6) && (opts & OPT_OUTQUE)) {
811 fp = (struct frentry *)fiop->f_fout6[set];
812 } else if ((use_inet6) && (opts & OPT_INQUE)) {
814 fp = (struct frentry *)fiop->f_fin6[set];
817 if (opts & OPT_OUTQUE) {
819 fp = (struct frentry *)fiop->f_fout[set];
820 } else if (opts & OPT_INQUE) {
822 fp = (struct frentry *)fiop->f_fin[set];
826 if (opts & OPT_VERBOSE)
827 FPRINTF(stderr, "showlist:opts %#x i %d\n", opts, i);
829 if (opts & OPT_VERBOSE)
830 PRINTF("fp %p set %d\n", fp, set);
832 FPRINTF(stderr, "empty list for %s%s\n",
833 (opts & OPT_INACTIVE) ? "inactive " : "", filters[i]);
841 * Display ipfilter stateful filtering information
843 static void showipstates(ipsp)
846 ipstate_t *istab[IPSTATE_SIZE];
849 * If a list of states hasn't been asked for, only print out stats
851 if (!(opts & OPT_SHOWLIST)) {
852 PRINTF("IP states added:\n\t%lu TCP\n\t%lu UDP\n\t%lu ICMP\n",
853 ipsp->iss_tcp, ipsp->iss_udp, ipsp->iss_icmp);
854 PRINTF("\t%lu hits\n\t%lu misses\n", ipsp->iss_hits,
856 PRINTF("\t%lu maximum\n\t%lu no memory\n\t%lu bkts in use\n",
857 ipsp->iss_max, ipsp->iss_nomem, ipsp->iss_inuse);
858 PRINTF("\t%lu logged\n\t%lu log failures\n",
859 ipsp->iss_logged, ipsp->iss_logfail);
860 PRINTF("\t%lu active\n\t%lu expired\n\t%lu closed\n",
861 ipsp->iss_active, ipsp->iss_expire, ipsp->iss_fin);
865 if (kmemcpy((char *)istab, (u_long)ipsp->iss_table, sizeof(istab)))
869 * Print out all the state information currently held in the kernel.
871 while (ipsp->iss_list != NULL) {
872 ipsp->iss_list = printstate(ipsp->iss_list, opts);
879 * Displays the list of interfaces of which IPFilter has taken control in
882 void showqiflist(kern)
885 struct nlist qifnlist[2] = {
895 if (nlist(kern, qifnlist) == -1) {
896 fprintf(stderr, "nlist error\n");
900 printf("List of interfaces bound by IPFilter:\n");
901 if (kmemcpy((char *)&qf, (u_long)qifnlist[0].n_value, sizeof(qf)))
904 if (kmemcpy((char *)&qif, (u_long)qf, sizeof(qif)))
906 if (kmemcpy((char *)&ill, (u_long)qif.qf_ill, sizeof(ill)))
908 printf("Name: %-8s Header Length: %2d SAP: %s (%04x) PPA %d",
909 qif.qf_name, qif.qf_hl,
911 (qif.qf_sap == IP6_DL_SAP) ? "IPv6" : "IPv4"
915 , qif.qf_sap, ill.ill_ppa);
916 printf(" %ld %ld", qif.qf_incnt, qif.qf_outcnt);
925 static void topipstates(saddr, daddr, sport, dport, protocol,
926 refreshtime, topclosed)
927 struct in_addr saddr;
928 struct in_addr daddr;
935 char str1[STSTRSIZE], str2[STSTRSIZE], str3[STSTRSIZE], str4[STSTRSIZE];
936 int maxtsentries = 0, reverse = 0, sorting = STSORT_DEFAULT;
937 int i, j, winx, tsentry, maxx, maxy, redraw = 0;
938 ipstate_t *istab[IPSTATE_SIZE], ips;
939 ips_stat_t ipsst, *ipsstp = &ipsst;
940 statetop_t *tstable = NULL, *tp;
941 char hostnm[HOSTNMLEN];
942 struct protoent *proto;
946 struct pollfd set[1];
948 struct timeval selecttimeout;
952 /* init ncurses stuff */
958 gethostname(hostnm, sizeof(hostnm) - 1);
959 hostnm[sizeof(hostnm) - 1] = '\0';
961 /* repeat until user aborts */
964 /* get state table */
965 bzero((char *)&ipsst, sizeof(&ipsst));
966 if ((ioctl(state_fd, SIOCGETFS, &ipsstp) == -1)) {
967 perror("ioctl(SIOCGETFS)");
970 if (kmemcpy((char *)istab, (u_long)ipsstp->iss_table,
974 /* clear the history */
977 /* read the state table and store in tstable */
978 while (ipsstp->iss_list) {
979 if (kmemcpy((char *)&ips, (u_long)ipsstp->iss_list,
982 ipsstp->iss_list = ips.is_next;
984 if (((saddr.s_addr == INADDR_ANY) ||
985 (saddr.s_addr == ips.is_saddr)) &&
986 ((daddr.s_addr == INADDR_ANY) ||
987 (daddr.s_addr == ips.is_daddr)) &&
988 ((protocol < 0) || (protocol == ips.is_p)) &&
989 (((ips.is_p != IPPROTO_TCP) &&
990 (ips.is_p != IPPROTO_UDP)) ||
992 (htons(sport) == ips.is_sport)) &&
994 (htons(dport) == ips.is_dport)))) &&
995 (topclosed || (ips.is_p != IPPROTO_TCP) ||
996 (ips.is_state[0] < TCPS_LAST_ACK) ||
997 (ips.is_state[1] < TCPS_LAST_ACK))) {
999 * if necessary make room for this state
1003 if (!maxtsentries ||
1004 (tsentry == maxtsentries)) {
1006 maxtsentries += STGROWSIZE;
1007 tstable = realloc(tstable, maxtsentries * sizeof(statetop_t));
1014 /* fill structure */
1015 tp = tstable + tsentry;
1016 tp->st_src = ips.is_src;
1017 tp->st_dst = ips.is_dst;
1018 tp->st_p = ips.is_p;
1019 tp->st_state[0] = ips.is_state[0];
1020 tp->st_state[1] = ips.is_state[1];
1021 tp->st_pkts = ips.is_pkts;
1022 tp->st_bytes = ips.is_bytes;
1023 tp->st_age = ips.is_age;
1024 if ((ips.is_p == IPPROTO_TCP) ||
1025 (ips.is_p == IPPROTO_UDP)) {
1026 tp->st_sport = ips.is_sport;
1027 tp->st_dport = ips.is_dport;
1034 /* sort the array */
1039 qsort(tstable, tsentry + 1,
1040 sizeof(statetop_t), sort_p);
1043 qsort(tstable, tsentry + 1,
1044 sizeof(statetop_t), sort_pkts);
1047 qsort(tstable, tsentry + 1,
1048 sizeof(statetop_t), sort_bytes);
1051 qsort(tstable, tsentry + 1,
1052 sizeof(statetop_t), sort_ttl);
1055 qsort(tstable, tsentry + 1,
1056 sizeof(statetop_t), sort_srcip);
1059 qsort(tstable, tsentry + 1,
1060 sizeof(statetop_t), sort_dstip);
1068 getmaxyx(stdscr, maxy, maxx);
1072 sprintf(str1, "%s - %s - state top", hostnm, IPL_VERSION);
1073 for (j = 0 ; j < (maxx - 8 - strlen(str1)) / 2; j++)
1078 /* just for fun add a clock */
1079 move(winx, maxx - 8);
1081 strftime(str1, 80, "%T", localtime(&t));
1082 printw("%s\n", str1);
1085 * print the display filters, this is placed in the loop,
1086 * because someday I might add code for changing these
1087 * while the programming is running :-)
1090 sprintf(str1, "%s,%d", inet_ntoa(saddr), sport);
1092 sprintf(str1, "%s", inet_ntoa(saddr));
1095 sprintf(str2, "%s,%d", inet_ntoa(daddr), dport);
1097 sprintf(str2, "%s", inet_ntoa(daddr));
1100 strcpy(str3, "any");
1101 else if ((proto = getprotobynumber(protocol)) != NULL)
1102 sprintf(str3, "%s", proto->p_name);
1104 sprintf(str3, "%d", protocol);
1109 sprintf(str4, "proto");
1112 sprintf(str4, "# pkts");
1115 sprintf(str4, "# bytes");
1118 sprintf(str4, "ttl");
1121 sprintf(str4, "srcip");
1124 sprintf(str4, "dstip");
1127 sprintf(str4, "unknown");
1132 strcat(str4, " (reverse)");
1136 printw("Src = %s Dest = %s Proto = %s Sorted by = %s\n\n",
1137 str1, str2, str3, str4);
1139 /* print column description */
1143 printw("%-21s %-21s %3s %4s %7s %9s %9s\n", "Source IP",
1144 "Destination IP", "ST", "PR", "#pkts", "#bytes", "ttl");
1147 /* print all the entries */
1152 if (tsentry > maxy - 6)
1154 for (i = 0; i <= tsentry; i++) {
1155 /* print src/dest and port */
1156 if ((tp->st_p == IPPROTO_TCP) ||
1157 (tp->st_p == IPPROTO_UDP)) {
1158 sprintf(str1, "%s,%hu",
1159 inet_ntoa(tp->st_src.in4),
1160 ntohs(tp->st_sport));
1161 sprintf(str2, "%s,%hu",
1162 inet_ntoa(tp->st_dst.in4),
1163 ntohs(tp->st_dport));
1165 sprintf(str1, "%s", inet_ntoa(tp->st_src.in4));
1166 sprintf(str2, "%s", inet_ntoa(tp->st_dst.in4));
1170 printw("%-21s %-21s", str1, str2);
1173 sprintf(str1, "%X/%X", tp->st_state[0],
1175 printw(" %3s", str1);
1178 proto = getprotobynumber(tp->st_p);
1180 strncpy(str1, proto->p_name, 4);
1183 sprintf(str1, "%d", tp->st_p);
1185 printw(" %4s", str1);
1186 /* print #pkt/#bytes */
1188 printw(" %7qu %9qu", (unsigned long long) tp->st_pkts,
1189 (unsigned long long) tp->st_bytes);
1191 printw(" %7lu %9lu", tp->st_pkts, tp->st_bytes);
1193 printw(" %9s", ttl_to_string(tp->st_age));
1201 /* screen data structure is filled, now update the screen */
1211 /* wait for key press or a 1 second time out period */
1214 set[0].events = POLLIN;
1215 poll(set, 1, refreshtime * 1000);
1217 /* if key pressed, read all waiting keys */
1218 if (set[0].revents & POLLIN)
1220 selecttimeout.tv_sec = refreshtime;
1221 selecttimeout.tv_usec = 0;
1224 select(1, &readfd, NULL, NULL, &selecttimeout);
1226 /* if key pressed, read all waiting keys */
1227 if (FD_ISSET(0, &readfd))
1235 if (isalpha(c) && isupper(c))
1239 } else if (c == 'q') {
1240 break; /* exits while() loop */
1241 } else if (c == 'r') {
1243 } else if (c == 's') {
1245 if (sorting > STSORT_MAX)
1259 * Show fragment cache information that's held in the kernel.
1261 static void showfrstates(ifsp)
1264 struct ipfr *ipfrtab[IPFT_SIZE], ifr;
1269 * print out the numeric statistics
1271 PRINTF("IP fragment states:\n\t%lu new\n\t%lu expired\n\t%lu hits\n",
1272 ifsp->ifs_new, ifsp->ifs_expire, ifsp->ifs_hits);
1273 PRINTF("\t%lu no memory\n\t%lu already exist\n",
1274 ifsp->ifs_nomem, ifsp->ifs_exists);
1275 PRINTF("\t%lu inuse\n", ifsp->ifs_inuse);
1276 if (kmemcpy((char *)ipfrtab, (u_long)ifsp->ifs_table, sizeof(ipfrtab)))
1280 * Print out the contents (if any) of the fragment cache table.
1283 for (i = 0; i < IPFT_SIZE; i++)
1284 while (ipfrtab[i]) {
1285 if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i],
1288 PRINTF("%s -> ", hostname(4, &ifr.ipfr_src));
1289 if (kmemcpy((char *)&fr, (u_long)ifr.ipfr_rule,
1292 PRINTF("%s id %d ttl %d pr %d seen0 %d ifp %p tos %#02x = fl %#x\n",
1293 hostname(4, &ifr.ipfr_dst), ntohs(ifr.ipfr_id),
1294 ifr.ipfr_ttl, ifr.ipfr_p, ifr.ipfr_seen0,
1295 ifr.ipfr_ifp, ifr.ipfr_tos, fr.fr_flags);
1296 ipfrtab[i] = ifr.ipfr_next;
1298 if (kmemcpy((char *)ipfrtab, (u_long)ifsp->ifs_nattab,sizeof(ipfrtab)))
1300 for (i = 0; i < IPFT_SIZE; i++)
1301 while (ipfrtab[i]) {
1302 if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i],
1305 PRINTF("NAT: %s -> ", hostname(4, &ifr.ipfr_src));
1306 if (kmemcpy((char *)&fr, (u_long)ifr.ipfr_rule,
1309 PRINTF("%s %d %d %d %#02x = %#x\n",
1310 hostname(4, &ifr.ipfr_dst), ifr.ipfr_id,
1311 ifr.ipfr_ttl, ifr.ipfr_p, ifr.ipfr_tos,
1313 ipfrtab[i] = ifr.ipfr_next;
1319 * Show stats on how auth within IPFilter has been used
1321 static void showauthstates(asp)
1324 frauthent_t *frap, fra;
1327 printf("Authorisation hits: %qu\tmisses %qu\n",
1328 (unsigned long long) asp->fas_hits,
1329 (unsigned long long) asp->fas_miss);
1331 printf("Authorisation hits: %ld\tmisses %ld\n", asp->fas_hits,
1334 printf("nospace %ld\nadded %ld\nsendfail %ld\nsendok %ld\n",
1335 asp->fas_nospace, asp->fas_added, asp->fas_sendfail,
1337 printf("queok %ld\nquefail %ld\nexpire %ld\n",
1338 asp->fas_queok, asp->fas_quefail, asp->fas_expire);
1340 frap = asp->fas_faelist;
1342 if (kmemcpy((char *)&fra, (u_long)frap, sizeof(fra)) == -1)
1345 printf("age %ld\t", fra.fae_age);
1346 printfr(&fra.fae_fr);
1347 frap = fra.fae_next;
1353 * Display groups used for each of filter rules, accounting rules and
1354 * authentication, separately.
1356 static void showgroups(fiop)
1357 struct friostat *fiop;
1359 static char *gnames[3] = { "Filter", "Accounting", "Authentication" };
1363 on = fiop->f_active;
1366 for (i = 0; i < 3; i++) {
1367 printf("%s groups (active):\n", gnames[i]);
1368 for (fp = fiop->f_groups[i][on]; fp; fp = grp.fg_next)
1369 if (kmemcpy((char *)&grp, (u_long)fp, sizeof(grp)))
1372 printf("%hu\n", grp.fg_num);
1373 printf("%s groups (inactive):\n", gnames[i]);
1374 for (fp = fiop->f_groups[i][off]; fp; fp = grp.fg_next)
1375 if (kmemcpy((char *)&grp, (u_long)fp, sizeof(grp)))
1378 printf("%hu\n", grp.fg_num);
1382 static void parse_ipportstr(argument, ip, port)
1383 const char *argument;
1390 /* make working copy of argument, Theoretically you must be able
1391 * to write to optarg, but that seems very ugly to me....
1393 if ((s = malloc(strlen(argument) + 1)) == NULL)
1395 strcpy(s, argument);
1398 if ((comma = strchr(s, ',')) != NULL) {
1399 if (!strcasecmp(s, "any")) {
1401 } else if (!sscanf(comma + 1, "%d", port) ||
1402 (*port < 0) || (*port > 65535)) {
1403 fprintf(stderr, "Invalid port specfication in %s\n",
1411 /* get ip address */
1412 if (!strcasecmp(s, "any")) {
1413 ip->s_addr = INADDR_ANY;
1414 } else if (!inet_aton(s, ip)) {
1415 fprintf(stderr, "Invalid IP address: %s\n", s);
1419 /* free allocated memory */
1425 static char ttlbuf[STSTRSIZE];
1427 static char *ttl_to_string(ttl)
1431 int hours, minutes, seconds;
1433 /* ttl is in half seconds */
1442 sprintf(ttlbuf, "%2d:%02d:%02d", hours, minutes, seconds);
1444 sprintf(ttlbuf, "%2d:%02d", minutes, seconds);
1449 static int sort_pkts(a, b)
1454 register const statetop_t *ap = a;
1455 register const statetop_t *bp = b;
1457 if (ap->st_pkts == bp->st_pkts)
1459 else if (ap->st_pkts < bp->st_pkts)
1465 static int sort_bytes(a, b)
1469 register const statetop_t *ap = a;
1470 register const statetop_t *bp = b;
1472 if (ap->st_bytes == bp->st_bytes)
1474 else if (ap->st_bytes < bp->st_bytes)
1480 static int sort_p(a, b)
1484 register const statetop_t *ap = a;
1485 register const statetop_t *bp = b;
1487 if (ap->st_p == bp->st_p)
1489 else if (ap->st_p < bp->st_p)
1495 static int sort_ttl(a, b)
1499 register const statetop_t *ap = a;
1500 register const statetop_t *bp = b;
1502 if (ap->st_age == bp->st_age)
1504 else if (ap->st_age < bp->st_age)
1509 static int sort_srcip(a, b)
1513 register const statetop_t *ap = a;
1514 register const statetop_t *bp = b;
1516 if (ntohl(ap->st_src.in4.s_addr) == ntohl(bp->st_src.in4.s_addr))
1518 else if (ntohl(ap->st_src.in4.s_addr) > ntohl(bp->st_src.in4.s_addr))
1523 static int sort_dstip(a, b)
1527 register const statetop_t *ap = a;
1528 register const statetop_t *bp = b;
1530 if (ntohl(ap->st_dst.in4.s_addr) == ntohl(bp->st_dst.in4.s_addr))
1532 else if (ntohl(ap->st_dst.in4.s_addr) > ntohl(bp->st_dst.in4.s_addr))