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.40 2002/12/06 11:40:20 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)" };
123 #define STGROWSIZE 16
127 #define STSORT_PKTS 1
128 #define STSORT_BYTES 2
130 #define STSORT_SRCIP 4
131 #define STSORT_DSTIP 5
132 #define STSORT_MAX STSORT_DSTIP
133 #define STSORT_DEFAULT STSORT_BYTES
136 typedef struct statetop {
149 extern int main __P((int, char *[]));
150 static void showstats __P((friostat_t *, u_32_t));
151 static void showfrstates __P((ipfrstat_t *));
152 static void showlist __P((friostat_t *));
153 static void showipstates __P((ips_stat_t *));
154 static void showauthstates __P((fr_authstat_t *));
155 static void showgroups __P((friostat_t *));
156 static void Usage __P((char *));
157 static void printlist __P((frentry_t *));
158 static void parse_ipportstr __P((const char *, struct in_addr *, int *));
159 static int ipfstate_live __P((char *, friostat_t **, ips_stat_t **,
160 ipfrstat_t **, fr_authstat_t **, u_32_t *));
161 static void ipfstate_dead __P((char *, friostat_t **, ips_stat_t **,
162 ipfrstat_t **, fr_authstat_t **, u_32_t *));
164 static void topipstates __P((struct in_addr, struct in_addr, int, int, int, int, int));
165 static char *ttl_to_string __P((long));
166 static int sort_p __P((const void *, const void *));
167 static int sort_pkts __P((const void *, const void *));
168 static int sort_bytes __P((const void *, const void *));
169 static int sort_ttl __P((const void *, const void *));
170 static int sort_srcip __P((const void *, const void *));
171 static int sort_dstip __P((const void *, const void *));
174 void showqiflist __P((char *));
178 static void Usage(name)
182 fprintf(stderr, "Usage: %s [-6aAfhIinosv] [-d <device>]\n", name);
184 fprintf(stderr, "Usage: %s [-aAfhIinosv] [-d <device>]\n", name);
186 fprintf(stderr, "\t\t[-M corefile] [-N symbol-list]\n");
187 fprintf(stderr, " %s -t [-S source address] [-D destination address] [-P protocol] [-T refreshtime] [-C] [-d <device>]\n", name);
196 fr_authstat_t frauthst;
197 fr_authstat_t *frauthstp = &frauthst;
199 friostat_t *fiop = &fio;
201 ips_stat_t *ipsstp = &ipsst;
203 ipfrstat_t *ifrstp = &ifrst;
204 char *device = IPL_NAME, *memf = NULL;
207 struct protoent *proto;
209 int protocol = -1; /* -1 = wild card for any protocol */
210 int refreshtime = 1; /* default update time */
211 int sport = -1; /* -1 = wild card for any source port */
212 int dport = -1; /* -1 = wild card for any dest port */
213 int topclosed = 0; /* do not show closed tcp sessions */
214 struct in_addr saddr, daddr;
217 saddr.s_addr = INADDR_ANY; /* default any source addr */
218 daddr.s_addr = INADDR_ANY; /* default any dest addr */
221 * Parse these two arguments now lest there be any buffer overflows
222 * in the parsing of the rest.
225 while ((c = getopt(argc, argv, "6aACfghIilnoqstvd:D:M:N:P:S:T:")) != -1)
239 if (kern != NULL || memf != NULL)
241 (void)setuid(getuid());
242 (void)setgid(getgid());
245 if (openkmem(kern, memf) == -1)
248 (void)setuid(getuid());
249 (void)setgid(getgid());
251 while ((c = getopt(argc, argv, "6aACfghIilnoqstvd:D:M:N:P:S:T:")) != -1)
261 opts |= OPT_ACCNT|OPT_SHOWLIST;
264 device = IPAUTH_NAME;
265 opts |= OPT_AUTHSTATS;
274 parse_ipportstr(optarg, &daddr, &dport);
277 opts |= OPT_FRSTATES;
286 opts |= OPT_INQUE|OPT_SHOWLIST;
289 opts |= OPT_INACTIVE;
292 opts |= OPT_SHOWLIST;
299 opts |= OPT_SHOWLINENO;
302 opts |= OPT_OUTQUE|OPT_SHOWLIST;
305 if ((proto = getprotobyname(optarg)) != NULL) {
306 protocol = proto->p_proto;
307 } else if (!sscanf(optarg, "%ud", &protocol) ||
309 fprintf(stderr, "%s : Invalid protocol: %s\n",
320 fprintf(stderr, "-q only availble on Solaris\n");
325 opts |= OPT_IPSTATES;
328 parse_ipportstr(optarg, &saddr, &sport);
332 opts |= OPT_STATETOP;
336 "%s : state top facility not compiled in\n",
341 if (!sscanf(optarg, "%d", &refreshtime) ||
342 (refreshtime <= 0)) {
344 "%s : Invalid refreshtime < 1 : %s\n",
358 if (live_kernel == 1) {
359 bzero((char *)&fio, sizeof(fio));
360 bzero((char *)&ipsst, sizeof(ipsst));
361 bzero((char *)&ifrst, sizeof(ifrst));
363 ipfstate_live(device, &fiop, &ipsstp, &ifrstp,
366 ipfstate_dead(kern, &fiop, &ipsstp, &ifrstp, &frauthstp, &frf);
368 if (opts & OPT_IPSTATES) {
369 showipstates(ipsstp);
370 } else if (opts & OPT_SHOWLIST) {
372 if ((opts & OPT_OUTQUE) && (opts & OPT_INQUE)){
377 if (opts & OPT_FRSTATES)
378 showfrstates(ifrstp);
380 else if (opts & OPT_STATETOP)
381 topipstates(saddr, daddr, sport, dport,
382 protocol, refreshtime, topclosed);
384 else if (opts & OPT_AUTHSTATS)
385 showauthstates(frauthstp);
386 else if (opts & OPT_GROUPS)
389 showstats(fiop, frf);
396 * Fill in the stats structures from the live kernel, using a combination
397 * of ioctl's and copying directly from kernel memory.
399 int ipfstate_live(device, fiopp, ipsstpp, ifrstpp, frauthstpp, frfp)
402 ips_stat_t **ipsstpp;
403 ipfrstat_t **ifrstpp;
404 fr_authstat_t **frauthstpp;
409 if ((fd = open(device, O_RDONLY)) < 0) {
414 if (!(opts & OPT_AUTHSTATS) && ioctl(fd, SIOCGETFS, fiopp) == -1) {
415 perror("ioctl(ipf:SIOCGETFS)");
419 if ((opts & OPT_IPSTATES)) {
420 int sfd = open(IPL_STATE, O_RDONLY);
426 if ((ioctl(sfd, SIOCGETFS, ipsstpp) == -1)) {
427 perror("ioctl(state:SIOCGETFS)");
432 if ((opts & OPT_FRSTATES) && (ioctl(fd, SIOCGFRST, ifrstpp) == -1)) {
433 perror("ioctl(SIOCGFRST)");
437 if (opts & OPT_VERBOSE)
438 PRINTF("opts %#x name %s\n", opts, device);
440 if ((opts & OPT_AUTHSTATS) &&
441 (ioctl(fd, SIOCATHST, frauthstpp) == -1)) {
442 perror("ioctl(SIOCATHST)");
446 if (ioctl(fd, SIOCGETFF, frfp) == -1)
447 perror("ioctl(SIOCGETFF)");
454 * Build up the stats structures from data held in the "core" memory.
455 * This is mainly useful when looking at data in crash dumps and ioctl's
456 * just won't work any more.
458 void ipfstate_dead(kernel, fiopp, ipsstpp, ifrstpp, frauthstpp, frfp)
461 ips_stat_t **ipsstpp;
462 ipfrstat_t **ifrstpp;
463 fr_authstat_t **frauthstpp;
466 static fr_authstat_t frauthst, *frauthstp;
467 static ips_stat_t ipsst, *ipsstp;
468 static ipfrstat_t ifrst, *ifrstp;
469 static friostat_t fio, *fiop;
472 struct nlist deadlist[42] = {
473 { "fr_authstats" }, /* 0 */
478 { "fr_authend" }, /* 5 */
483 { "fr_defaultauthage" }, /* 10 */
488 { "ips_num" }, /* 15 */
493 { "fr_statesize" }, /* 20 */
494 { "fr_state_doflush" },
498 { "ipfr_stats" }, /* 25 */
503 { "fr_nat_lock" }, /* 30 */
508 { "ipl_frouteok" }, /* 35 */
513 { "fr_flags" }, /* 40 */
518 frauthstp = &frauthst;
527 *frauthstpp = frauthstp;
529 bzero((char *)fiop, sizeof(*fiop));
530 bzero((char *)ipsstp, sizeof(*ipsstp));
531 bzero((char *)ifrstp, sizeof(*ifrstp));
532 bzero((char *)frauthstp, sizeof(*frauthstp));
534 if (nlist(kernel, deadlist) == -1) {
535 fprintf(stderr, "nlist error\n");
540 * This is for SIOCGETFF.
542 kmemcpy((char *)frfp, (u_long)deadlist[40].n_value, sizeof(*frfp));
545 * f_locks is a combination of the lock variable from each part of
546 * ipfilter (state, auth, nat, fragments).
548 kmemcpy((char *)fiop, (u_long)deadlist[13].n_value, sizeof(*fiop));
549 kmemcpy((char *)&fiop->f_locks[0], (u_long)deadlist[22].n_value,
550 sizeof(fiop->f_locks[0]));
551 kmemcpy((char *)&fiop->f_locks[0], (u_long)deadlist[30].n_value,
552 sizeof(fiop->f_locks[1]));
553 kmemcpy((char *)&fiop->f_locks[2], (u_long)deadlist[28].n_value,
554 sizeof(fiop->f_locks[2]));
555 kmemcpy((char *)&fiop->f_locks[3], (u_long)deadlist[12].n_value,
556 sizeof(fiop->f_locks[3]));
559 * Get pointers to each list of rules (active, inactive, in, out)
561 kmemcpy((char *)&rules, (u_long)deadlist[31].n_value, sizeof(rules));
562 fiop->f_fin[0] = rules[0][0];
563 fiop->f_fin[1] = rules[0][1];
564 fiop->f_fout[0] = rules[1][0];
565 fiop->f_fout[1] = rules[1][1];
568 * Same for IPv6, except make them null if support for it is not
572 kmemcpy((char *)&rules, (u_long)deadlist[32].n_value, sizeof(rules));
573 fiop->f_fin6[0] = rules[0][0];
574 fiop->f_fin6[1] = rules[0][1];
575 fiop->f_fout6[0] = rules[1][0];
576 fiop->f_fout6[1] = rules[1][1];
578 fiop->f_fin6[0] = NULL;
579 fiop->f_fin6[1] = NULL;
580 fiop->f_fout6[0] = NULL;
581 fiop->f_fout6[1] = NULL;
585 * Now get accounting rules pointers.
587 kmemcpy((char *)&rules, (u_long)deadlist[33].n_value, sizeof(rules));
588 fiop->f_acctin[0] = rules[0][0];
589 fiop->f_acctin[1] = rules[0][1];
590 fiop->f_acctout[0] = rules[1][0];
591 fiop->f_acctout[1] = rules[1][1];
594 kmemcpy((char *)&rules, (u_long)deadlist[34].n_value, sizeof(rules));
595 fiop->f_acctin6[0] = rules[0][0];
596 fiop->f_acctin6[1] = rules[0][1];
597 fiop->f_acctout6[0] = rules[1][0];
598 fiop->f_acctout6[1] = rules[1][1];
600 fiop->f_acctin6[0] = NULL;
601 fiop->f_acctin6[1] = NULL;
602 fiop->f_acctout6[0] = NULL;
603 fiop->f_acctout6[1] = NULL;
607 * A collection of "global" variables used inside the kernel which
608 * are all collected in friostat_t via ioctl.
610 kmemcpy((char *)&fiop->f_froute, (u_long)deadlist[35].n_value,
611 sizeof(fiop->f_froute));
612 kmemcpy((char *)&fiop->f_running, (u_long)deadlist[36].n_value,
613 sizeof(fiop->f_running));
614 kmemcpy((char *)&fiop->f_groups, (u_long)deadlist[37].n_value,
615 sizeof(fiop->f_groups));
616 kmemcpy((char *)&fiop->f_active, (u_long)deadlist[38].n_value,
617 sizeof(fiop->f_active));
618 kmemcpy((char *)&fiop->f_defpass, (u_long)deadlist[39].n_value,
619 sizeof(fiop->f_defpass));
622 * Build up the state information stats structure.
624 kmemcpy((char *)ipsstp, (u_long)deadlist[14].n_value, sizeof(*ipsstp));
625 kmemcpy((char *)&ipsstp->iss_active, (u_long)deadlist[15].n_value,
626 sizeof(ipsstp->iss_active));
627 ipsstp->iss_table = (void *)deadlist[18].n_value;
628 ipsstp->iss_list = (void *)deadlist[17].n_value;
631 * Build up the authentiation information stats structure.
633 kmemcpy((char *)frauthstp, (u_long)deadlist[0].n_value,
635 frauthstp->fas_faelist = (void *)deadlist[1].n_value;
638 * Build up the fragment information stats structure.
640 kmemcpy((char *)ifrstp, (u_long)deadlist[25].n_value,
642 ifrstp->ifs_table = (void *)deadlist[23].n_value;
643 ifrstp->ifs_nattab = (void *)deadlist[24].n_value;
644 kmemcpy((char *)&ifrstp->ifs_inuse, (u_long)deadlist[26].n_value,
645 sizeof(ifrstp->ifs_inuse));
650 * Display the kernel stats for packets blocked and passed and other
651 * associated running totals which are kept.
653 static void showstats(fp, frf)
659 PRINTF("dropped packets:\tin %lu\tout %lu\n",
660 fp->f_st[0].fr_drop, fp->f_st[1].fr_drop);
661 PRINTF("non-data packets:\tin %lu\tout %lu\n",
662 fp->f_st[0].fr_notdata, fp->f_st[1].fr_notdata);
663 PRINTF("no-data packets:\tin %lu\tout %lu\n",
664 fp->f_st[0].fr_nodata, fp->f_st[1].fr_nodata);
665 PRINTF("non-ip packets:\t\tin %lu\tout %lu\n",
666 fp->f_st[0].fr_notip, fp->f_st[1].fr_notip);
667 PRINTF(" bad packets:\t\tin %lu\tout %lu\n",
668 fp->f_st[0].fr_bad, fp->f_st[1].fr_bad);
669 PRINTF("copied messages:\tin %lu\tout %lu\n",
670 fp->f_st[0].fr_copy, fp->f_st[1].fr_copy);
673 PRINTF(" IPv6 packets:\t\tin %lu out %lu\n",
674 fp->f_st[0].fr_ipv6[0], fp->f_st[0].fr_ipv6[1]);
676 PRINTF(" input packets:\t\tblocked %lu passed %lu nomatch %lu",
677 fp->f_st[0].fr_block, fp->f_st[0].fr_pass,
679 PRINTF(" counted %lu short %lu\n",
680 fp->f_st[0].fr_acct, fp->f_st[0].fr_short);
681 PRINTF("output packets:\t\tblocked %lu passed %lu nomatch %lu",
682 fp->f_st[1].fr_block, fp->f_st[1].fr_pass,
684 PRINTF(" counted %lu short %lu\n",
685 fp->f_st[1].fr_acct, fp->f_st[1].fr_short);
686 PRINTF(" input packets logged:\tblocked %lu passed %lu\n",
687 fp->f_st[0].fr_bpkl, fp->f_st[0].fr_ppkl);
688 PRINTF("output packets logged:\tblocked %lu passed %lu\n",
689 fp->f_st[1].fr_bpkl, fp->f_st[1].fr_ppkl);
690 PRINTF(" packets logged:\tinput %lu output %lu\n",
691 fp->f_st[0].fr_pkl, fp->f_st[1].fr_pkl);
692 PRINTF(" log failures:\t\tinput %lu output %lu\n",
693 fp->f_st[0].fr_skip, fp->f_st[1].fr_skip);
694 PRINTF("fragment state(in):\tkept %lu\tlost %lu\n",
695 fp->f_st[0].fr_nfr, fp->f_st[0].fr_bnfr);
696 PRINTF("fragment state(out):\tkept %lu\tlost %lu\n",
697 fp->f_st[1].fr_nfr, fp->f_st[1].fr_bnfr);
698 PRINTF("packet state(in):\tkept %lu\tlost %lu\n",
699 fp->f_st[0].fr_ads, fp->f_st[0].fr_bads);
700 PRINTF("packet state(out):\tkept %lu\tlost %lu\n",
701 fp->f_st[1].fr_ads, fp->f_st[1].fr_bads);
702 PRINTF("ICMP replies:\t%lu\tTCP RSTs sent:\t%lu\n",
703 fp->f_st[0].fr_ret, fp->f_st[1].fr_ret);
704 PRINTF("Invalid source(in):\t%lu\n", fp->f_st[0].fr_badsrc);
705 PRINTF("Result cache hits(in):\t%lu\t(out):\t%lu\n",
706 fp->f_st[0].fr_chit, fp->f_st[1].fr_chit);
707 PRINTF("IN Pullups succeeded:\t%lu\tfailed:\t%lu\n",
708 fp->f_st[0].fr_pull[0], fp->f_st[0].fr_pull[1]);
709 PRINTF("OUT Pullups succeeded:\t%lu\tfailed:\t%lu\n",
710 fp->f_st[1].fr_pull[0], fp->f_st[1].fr_pull[1]);
711 PRINTF("Fastroute successes:\t%lu\tfailures:\t%lu\n",
712 fp->f_froute[0], fp->f_froute[1]);
713 PRINTF("TCP cksum fails(in):\t%lu\t(out):\t%lu\n",
714 fp->f_st[0].fr_tcpbad, fp->f_st[1].fr_tcpbad);
716 PRINTF("Packet log flags set: (%#x)\n", frf);
717 if (frf & FF_LOGPASS)
718 PRINTF("\tpackets passed through filter\n");
719 if (frf & FF_LOGBLOCK)
720 PRINTF("\tpackets blocked by filter\n");
721 if (frf & FF_LOGNOMATCH)
722 PRINTF("\tpackets not matched by filter\n");
729 * Print out a list of rules from the kernel, starting at the one passed.
731 static void printlist(fp)
737 for (n = 1; fp; n++) {
738 if (kmemcpy((char *)&fb, (u_long)fp, sizeof(fb)) == -1) {
743 if (opts & OPT_OUTQUE)
744 fp->fr_flags |= FR_OUTQUE;
745 if (opts & (OPT_HITS|OPT_VERBOSE))
747 PRINTF("%qu ", (unsigned long long) fp->fr_hits);
749 PRINTF("%lu ", fp->fr_hits);
751 if (opts & (OPT_ACCNT|OPT_VERBOSE))
753 PRINTF("%qu ", (unsigned long long) fp->fr_bytes);
755 PRINTF("%lu ", fp->fr_bytes);
757 if (opts & OPT_SHOWLINENO)
760 if (opts & OPT_VERBOSE)
763 printlist(fp->fr_grp);
769 * print out all of the asked for rule sets, using the stats struct as
770 * the base from which to get the pointers.
772 static void showlist(fiop)
773 struct friostat *fiop;
775 struct frentry *fp = NULL;
778 set = fiop->f_active;
779 if (opts & OPT_INACTIVE)
781 if (opts & OPT_ACCNT) {
783 if ((use_inet6) && (opts & OPT_OUTQUE)) {
785 fp = (struct frentry *)fiop->f_acctout6[set];
786 } else if ((use_inet6) && (opts & OPT_INQUE)) {
788 fp = (struct frentry *)fiop->f_acctin6[set];
791 if (opts & OPT_OUTQUE) {
793 fp = (struct frentry *)fiop->f_acctout[set];
794 } else if (opts & OPT_INQUE) {
796 fp = (struct frentry *)fiop->f_acctin[set];
798 FPRINTF(stderr, "No -i or -o given with -a\n");
803 if ((use_inet6) && (opts & OPT_OUTQUE)) {
805 fp = (struct frentry *)fiop->f_fout6[set];
806 } else if ((use_inet6) && (opts & OPT_INQUE)) {
808 fp = (struct frentry *)fiop->f_fin6[set];
811 if (opts & OPT_OUTQUE) {
813 fp = (struct frentry *)fiop->f_fout[set];
814 } else if (opts & OPT_INQUE) {
816 fp = (struct frentry *)fiop->f_fin[set];
820 if (opts & OPT_VERBOSE)
821 FPRINTF(stderr, "showlist:opts %#x i %d\n", opts, i);
823 if (opts & OPT_VERBOSE)
824 PRINTF("fp %p set %d\n", fp, set);
826 FPRINTF(stderr, "empty list for %s%s\n",
827 (opts & OPT_INACTIVE) ? "inactive " : "", filters[i]);
835 * Display ipfilter stateful filtering information
837 static void showipstates(ipsp)
840 ipstate_t *istab[IPSTATE_SIZE];
843 * If a list of states hasn't been asked for, only print out stats
845 if (!(opts & OPT_SHOWLIST)) {
846 PRINTF("IP states added:\n\t%lu TCP\n\t%lu UDP\n\t%lu ICMP\n",
847 ipsp->iss_tcp, ipsp->iss_udp, ipsp->iss_icmp);
848 PRINTF("\t%lu hits\n\t%lu misses\n", ipsp->iss_hits,
850 PRINTF("\t%lu maximum\n\t%lu no memory\n\t%lu bkts in use\n",
851 ipsp->iss_max, ipsp->iss_nomem, ipsp->iss_inuse);
852 PRINTF("\t%lu active\n\t%lu expired\n\t%lu closed\n",
853 ipsp->iss_active, ipsp->iss_expire, ipsp->iss_fin);
857 if (kmemcpy((char *)istab, (u_long)ipsp->iss_table, sizeof(istab)))
861 * Print out all the state information currently held in the kernel.
863 while (ipsp->iss_list != NULL) {
864 ipsp->iss_list = printstate(ipsp->iss_list, opts);
871 * Displays the list of interfaces of which IPFilter has taken control in
874 void showqiflist(kern)
877 struct nlist qifnlist[2] = {
887 if (nlist(kern, qifnlist) == -1) {
888 fprintf(stderr, "nlist error\n");
892 printf("List of interfaces bound by IPFilter:\n");
893 if (kmemcpy((char *)&qf, (u_long)qifnlist[0].n_value, sizeof(qf)))
896 if (kmemcpy((char *)&qif, (u_long)qf, sizeof(qif)))
898 if (kmemcpy((char *)&ill, (u_long)qif.qf_ill, sizeof(ill)))
900 printf("Name: %-8s Header Length: %2d SAP: %s (%04x) PPA %d",
901 qif.qf_name, qif.qf_hl,
903 (qif.qf_sap == IP6_DL_SAP) ? "IPv6" : "IPv4"
907 , qif.qf_sap, ill.ill_ppa);
908 printf(" %ld %ld", qif.qf_incnt, qif.qf_outcnt);
917 static void topipstates(saddr, daddr, sport, dport, protocol,
918 refreshtime, topclosed)
919 struct in_addr saddr;
920 struct in_addr daddr;
927 char str1[STSTRSIZE], str2[STSTRSIZE], str3[STSTRSIZE], str4[STSTRSIZE];
928 int maxtsentries = 0, reverse = 0, sorting = STSORT_DEFAULT;
929 int i, j, sfd, winx, tsentry, maxx, maxy, redraw = 0;
930 ipstate_t *istab[IPSTATE_SIZE], ips;
931 ips_stat_t ipsst, *ipsstp = &ipsst;
932 statetop_t *tstable = NULL, *tp;
933 char hostnm[HOSTNMLEN];
934 struct protoent *proto;
938 struct pollfd set[1];
940 struct timeval selecttimeout;
944 /* open state device */
945 if ((sfd = open(IPL_STATE, O_RDONLY)) == -1) {
950 /* init ncurses stuff */
956 gethostname(hostnm, sizeof(hostnm) - 1);
957 hostnm[sizeof(hostnm) - 1] = '\0';
959 /* repeat until user aborts */
962 /* get state table */
963 bzero((char *)&ipsst, sizeof(&ipsst));
964 if ((ioctl(sfd, SIOCGETFS, &ipsstp) == -1)) {
965 perror("ioctl(SIOCGETFS)");
968 if (kmemcpy((char *)istab, (u_long)ipsstp->iss_table,
972 /* clear the history */
975 /* read the state table and store in tstable */
976 while (ipsstp->iss_list) {
977 if (kmemcpy((char *)&ips, (u_long)ipsstp->iss_list,
980 ipsstp->iss_list = ips.is_next;
982 if (((saddr.s_addr == INADDR_ANY) ||
983 (saddr.s_addr == ips.is_saddr)) &&
984 ((daddr.s_addr == INADDR_ANY) ||
985 (daddr.s_addr == ips.is_daddr)) &&
986 ((protocol < 0) || (protocol == ips.is_p)) &&
987 (((ips.is_p != IPPROTO_TCP) &&
988 (ips.is_p != IPPROTO_UDP)) ||
990 (htons(sport) == ips.is_sport)) &&
992 (htons(dport) == ips.is_dport)))) &&
993 (topclosed || (ips.is_p != IPPROTO_TCP) ||
994 (ips.is_state[0] < TCPS_LAST_ACK) ||
995 (ips.is_state[1] < TCPS_LAST_ACK))) {
997 * if necessary make room for this state
1001 if (!maxtsentries ||
1002 (tsentry == maxtsentries)) {
1004 maxtsentries += STGROWSIZE;
1005 tstable = realloc(tstable, maxtsentries * sizeof(statetop_t));
1012 /* fill structure */
1013 tp = tstable + tsentry;
1014 tp->st_src = ips.is_src;
1015 tp->st_dst = ips.is_dst;
1016 tp->st_p = ips.is_p;
1017 tp->st_state[0] = ips.is_state[0];
1018 tp->st_state[1] = ips.is_state[1];
1019 tp->st_pkts = ips.is_pkts;
1020 tp->st_bytes = ips.is_bytes;
1021 tp->st_age = ips.is_age;
1022 if ((ips.is_p == IPPROTO_TCP) ||
1023 (ips.is_p == IPPROTO_UDP)) {
1024 tp->st_sport = ips.is_sport;
1025 tp->st_dport = ips.is_dport;
1032 /* sort the array */
1037 qsort(tstable, tsentry + 1,
1038 sizeof(statetop_t), sort_p);
1041 qsort(tstable, tsentry + 1,
1042 sizeof(statetop_t), sort_pkts);
1045 qsort(tstable, tsentry + 1,
1046 sizeof(statetop_t), sort_bytes);
1049 qsort(tstable, tsentry + 1,
1050 sizeof(statetop_t), sort_ttl);
1053 qsort(tstable, tsentry + 1,
1054 sizeof(statetop_t), sort_srcip);
1057 qsort(tstable, tsentry + 1,
1058 sizeof(statetop_t), sort_dstip);
1066 getmaxyx(stdscr, maxy, maxx);
1070 sprintf(str1, "%s - %s - state top", hostnm, IPL_VERSION);
1071 for (j = 0 ; j < (maxx - 8 - strlen(str1)) / 2; j++)
1076 /* just for fun add a clock */
1077 move(winx, maxx - 8);
1079 strftime(str1, 80, "%T", localtime(&t));
1080 printw("%s\n", str1);
1083 * print the display filters, this is placed in the loop,
1084 * because someday I might add code for changing these
1085 * while the programming is running :-)
1088 sprintf(str1, "%s,%d", inet_ntoa(saddr), sport);
1090 sprintf(str1, "%s", inet_ntoa(saddr));
1093 sprintf(str2, "%s,%d", inet_ntoa(daddr), dport);
1095 sprintf(str2, "%s", inet_ntoa(daddr));
1098 strcpy(str3, "any");
1099 else if ((proto = getprotobynumber(protocol)) != NULL)
1100 sprintf(str3, "%s", proto->p_name);
1102 sprintf(str3, "%d", protocol);
1107 sprintf(str4, "proto");
1110 sprintf(str4, "# pkts");
1113 sprintf(str4, "# bytes");
1116 sprintf(str4, "ttl");
1119 sprintf(str4, "srcip");
1122 sprintf(str4, "dstip");
1125 sprintf(str4, "unknown");
1130 strcat(str4, " (reverse)");
1134 printw("Src = %s Dest = %s Proto = %s Sorted by = %s\n\n",
1135 str1, str2, str3, str4);
1137 /* print column description */
1141 printw("%-21s %-21s %3s %4s %7s %9s %9s\n", "Source IP",
1142 "Destination IP", "ST", "PR", "#pkts", "#bytes", "ttl");
1145 /* print all the entries */
1150 if (tsentry > maxy - 6)
1152 for (i = 0; i <= tsentry; i++) {
1153 /* print src/dest and port */
1154 if ((tp->st_p == IPPROTO_TCP) ||
1155 (tp->st_p == IPPROTO_UDP)) {
1156 sprintf(str1, "%s,%hu",
1157 inet_ntoa(tp->st_src.in4),
1158 ntohs(tp->st_sport));
1159 sprintf(str2, "%s,%hu",
1160 inet_ntoa(tp->st_dst.in4),
1161 ntohs(tp->st_dport));
1163 sprintf(str1, "%s", inet_ntoa(tp->st_src.in4));
1164 sprintf(str2, "%s", inet_ntoa(tp->st_dst.in4));
1168 printw("%-21s %-21s", str1, str2);
1171 sprintf(str1, "%X/%X", tp->st_state[0],
1173 printw(" %3s", str1);
1176 proto = getprotobynumber(tp->st_p);
1178 strncpy(str1, proto->p_name, 4);
1181 sprintf(str1, "%d", tp->st_p);
1183 printw(" %4s", str1);
1184 /* print #pkt/#bytes */
1186 printw(" %7qu %9qu", (unsigned long long) tp->st_pkts,
1187 (unsigned long long) tp->st_bytes);
1189 printw(" %7lu %9lu", tp->st_pkts, tp->st_bytes);
1191 printw(" %9s", ttl_to_string(tp->st_age));
1199 /* screen data structure is filled, now update the screen */
1209 /* wait for key press or a 1 second time out period */
1212 set[0].events = POLLIN;
1213 poll(set, 1, refreshtime * 1000);
1215 /* if key pressed, read all waiting keys */
1216 if (set[0].revents & POLLIN)
1218 selecttimeout.tv_sec = refreshtime;
1219 selecttimeout.tv_usec = 0;
1222 select(1, &readfd, NULL, NULL, &selecttimeout);
1224 /* if key pressed, read all waiting keys */
1225 if (FD_ISSET(0, &readfd))
1233 if (isalpha(c) && isupper(c))
1237 } else if (c == 'q') {
1238 break; /* exits while() loop */
1239 } else if (c == 'r') {
1241 } else if (c == 's') {
1243 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.
1282 for (i = 0; i < IPFT_SIZE; i++)
1283 while (ipfrtab[i]) {
1284 if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i],
1287 PRINTF("%s -> ", hostname(4, &ifr.ipfr_src));
1288 if (kmemcpy((char *)&fr, (u_long)ifr.ipfr_rule,
1291 PRINTF("%s %d %d %d %#02x = %#x\n",
1292 hostname(4, &ifr.ipfr_dst), ifr.ipfr_id,
1293 ifr.ipfr_ttl, ifr.ipfr_p, ifr.ipfr_tos,
1295 ipfrtab[i] = ifr.ipfr_next;
1297 if (kmemcpy((char *)ipfrtab, (u_long)ifsp->ifs_nattab,sizeof(ipfrtab)))
1299 for (i = 0; i < IPFT_SIZE; i++)
1300 while (ipfrtab[i]) {
1301 if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i],
1304 PRINTF("NAT: %s -> ", hostname(4, &ifr.ipfr_src));
1305 if (kmemcpy((char *)&fr, (u_long)ifr.ipfr_rule,
1308 PRINTF("%s %d %d %d %#02x = %#x\n",
1309 hostname(4, &ifr.ipfr_dst), ifr.ipfr_id,
1310 ifr.ipfr_ttl, ifr.ipfr_p, ifr.ipfr_tos,
1312 ipfrtab[i] = ifr.ipfr_next;
1318 * Show stats on how auth within IPFilter has been used
1320 static void showauthstates(asp)
1323 frauthent_t *frap, fra;
1326 printf("Authorisation hits: %qu\tmisses %qu\n",
1327 (unsigned long long) asp->fas_hits,
1328 (unsigned long long) asp->fas_miss);
1330 printf("Authorisation hits: %ld\tmisses %ld\n", asp->fas_hits,
1333 printf("nospace %ld\nadded %ld\nsendfail %ld\nsendok %ld\n",
1334 asp->fas_nospace, asp->fas_added, asp->fas_sendfail,
1336 printf("queok %ld\nquefail %ld\nexpire %ld\n",
1337 asp->fas_queok, asp->fas_quefail, asp->fas_expire);
1339 frap = asp->fas_faelist;
1341 if (kmemcpy((char *)&fra, (u_long)frap, sizeof(fra)) == -1)
1344 printf("age %ld\t", fra.fae_age);
1345 printfr(&fra.fae_fr);
1346 frap = fra.fae_next;
1352 * Display groups used for each of filter rules, accounting rules and
1353 * authentication, separately.
1355 static void showgroups(fiop)
1356 struct friostat *fiop;
1358 static char *gnames[3] = { "Filter", "Accounting", "Authentication" };
1362 on = fiop->f_active;
1365 for (i = 0; i < 3; i++) {
1366 printf("%s groups (active):\n", gnames[i]);
1367 for (fp = fiop->f_groups[i][on]; fp; fp = grp.fg_next)
1368 if (kmemcpy((char *)&grp, (u_long)fp, sizeof(grp)))
1371 printf("%hu\n", grp.fg_num);
1372 printf("%s groups (inactive):\n", gnames[i]);
1373 for (fp = fiop->f_groups[i][off]; fp; fp = grp.fg_next)
1374 if (kmemcpy((char *)&grp, (u_long)fp, sizeof(grp)))
1377 printf("%hu\n", grp.fg_num);
1381 static void parse_ipportstr(argument, ip, port)
1382 const char *argument;
1389 /* make working copy of argument, Theoretically you must be able
1390 * to write to optarg, but that seems very ugly to me....
1392 if ((s = malloc(strlen(argument) + 1)) == NULL)
1394 strcpy(s, argument);
1397 if ((comma = strchr(s, ',')) != NULL) {
1398 if (!strcasecmp(s, "any")) {
1400 } else if (!sscanf(comma + 1, "%d", port) ||
1401 (*port < 0) || (*port > 65535)) {
1402 fprintf(stderr, "Invalid port specfication in %s\n",
1410 /* get ip address */
1411 if (!strcasecmp(s, "any")) {
1412 ip->s_addr = INADDR_ANY;
1413 } else if (!inet_aton(s, ip)) {
1414 fprintf(stderr, "Invalid IP address: %s\n", s);
1418 /* free allocated memory */
1424 static char ttlbuf[STSTRSIZE];
1426 static char *ttl_to_string(ttl)
1430 int hours, minutes, seconds;
1432 /* ttl is in half seconds */
1441 sprintf(ttlbuf, "%2d:%02d:%02d", hours, minutes, seconds);
1443 sprintf(ttlbuf, "%2d:%02d", minutes, seconds);
1448 static int sort_pkts(a, b)
1453 register const statetop_t *ap = a;
1454 register const statetop_t *bp = b;
1456 if (ap->st_pkts == bp->st_pkts)
1458 else if (ap->st_pkts < bp->st_pkts)
1464 static int sort_bytes(a, b)
1468 register const statetop_t *ap = a;
1469 register const statetop_t *bp = b;
1471 if (ap->st_bytes == bp->st_bytes)
1473 else if (ap->st_bytes < bp->st_bytes)
1479 static int sort_p(a, b)
1483 register const statetop_t *ap = a;
1484 register const statetop_t *bp = b;
1486 if (ap->st_p == bp->st_p)
1488 else if (ap->st_p < bp->st_p)
1494 static int sort_ttl(a, b)
1498 register const statetop_t *ap = a;
1499 register const statetop_t *bp = b;
1501 if (ap->st_age == bp->st_age)
1503 else if (ap->st_age < bp->st_age)
1508 static int sort_srcip(a, b)
1512 register const statetop_t *ap = a;
1513 register const statetop_t *bp = b;
1515 if (ntohl(ap->st_src.in4.s_addr) == ntohl(bp->st_src.in4.s_addr))
1517 else if (ntohl(ap->st_src.in4.s_addr) > ntohl(bp->st_src.in4.s_addr))
1522 static int sort_dstip(a, b)
1526 register const statetop_t *ap = a;
1527 register const statetop_t *bp = b;
1529 if (ntohl(ap->st_dst.in4.s_addr) == ntohl(bp->st_dst.in4.s_addr))
1531 else if (ntohl(ap->st_dst.in4.s_addr) > ntohl(bp->st_dst.in4.s_addr))