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>
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__) && (__NetBSD_Version__ < 105000000)
39 # if defined(__svr4__) || defined(__SVR4)
40 # include <sys/select.h>
42 # undef STATETOP /* NOT supported on SunOS4 */
51 #include <sys/socket.h>
52 #include <sys/ioctl.h>
53 #include <netinet/in.h>
54 #include <arpa/inet.h>
55 #include <netinet/in_systm.h>
56 #include <netinet/ip.h>
58 #if __FreeBSD_version >= 300000
59 # include <net/if_var.h>
62 #include <arpa/nameser.h>
64 #include <netinet/tcp.h>
65 #if defined(STATETOP) && !defined(linux)
66 # include <netinet/ip_var.h>
67 # include <netinet/tcp_fsm.h>
69 #include "netinet/ip_compat.h"
70 #include "netinet/ip_fil.h"
72 #include "netinet/ip_nat.h"
73 #include "netinet/ip_frag.h"
74 #include "netinet/ip_state.h"
75 #include "netinet/ip_proxy.h"
76 #include "netinet/ip_auth.h"
78 # include "netinet/ipl.h"
80 # if SOLARIS || defined(__NetBSD__) || defined(_BSDI_VERSION) || \
91 #if defined(__NetBSD__) || (__OpenBSD__)
96 static const char sccsid[] = "@(#)fils.c 1.21 4/20/96 (C) 1993-2000 Darren Reed";
97 static const char rcsid[] = "@(#)$Id: fils.c,v 2.21.2.34 2002/02/22 15:32:45 darrenr Exp $";
103 #define PRINTF (void)printf
104 #define FPRINTF (void)fprintf
108 static char *filters[4] = { "ipfilter(in)", "ipfilter(out)",
109 "ipacct(in)", "ipacct(out)" };
117 #define STGROWSIZE 16
121 #define STSORT_PKTS 1
122 #define STSORT_BYTES 2
124 #define STSORT_SRCIP 4
125 #define STSORT_DSTIP 5
126 #define STSORT_MAX STSORT_DSTIP
127 #define STSORT_DEFAULT STSORT_BYTES
130 typedef struct statetop {
143 extern int main __P((int, char *[]));
144 static void showstats __P((friostat_t *, u_32_t));
145 static void showfrstates __P((ipfrstat_t *));
146 static void showlist __P((friostat_t *));
147 static void showipstates __P((ips_stat_t *));
148 static void showauthstates __P((fr_authstat_t *));
149 static void showgroups __P((friostat_t *));
150 static void Usage __P((char *));
151 static void printlist __P((frentry_t *));
152 static void parse_ipportstr __P((const char *, struct in_addr *, int *));
153 static int ipfstate_live __P((char *, friostat_t **, ips_stat_t **,
154 ipfrstat_t **, fr_authstat_t **, u_32_t *));
155 static void ipfstate_dead __P((char *, friostat_t **, ips_stat_t **,
156 ipfrstat_t **, fr_authstat_t **, u_32_t *));
158 static void topipstates __P((struct in_addr, struct in_addr, int, int, int, int, int));
159 static char *ttl_to_string __P((long));
160 static int sort_p __P((const void *, const void *));
161 static int sort_pkts __P((const void *, const void *));
162 static int sort_bytes __P((const void *, const void *));
163 static int sort_ttl __P((const void *, const void *));
164 static int sort_srcip __P((const void *, const void *));
165 static int sort_dstip __P((const void *, const void *));
168 void showqiflist __P((char *));
172 static void Usage(name)
176 fprintf(stderr, "Usage: %s [-6aAfhIinosv] [-d <device>]\n", name);
178 fprintf(stderr, "Usage: %s [-aAfhIinosv] [-d <device>]\n", name);
180 fprintf(stderr, "\t\t[-M corefile] [-N symbol-list]\n");
181 fprintf(stderr, " %s -t [-S source address] [-D destination address] [-P protocol] [-T refreshtime] [-C] [-d <device>]\n", name);
190 fr_authstat_t frauthst;
191 fr_authstat_t *frauthstp = &frauthst;
193 friostat_t *fiop = &fio;
195 ips_stat_t *ipsstp = &ipsst;
197 ipfrstat_t *ifrstp = &ifrst;
198 char *device = IPL_NAME, *memf = NULL;
201 struct protoent *proto;
203 int protocol = -1; /* -1 = wild card for any protocol */
204 int refreshtime = 1; /* default update time */
205 int sport = -1; /* -1 = wild card for any source port */
206 int dport = -1; /* -1 = wild card for any dest port */
207 int topclosed = 0; /* do not show closed tcp sessions */
208 struct in_addr saddr, daddr;
211 saddr.s_addr = INADDR_ANY; /* default any source addr */
212 daddr.s_addr = INADDR_ANY; /* default any dest addr */
215 * Parse these two arguments now lest there be any buffer overflows
216 * in the parsing of the rest.
219 while ((c = getopt(argc, argv, "6aACfghIilnoqstvd:D:M:N:P:S:T:")) != -1)
233 if (kern != NULL || memf != NULL)
235 (void)setuid(getuid());
236 (void)setgid(getgid());
239 if (openkmem(kern, memf) == -1)
242 (void)setuid(getuid());
243 (void)setgid(getgid());
245 while ((c = getopt(argc, argv, "6aACfghIilnoqstvd:D:M:N:P:S:T:")) != -1)
255 opts |= OPT_ACCNT|OPT_SHOWLIST;
258 device = IPAUTH_NAME;
259 opts |= OPT_AUTHSTATS;
268 parse_ipportstr(optarg, &daddr, &dport);
271 opts |= OPT_FRSTATES;
280 opts |= OPT_INQUE|OPT_SHOWLIST;
283 opts |= OPT_INACTIVE;
286 opts |= OPT_SHOWLIST;
293 opts |= OPT_SHOWLINENO;
296 opts |= OPT_OUTQUE|OPT_SHOWLIST;
299 if ((proto = getprotobyname(optarg)) != NULL) {
300 protocol = proto->p_proto;
301 } else if (!sscanf(optarg, "%ud", &protocol) ||
303 fprintf(stderr, "%s : Invalid protocol: %s\n",
314 fprintf(stderr, "-q only availble on Solaris\n");
319 opts |= OPT_IPSTATES;
322 parse_ipportstr(optarg, &saddr, &sport);
326 opts |= OPT_STATETOP;
330 "%s : state top facility not compiled in\n",
335 if (!sscanf(optarg, "%d", &refreshtime) ||
336 (refreshtime <= 0)) {
338 "%s : Invalid refreshtime < 1 : %s\n",
352 if (live_kernel == 1) {
353 bzero((char *)&fio, sizeof(fio));
354 bzero((char *)&ipsst, sizeof(ipsst));
355 bzero((char *)&ifrst, sizeof(ifrst));
357 fd = ipfstate_live(device, &fiop, &ipsstp, &ifrstp,
360 ipfstate_dead(kern, &fiop, &ipsstp, &ifrstp, &frauthstp, &frf);
362 if (opts & OPT_IPSTATES) {
363 showipstates(ipsstp);
364 } else if (opts & OPT_SHOWLIST) {
366 if ((opts & OPT_OUTQUE) && (opts & OPT_INQUE)){
371 if (opts & OPT_FRSTATES)
372 showfrstates(ifrstp);
374 else if (opts & OPT_STATETOP)
375 topipstates(saddr, daddr, sport, dport,
376 protocol, refreshtime, topclosed);
378 else if (opts & OPT_AUTHSTATS)
379 showauthstates(frauthstp);
380 else if (opts & OPT_GROUPS)
383 showstats(fiop, frf);
390 * Fill in the stats structures from the live kernel, using a combination
391 * of ioctl's and copying directly from kernel memory.
393 int ipfstate_live(device, fiopp, ipsstpp, ifrstpp, frauthstpp, frfp)
396 ips_stat_t **ipsstpp;
397 ipfrstat_t **ifrstpp;
398 fr_authstat_t **frauthstpp;
403 if ((fd = open(device, O_RDONLY)) < 0) {
408 if (!(opts & OPT_AUTHSTATS) && ioctl(fd, SIOCGETFS, fiopp) == -1) {
409 perror("ioctl(ipf:SIOCGETFS)");
413 if ((opts & OPT_IPSTATES)) {
414 int sfd = open(IPL_STATE, O_RDONLY);
420 if ((ioctl(sfd, SIOCGETFS, ipsstpp) == -1)) {
421 perror("ioctl(state:SIOCGETFS)");
426 if ((opts & OPT_FRSTATES) && (ioctl(fd, SIOCGFRST, ifrstpp) == -1)) {
427 perror("ioctl(SIOCGFRST)");
431 if (opts & OPT_VERBOSE)
432 PRINTF("opts %#x name %s\n", opts, device);
434 if ((opts & OPT_AUTHSTATS) &&
435 (ioctl(fd, SIOCATHST, frauthstpp) == -1)) {
436 perror("ioctl(SIOCATHST)");
440 if (ioctl(fd, SIOCGETFF, frfp) == -1)
441 perror("ioctl(SIOCGETFF)");
448 * Build up the stats structures from data held in the "core" memory.
449 * This is mainly useful when looking at data in crash dumps and ioctl's
450 * just won't work any more.
452 void ipfstate_dead(kernel, fiopp, ipsstpp, ifrstpp, frauthstpp, frfp)
455 ips_stat_t **ipsstpp;
456 ipfrstat_t **ifrstpp;
457 fr_authstat_t **frauthstpp;
460 static fr_authstat_t frauthst, *frauthstp;
461 static ips_stat_t ipsst, *ipsstp;
462 static ipfrstat_t ifrst, *ifrstp;
463 static friostat_t fio, *fiop;
466 struct nlist deadlist[42] = {
467 { "fr_authstats" }, /* 0 */
472 { "fr_authend" }, /* 5 */
477 { "fr_defaultauthage" }, /* 10 */
482 { "ips_num" }, /* 15 */
487 { "fr_statesize" }, /* 20 */
488 { "fr_state_doflush" },
492 { "ipfr_stats" }, /* 25 */
497 { "fr_nat_lock" }, /* 30 */
502 { "ipl_frouteok" }, /* 35 */
507 { "fr_flags" }, /* 40 */
512 frauthstp = &frauthst;
521 *frauthstpp = frauthstp;
523 bzero((char *)fiop, sizeof(*fiop));
524 bzero((char *)ipsstp, sizeof(*ipsstp));
525 bzero((char *)ifrstp, sizeof(*ifrstp));
526 bzero((char *)frauthstp, sizeof(*frauthstp));
528 if (nlist(kernel, deadlist) == -1) {
529 fprintf(stderr, "nlist error\n");
534 * This is for SIOCGETFF.
536 kmemcpy((char *)frfp, (u_long)deadlist[40].n_value, sizeof(*frfp));
539 * f_locks is a combination of the lock variable from each part of
540 * ipfilter (state, auth, nat, fragments).
542 kmemcpy((char *)fiop, (u_long)deadlist[13].n_value, sizeof(*fiop));
543 kmemcpy((char *)&fiop->f_locks[0], (u_long)deadlist[22].n_value,
544 sizeof(fiop->f_locks[0]));
545 kmemcpy((char *)&fiop->f_locks[0], (u_long)deadlist[30].n_value,
546 sizeof(fiop->f_locks[1]));
547 kmemcpy((char *)&fiop->f_locks[2], (u_long)deadlist[28].n_value,
548 sizeof(fiop->f_locks[2]));
549 kmemcpy((char *)&fiop->f_locks[3], (u_long)deadlist[12].n_value,
550 sizeof(fiop->f_locks[3]));
553 * Get pointers to each list of rules (active, inactive, in, out)
555 kmemcpy((char *)&rules, (u_long)deadlist[31].n_value, sizeof(rules));
556 fiop->f_fin[0] = rules[0][0];
557 fiop->f_fin[1] = rules[0][1];
558 fiop->f_fout[0] = rules[1][0];
559 fiop->f_fout[1] = rules[1][1];
562 * Same for IPv6, except make them null if support for it is not
566 kmemcpy((char *)&rules, (u_long)deadlist[32].n_value, sizeof(rules));
567 fiop->f_fin6[0] = rules[0][0];
568 fiop->f_fin6[1] = rules[0][1];
569 fiop->f_fout6[0] = rules[1][0];
570 fiop->f_fout6[1] = rules[1][1];
572 fiop->f_fin6[0] = NULL;
573 fiop->f_fin6[1] = NULL;
574 fiop->f_fout6[0] = NULL;
575 fiop->f_fout6[1] = NULL;
579 * Now get accounting rules pointers.
581 kmemcpy((char *)&rules, (u_long)deadlist[33].n_value, sizeof(rules));
582 fiop->f_acctin[0] = rules[0][0];
583 fiop->f_acctin[1] = rules[0][1];
584 fiop->f_acctout[0] = rules[1][0];
585 fiop->f_acctout[1] = rules[1][1];
588 kmemcpy((char *)&rules, (u_long)deadlist[34].n_value, sizeof(rules));
589 fiop->f_acctin6[0] = rules[0][0];
590 fiop->f_acctin6[1] = rules[0][1];
591 fiop->f_acctout6[0] = rules[1][0];
592 fiop->f_acctout6[1] = rules[1][1];
594 fiop->f_acctin6[0] = NULL;
595 fiop->f_acctin6[1] = NULL;
596 fiop->f_acctout6[0] = NULL;
597 fiop->f_acctout6[1] = NULL;
601 * A collection of "global" variables used inside the kernel which
602 * are all collected in friostat_t via ioctl.
604 kmemcpy((char *)&fiop->f_froute, (u_long)deadlist[35].n_value,
605 sizeof(fiop->f_froute));
606 kmemcpy((char *)&fiop->f_running, (u_long)deadlist[36].n_value,
607 sizeof(fiop->f_running));
608 kmemcpy((char *)&fiop->f_groups, (u_long)deadlist[37].n_value,
609 sizeof(fiop->f_groups));
610 kmemcpy((char *)&fiop->f_active, (u_long)deadlist[38].n_value,
611 sizeof(fiop->f_active));
612 kmemcpy((char *)&fiop->f_defpass, (u_long)deadlist[39].n_value,
613 sizeof(fiop->f_defpass));
616 * Build up the state information stats structure.
618 kmemcpy((char *)ipsstp, (u_long)deadlist[14].n_value, sizeof(*ipsstp));
619 kmemcpy((char *)&ipsstp->iss_active, (u_long)deadlist[15].n_value,
620 sizeof(ipsstp->iss_active));
621 ipsstp->iss_table = (void *)deadlist[18].n_value;
622 ipsstp->iss_list = (void *)deadlist[17].n_value;
625 * Build up the authentiation information stats structure.
627 kmemcpy((char *)frauthstp, (u_long)deadlist[0].n_value,
629 frauthstp->fas_faelist = (void *)deadlist[1].n_value;
632 * Build up the fragment information stats structure.
634 kmemcpy((char *)ifrstp, (u_long)deadlist[25].n_value,
636 ifrstp->ifs_table = (void *)deadlist[23].n_value;
637 ifrstp->ifs_nattab = (void *)deadlist[24].n_value;
638 kmemcpy((char *)&ifrstp->ifs_inuse, (u_long)deadlist[26].n_value,
639 sizeof(ifrstp->ifs_inuse));
644 * Display the kernel stats for packets blocked and passed and other
645 * associated running totals which are kept.
647 static void showstats(fp, frf)
653 PRINTF("dropped packets:\tin %lu\tout %lu\n",
654 fp->f_st[0].fr_drop, fp->f_st[1].fr_drop);
655 PRINTF("non-data packets:\tin %lu\tout %lu\n",
656 fp->f_st[0].fr_notdata, fp->f_st[1].fr_notdata);
657 PRINTF("no-data packets:\tin %lu\tout %lu\n",
658 fp->f_st[0].fr_nodata, fp->f_st[1].fr_nodata);
659 PRINTF("non-ip packets:\t\tin %lu\tout %lu\n",
660 fp->f_st[0].fr_notip, fp->f_st[1].fr_notip);
661 PRINTF(" bad packets:\t\tin %lu\tout %lu\n",
662 fp->f_st[0].fr_bad, fp->f_st[1].fr_bad);
663 PRINTF("copied messages:\tin %lu\tout %lu\n",
664 fp->f_st[0].fr_copy, fp->f_st[1].fr_copy);
667 PRINTF(" IPv6 packets:\t\tin %lu out %lu\n",
668 fp->f_st[0].fr_ipv6[0], fp->f_st[0].fr_ipv6[1]);
670 PRINTF(" input packets:\t\tblocked %lu passed %lu nomatch %lu",
671 fp->f_st[0].fr_block, fp->f_st[0].fr_pass,
673 PRINTF(" counted %lu short %lu\n",
674 fp->f_st[0].fr_acct, fp->f_st[0].fr_short);
675 PRINTF("output packets:\t\tblocked %lu passed %lu nomatch %lu",
676 fp->f_st[1].fr_block, fp->f_st[1].fr_pass,
678 PRINTF(" counted %lu short %lu\n",
679 fp->f_st[1].fr_acct, fp->f_st[1].fr_short);
680 PRINTF(" input packets logged:\tblocked %lu passed %lu\n",
681 fp->f_st[0].fr_bpkl, fp->f_st[0].fr_ppkl);
682 PRINTF("output packets logged:\tblocked %lu passed %lu\n",
683 fp->f_st[1].fr_bpkl, fp->f_st[1].fr_ppkl);
684 PRINTF(" packets logged:\tinput %lu output %lu\n",
685 fp->f_st[0].fr_pkl, fp->f_st[1].fr_pkl);
686 PRINTF(" log failures:\t\tinput %lu output %lu\n",
687 fp->f_st[0].fr_skip, fp->f_st[1].fr_skip);
688 PRINTF("fragment state(in):\tkept %lu\tlost %lu\n",
689 fp->f_st[0].fr_nfr, fp->f_st[0].fr_bnfr);
690 PRINTF("fragment state(out):\tkept %lu\tlost %lu\n",
691 fp->f_st[1].fr_nfr, fp->f_st[1].fr_bnfr);
692 PRINTF("packet state(in):\tkept %lu\tlost %lu\n",
693 fp->f_st[0].fr_ads, fp->f_st[0].fr_bads);
694 PRINTF("packet state(out):\tkept %lu\tlost %lu\n",
695 fp->f_st[1].fr_ads, fp->f_st[1].fr_bads);
696 PRINTF("ICMP replies:\t%lu\tTCP RSTs sent:\t%lu\n",
697 fp->f_st[0].fr_ret, fp->f_st[1].fr_ret);
698 PRINTF("Invalid source(in):\t%lu\n", fp->f_st[0].fr_badsrc);
699 PRINTF("Result cache hits(in):\t%lu\t(out):\t%lu\n",
700 fp->f_st[0].fr_chit, fp->f_st[1].fr_chit);
701 PRINTF("IN Pullups succeeded:\t%lu\tfailed:\t%lu\n",
702 fp->f_st[0].fr_pull[0], fp->f_st[0].fr_pull[1]);
703 PRINTF("OUT Pullups succeeded:\t%lu\tfailed:\t%lu\n",
704 fp->f_st[1].fr_pull[0], fp->f_st[1].fr_pull[1]);
705 PRINTF("Fastroute successes:\t%lu\tfailures:\t%lu\n",
706 fp->f_froute[0], fp->f_froute[1]);
707 PRINTF("TCP cksum fails(in):\t%lu\t(out):\t%lu\n",
708 fp->f_st[0].fr_tcpbad, fp->f_st[1].fr_tcpbad);
710 PRINTF("Packet log flags set: (%#x)\n", frf);
711 if (frf & FF_LOGPASS)
712 PRINTF("\tpackets passed through filter\n");
713 if (frf & FF_LOGBLOCK)
714 PRINTF("\tpackets blocked by filter\n");
715 if (frf & FF_LOGNOMATCH)
716 PRINTF("\tpackets not matched by filter\n");
723 * Print out a list of rules from the kernel, starting at the one passed.
725 static void printlist(fp)
731 for (n = 1; fp; n++) {
732 if (kmemcpy((char *)&fb, (u_long)fp, sizeof(fb)) == -1) {
737 if (opts & OPT_OUTQUE)
738 fp->fr_flags |= FR_OUTQUE;
739 if (opts & (OPT_HITS|OPT_VERBOSE))
741 PRINTF("%qu ", (unsigned long long) fp->fr_hits);
743 PRINTF("%lu ", fp->fr_hits);
745 if (opts & (OPT_ACCNT|OPT_VERBOSE))
747 PRINTF("%qu ", (unsigned long long) fp->fr_bytes);
749 PRINTF("%lu ", fp->fr_bytes);
751 if (opts & OPT_SHOWLINENO)
754 if (opts & OPT_VERBOSE)
757 printlist(fp->fr_grp);
763 * print out all of the asked for rule sets, using the stats struct as
764 * the base from which to get the pointers.
766 static void showlist(fiop)
767 struct friostat *fiop;
769 struct frentry *fp = NULL;
772 set = fiop->f_active;
773 if (opts & OPT_INACTIVE)
775 if (opts & OPT_ACCNT) {
777 if (opts & OPT_OUTQUE) {
778 fp = (struct frentry *)fiop->f_acctout[set];
780 } else if (opts & OPT_INQUE)
781 fp = (struct frentry *)fiop->f_acctin[set];
783 FPRINTF(stderr, "No -i or -o given with -a\n");
788 if ((use_inet6) && (opts & OPT_OUTQUE)) {
790 fp = (struct frentry *)fiop->f_fout6[set];
791 } else if ((use_inet6) && (opts & OPT_INQUE)) {
793 fp = (struct frentry *)fiop->f_fin6[set];
796 if (opts & OPT_OUTQUE) {
798 fp = (struct frentry *)fiop->f_fout[set];
799 } else if (opts & OPT_INQUE) {
801 fp = (struct frentry *)fiop->f_fin[set];
805 if (opts & OPT_VERBOSE)
806 FPRINTF(stderr, "showlist:opts %#x i %d\n", opts, i);
808 if (opts & OPT_VERBOSE)
809 PRINTF("fp %p set %d\n", fp, set);
811 FPRINTF(stderr, "empty list for %s%s\n",
812 (opts & OPT_INACTIVE) ? "inactive " : "", filters[i]);
820 * Display ipfilter stateful filtering information
822 static void showipstates(ipsp)
825 ipstate_t *istab[IPSTATE_SIZE];
828 * If a list of states hasn't been asked for, only print out stats
830 if (!(opts & OPT_SHOWLIST)) {
831 PRINTF("IP states added:\n\t%lu TCP\n\t%lu UDP\n\t%lu ICMP\n",
832 ipsp->iss_tcp, ipsp->iss_udp, ipsp->iss_icmp);
833 PRINTF("\t%lu hits\n\t%lu misses\n", ipsp->iss_hits,
835 PRINTF("\t%lu maximum\n\t%lu no memory\n\t%lu bkts in use\n",
836 ipsp->iss_max, ipsp->iss_nomem, ipsp->iss_inuse);
837 PRINTF("\t%lu active\n\t%lu expired\n\t%lu closed\n",
838 ipsp->iss_active, ipsp->iss_expire, ipsp->iss_fin);
842 if (kmemcpy((char *)istab, (u_long)ipsp->iss_table, sizeof(istab)))
846 * Print out all the state information currently held in the kernel.
848 while (ipsp->iss_list != NULL) {
849 ipsp->iss_list = printstate(ipsp->iss_list, opts);
856 * Displays the list of interfaces of which IPFilter has taken control in
859 void showqiflist(kern)
862 struct nlist qifnlist[2] = {
872 if (nlist(kern, qifnlist) == -1) {
873 fprintf(stderr, "nlist error\n");
877 printf("List of interfaces bound by IPFilter:\n");
878 if (kmemcpy((char *)&qf, (u_long)qifnlist[0].n_value, sizeof(qf)))
881 if (kmemcpy((char *)&qif, (u_long)qf, sizeof(qif)))
883 if (kmemcpy((char *)&ill, (u_long)qif.qf_ill, sizeof(ill)))
885 printf("Name: %-8s Header Length: %2d SAP: %s (%04x) PPA %d",
886 qif.qf_name, qif.qf_hl,
888 (qif.qf_sap == IP6_DL_SAP) ? "IPv6" : "IPv4"
892 , qif.qf_sap, ill.ill_ppa);
893 printf(" %ld %ld", qif.qf_incnt, qif.qf_outcnt);
902 static void topipstates(saddr, daddr, sport, dport, protocol,
903 refreshtime, topclosed)
904 struct in_addr saddr;
905 struct in_addr daddr;
912 char str1[STSTRSIZE], str2[STSTRSIZE], str3[STSTRSIZE], str4[STSTRSIZE];
913 int maxtsentries = 0, reverse = 0, sorting = STSORT_DEFAULT;
914 int i, j, sfd, winx, tsentry, maxx, maxy, redraw = 0;
915 ipstate_t *istab[IPSTATE_SIZE], ips;
916 ips_stat_t ipsst, *ipsstp = &ipsst;
917 statetop_t *tstable = NULL, *tp;
918 struct timeval selecttimeout;
919 char hostnm[HOSTNMLEN];
920 struct protoent *proto;
925 /* open state device */
926 if ((sfd = open(IPL_STATE, O_RDONLY)) == -1) {
931 /* init ncurses stuff */
937 gethostname(hostnm, sizeof(hostnm) - 1);
938 hostnm[sizeof(hostnm) - 1] = '\0';
940 /* repeat until user aborts */
943 /* get state table */
944 bzero((char *)&ipsst, sizeof(&ipsst));
945 if ((ioctl(sfd, SIOCGETFS, &ipsstp) == -1)) {
946 perror("ioctl(SIOCGETFS)");
949 if (kmemcpy((char *)istab, (u_long)ipsstp->iss_table,
953 /* clear the history */
956 /* read the state table and store in tstable */
957 while (ipsstp->iss_list) {
958 if (kmemcpy((char *)&ips, (u_long)ipsstp->iss_list,
961 ipsstp->iss_list = ips.is_next;
963 if (((saddr.s_addr == INADDR_ANY) ||
964 (saddr.s_addr == ips.is_saddr)) &&
965 ((daddr.s_addr == INADDR_ANY) ||
966 (daddr.s_addr == ips.is_daddr)) &&
967 ((protocol < 0) || (protocol == ips.is_p)) &&
968 (((ips.is_p != IPPROTO_TCP) &&
969 (ips.is_p != IPPROTO_UDP)) ||
971 (htons(sport) == ips.is_sport)) &&
973 (htons(dport) == ips.is_dport)))) &&
974 (topclosed || (ips.is_p != IPPROTO_TCP) ||
975 (ips.is_state[0] < TCPS_LAST_ACK) ||
976 (ips.is_state[1] < TCPS_LAST_ACK))) {
978 * if necessary make room for this state
983 (tsentry == maxtsentries)) {
985 maxtsentries += STGROWSIZE;
986 tstable = realloc(tstable, maxtsentries * sizeof(statetop_t));
994 tp = tstable + tsentry;
995 tp->st_src = ips.is_src;
996 tp->st_dst = ips.is_dst;
998 tp->st_state[0] = ips.is_state[0];
999 tp->st_state[1] = ips.is_state[1];
1000 tp->st_pkts = ips.is_pkts;
1001 tp->st_bytes = ips.is_bytes;
1002 tp->st_age = ips.is_age;
1003 if ((ips.is_p == IPPROTO_TCP) ||
1004 (ips.is_p == IPPROTO_UDP)) {
1005 tp->st_sport = ips.is_sport;
1006 tp->st_dport = ips.is_dport;
1013 /* sort the array */
1018 qsort(tstable, tsentry + 1,
1019 sizeof(statetop_t), sort_p);
1022 qsort(tstable, tsentry + 1,
1023 sizeof(statetop_t), sort_pkts);
1026 qsort(tstable, tsentry + 1,
1027 sizeof(statetop_t), sort_bytes);
1030 qsort(tstable, tsentry + 1,
1031 sizeof(statetop_t), sort_ttl);
1034 qsort(tstable, tsentry + 1,
1035 sizeof(statetop_t), sort_srcip);
1038 qsort(tstable, tsentry + 1,
1039 sizeof(statetop_t), sort_dstip);
1047 getmaxyx(stdscr, maxy, maxx);
1051 sprintf(str1, "%s - %s - state top", hostnm, IPL_VERSION);
1052 for (j = 0 ; j < (maxx - 8 - strlen(str1)) / 2; j++)
1057 /* just for fun add a clock */
1058 move(winx, maxx - 8);
1060 strftime(str1, 80, "%T", localtime(&t));
1061 printw("%s\n", str1);
1064 * print the display filters, this is placed in the loop,
1065 * because someday I might add code for changing these
1066 * while the programming is running :-)
1069 sprintf(str1, "%s,%d", inet_ntoa(saddr), sport);
1071 sprintf(str1, "%s", inet_ntoa(saddr));
1074 sprintf(str2, "%s,%d", inet_ntoa(daddr), dport);
1076 sprintf(str2, "%s", inet_ntoa(daddr));
1079 strcpy(str3, "any");
1080 else if ((proto = getprotobynumber(protocol)) != NULL)
1081 sprintf(str3, "%s", proto->p_name);
1083 sprintf(str3, "%d", protocol);
1088 sprintf(str4, "proto");
1091 sprintf(str4, "# pkts");
1094 sprintf(str4, "# bytes");
1097 sprintf(str4, "ttl");
1100 sprintf(str4, "srcip");
1103 sprintf(str4, "dstip");
1106 sprintf(str4, "unknown");
1111 strcat(str4, " (reverse)");
1115 printw("Src = %s Dest = %s Proto = %s Sorted by = %s\n\n",
1116 str1, str2, str3, str4);
1118 /* print column description */
1122 printw("%-21s %-21s %3s %4s %7s %9s %9s\n", "Source IP",
1123 "Destination IP", "ST", "PR", "#pkts", "#bytes", "ttl");
1126 /* print all the entries */
1131 if (tsentry > maxy - 6)
1133 for (i = 0; i <= tsentry; i++) {
1134 /* print src/dest and port */
1135 if ((tp->st_p == IPPROTO_TCP) ||
1136 (tp->st_p == IPPROTO_UDP)) {
1137 sprintf(str1, "%s,%hu",
1138 inet_ntoa(tp->st_src.in4),
1139 ntohs(tp->st_sport));
1140 sprintf(str2, "%s,%hu",
1141 inet_ntoa(tp->st_dst.in4),
1142 ntohs(tp->st_dport));
1144 sprintf(str1, "%s", inet_ntoa(tp->st_src.in4));
1145 sprintf(str2, "%s", inet_ntoa(tp->st_dst.in4));
1149 printw("%-21s %-21s", str1, str2);
1152 sprintf(str1, "%X/%X", tp->st_state[0],
1154 printw(" %3s", str1);
1157 proto = getprotobynumber(tp->st_p);
1159 strncpy(str1, proto->p_name, 4);
1162 sprintf(str1, "%d", tp->st_p);
1164 printw(" %4s", str1);
1165 /* print #pkt/#bytes */
1167 printw(" %7qu %9qu", (unsigned long long) tp->st_pkts,
1168 (unsigned long long) tp->st_bytes);
1170 printw(" %7lu %9lu", tp->st_pkts, tp->st_bytes);
1172 printw(" %9s", ttl_to_string(tp->st_age));
1180 /* screen data structure is filled, now update the screen */
1190 /* wait for key press or a 1 second time out period */
1191 selecttimeout.tv_sec = refreshtime;
1192 selecttimeout.tv_usec = 0;
1195 select(1, &readfd, NULL, NULL, &selecttimeout);
1197 /* if key pressed, read all waiting keys */
1198 if (FD_ISSET(0, &readfd)) {
1203 if (tolower(c) == 'l') {
1205 } else if (tolower(c) == 'q') {
1209 } else if (tolower(c) == 'r') {
1211 } else if (tolower(c) == 's') {
1213 if (sorting > STSORT_MAX)
1229 * Show fragment cache information that's held in the kernel.
1231 static void showfrstates(ifsp)
1234 struct ipfr *ipfrtab[IPFT_SIZE], ifr;
1239 * print out the numeric statistics
1241 PRINTF("IP fragment states:\n\t%lu new\n\t%lu expired\n\t%lu hits\n",
1242 ifsp->ifs_new, ifsp->ifs_expire, ifsp->ifs_hits);
1243 PRINTF("\t%lu no memory\n\t%lu already exist\n",
1244 ifsp->ifs_nomem, ifsp->ifs_exists);
1245 PRINTF("\t%lu inuse\n", ifsp->ifs_inuse);
1246 if (kmemcpy((char *)ipfrtab, (u_long)ifsp->ifs_table, sizeof(ipfrtab)))
1250 * Print out the contents (if any) of the fragment cache table.
1252 for (i = 0; i < IPFT_SIZE; i++)
1253 while (ipfrtab[i]) {
1254 if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i],
1257 PRINTF("%s -> ", hostname(4, &ifr.ipfr_src));
1258 if (kmemcpy((char *)&fr, (u_long)ifr.ipfr_rule,
1261 PRINTF("%s %d %d %d %#02x = %#x\n",
1262 hostname(4, &ifr.ipfr_dst), ifr.ipfr_id,
1263 ifr.ipfr_ttl, ifr.ipfr_p, ifr.ipfr_tos,
1265 ipfrtab[i] = ifr.ipfr_next;
1267 if (kmemcpy((char *)ipfrtab, (u_long)ifsp->ifs_nattab,sizeof(ipfrtab)))
1269 for (i = 0; i < IPFT_SIZE; i++)
1270 while (ipfrtab[i]) {
1271 if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i],
1274 PRINTF("NAT: %s -> ", hostname(4, &ifr.ipfr_src));
1275 if (kmemcpy((char *)&fr, (u_long)ifr.ipfr_rule,
1278 PRINTF("%s %d %d %d %#02x = %#x\n",
1279 hostname(4, &ifr.ipfr_dst), ifr.ipfr_id,
1280 ifr.ipfr_ttl, ifr.ipfr_p, ifr.ipfr_tos,
1282 ipfrtab[i] = ifr.ipfr_next;
1288 * Show stats on how auth within IPFilter has been used
1290 static void showauthstates(asp)
1293 frauthent_t *frap, fra;
1296 printf("Authorisation hits: %qu\tmisses %qu\n",
1297 (unsigned long long) asp->fas_hits,
1298 (unsigned long long) asp->fas_miss);
1300 printf("Authorisation hits: %ld\tmisses %ld\n", asp->fas_hits,
1303 printf("nospace %ld\nadded %ld\nsendfail %ld\nsendok %ld\n",
1304 asp->fas_nospace, asp->fas_added, asp->fas_sendfail,
1306 printf("queok %ld\nquefail %ld\nexpire %ld\n",
1307 asp->fas_queok, asp->fas_quefail, asp->fas_expire);
1309 frap = asp->fas_faelist;
1311 if (kmemcpy((char *)&fra, (u_long)frap, sizeof(fra)) == -1)
1314 printf("age %ld\t", fra.fae_age);
1315 printfr(&fra.fae_fr);
1316 frap = fra.fae_next;
1322 * Display groups used for each of filter rules, accounting rules and
1323 * authentication, separately.
1325 static void showgroups(fiop)
1326 struct friostat *fiop;
1328 static char *gnames[3] = { "Filter", "Accounting", "Authentication" };
1332 on = fiop->f_active;
1335 for (i = 0; i < 3; i++) {
1336 printf("%s groups (active):\n", gnames[i]);
1337 for (fp = fiop->f_groups[i][on]; fp; fp = grp.fg_next)
1338 if (kmemcpy((char *)&grp, (u_long)fp, sizeof(grp)))
1341 printf("%hu\n", grp.fg_num);
1342 printf("%s groups (inactive):\n", gnames[i]);
1343 for (fp = fiop->f_groups[i][off]; fp; fp = grp.fg_next)
1344 if (kmemcpy((char *)&grp, (u_long)fp, sizeof(grp)))
1347 printf("%hu\n", grp.fg_num);
1351 static void parse_ipportstr(argument, ip, port)
1352 const char *argument;
1359 /* make working copy of argument, Theoretically you must be able
1360 * to write to optarg, but that seems very ugly to me....
1362 if ((s = malloc(strlen(argument) + 1)) == NULL)
1364 strcpy(s, argument);
1367 if ((comma = strchr(s, ',')) != NULL) {
1368 if (!strcasecmp(s, "any")) {
1370 } else if (!sscanf(comma + 1, "%d", port) ||
1371 (*port < 0) || (*port > 65535)) {
1372 fprintf(stderr, "Invalid port specfication in %s\n",
1380 /* get ip address */
1381 if (!strcasecmp(s, "any")) {
1382 ip->s_addr = INADDR_ANY;
1383 } else if (!inet_aton(s, ip)) {
1384 fprintf(stderr, "Invalid IP address: %s\n", s);
1388 /* free allocated memory */
1394 static char ttlbuf[STSTRSIZE];
1396 static char *ttl_to_string(ttl)
1400 int hours, minutes, seconds;
1402 /* ttl is in half seconds */
1411 sprintf(ttlbuf, "%2d:%02d:%02d", hours, minutes, seconds);
1413 sprintf(ttlbuf, "%2d:%02d", minutes, seconds);
1418 static int sort_pkts(a, b)
1423 register const statetop_t *ap = a;
1424 register const statetop_t *bp = b;
1426 if (ap->st_pkts == bp->st_pkts)
1428 else if (ap->st_pkts < bp->st_pkts)
1434 static int sort_bytes(a, b)
1438 register const statetop_t *ap = a;
1439 register const statetop_t *bp = b;
1441 if (ap->st_bytes == bp->st_bytes)
1443 else if (ap->st_bytes < bp->st_bytes)
1449 static int sort_p(a, b)
1453 register const statetop_t *ap = a;
1454 register const statetop_t *bp = b;
1456 if (ap->st_p == bp->st_p)
1458 else if (ap->st_p < bp->st_p)
1464 static int sort_ttl(a, b)
1468 register const statetop_t *ap = a;
1469 register const statetop_t *bp = b;
1471 if (ap->st_age == bp->st_age)
1473 else if (ap->st_age < bp->st_age)
1478 static int sort_srcip(a, b)
1482 register const statetop_t *ap = a;
1483 register const statetop_t *bp = b;
1485 if (ntohl(ap->st_src.in4.s_addr) == ntohl(bp->st_src.in4.s_addr))
1487 else if (ntohl(ap->st_src.in4.s_addr) > ntohl(bp->st_src.in4.s_addr))
1492 static int sort_dstip(a, b)
1496 register const statetop_t *ap = a;
1497 register const statetop_t *bp = b;
1499 if (ntohl(ap->st_dst.in4.s_addr) == ntohl(bp->st_dst.in4.s_addr))
1501 else if (ntohl(ap->st_dst.in4.s_addr) > ntohl(bp->st_dst.in4.s_addr))