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
))