4 * Copyright (C) 2002-2006 by Darren Reed.
6 * See the IPFILTER.LICENCE file for details on licencing.
8 * Copyright 2008 Sun Microsystems, Inc.
11 # ifndef __FreeBSD_cc_version
12 # include <osreldate.h>
14 # if __FreeBSD_cc_version < 430000
15 # include <osreldate.h>
19 #include <sys/ioctl.h>
22 # include <linux/a.out.h>
27 #if defined(sun) && (defined(__svr4__) || defined(__SVR4))
31 #include "netinet/ipl.h"
33 # if defined(_BSDI_VERSION)
36 # if defined(__FreeBSD__) && \
37 (!defined(__FreeBSD_version) || (__FreeBSD_version < 430000))
40 # if defined(__NetBSD_Version__) && (__NetBSD_Version__ < 105000000)
44 # if defined(__svr4__) || defined(__SVR4)
45 # include <sys/select.h>
47 # undef STATETOP /* NOT supported on SunOS4 */
51 #if defined(STATETOP) && !defined(linux)
52 # include <netinet/ip_var.h>
53 # include <netinet/tcp_fsm.h>
59 # if SOLARIS || defined(__NetBSD__) || defined(_BSDI_VERSION) || \
70 #if defined(__NetBSD__) || (__OpenBSD__)
75 static const char sccsid
[] = "@(#)fils.c 1.21 4/20/96 (C) 1993-2000 Darren Reed";
76 static const char rcsid
[] = "@(#)Id: ipfstat.c,v 1.44.2.27 2009/07/21 09:13:13 darrenr Exp";
80 # define nlist nlist64
87 #define PRINTF (void)printf
88 #define FPRINTF (void)fprintf
89 static char *filters
[4] = { "ipfilter(in)", "ipfilter(out)",
90 "ipacct(in)", "ipacct(out)" };
91 static int state_logging
= -1;
100 frgroup_t
*grtop
= NULL
;
101 frgroup_t
*grtail
= NULL
;
105 #define STGROWSIZE 16
109 #define STSORT_PKTS 1
110 #define STSORT_BYTES 2
112 #define STSORT_SRCIP 4
113 #define STSORT_SRCPT 5
114 #define STSORT_DSTIP 6
115 #define STSORT_DSTPT 7
116 #define STSORT_MAX STSORT_DSTPT
117 #define STSORT_DEFAULT STSORT_BYTES
120 typedef struct statetop
{
134 int main
__P((int, char *[]));
136 static int fetchfrag
__P((int, int, ipfr_t
*));
137 static void showstats
__P((friostat_t
*, u_32_t
));
138 static void showfrstates
__P((ipfrstat_t
*, u_long
));
139 static void showlist
__P((friostat_t
*));
140 static void showipstates
__P((ips_stat_t
*));
141 static void showauthstates
__P((fr_authstat_t
*));
142 static void showgroups
__P((friostat_t
*));
143 static void usage
__P((char *));
144 static void showtqtable_live
__P((int));
145 static void printlivelist
__P((int, int, frentry_t
*, char *, char *));
146 static void printdeadlist
__P((int, int, frentry_t
*, char *, char *));
147 static void parse_ipportstr
__P((const char *, i6addr_t
*, int *));
148 static void ipfstate_live
__P((char *, friostat_t
**, ips_stat_t
**,
149 ipfrstat_t
**, fr_authstat_t
**, u_32_t
*));
150 static void ipfstate_dead
__P((char *, friostat_t
**, ips_stat_t
**,
151 ipfrstat_t
**, fr_authstat_t
**, u_32_t
*));
152 static ipstate_t
*fetchstate
__P((ipstate_t
*, ipstate_t
*));
154 static void topipstates
__P((i6addr_t
, i6addr_t
, int, int, int,
156 static void sig_break
__P((int));
157 static void sig_resize
__P((int));
158 static char *getip
__P((int, i6addr_t
*));
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_srcpt
__P((const void *, const void *));
166 static int sort_dstip
__P((const void *, const void *));
167 static int sort_dstpt
__P((const void *, const void *));
171 static void usage(name
)
175 fprintf(stderr
, "Usage: %s [-6aAdfghIilnoRsv]\n", name
);
177 fprintf(stderr
, "Usage: %s [-aAdfghIilnoRsv]\n", name
);
179 fprintf(stderr
, " %s [-M corefile] [-N symbol-list]\n", name
);
181 fprintf(stderr
, " %s -t [-6C] ", name
);
183 fprintf(stderr
, " %s -t [-C] ", name
);
185 fprintf(stderr
, "[-D destination address] [-P protocol] [-S source address] [-T refresh time]\n");
194 fr_authstat_t frauthst
;
195 fr_authstat_t
*frauthstp
= &frauthst
;
197 friostat_t
*fiop
= &fio
;
199 ips_stat_t
*ipsstp
= &ipsst
;
201 ipfrstat_t
*ifrstp
= &ifrst
;
203 char *options
, *kern
= NULL
;
206 int protocol
= -1; /* -1 = wild card for any protocol */
207 int refreshtime
= 1; /* default update time */
208 int sport
= -1; /* -1 = wild card for any source port */
209 int dport
= -1; /* -1 = wild card for any dest port */
210 int topclosed
= 0; /* do not show closed tcp sessions */
211 i6addr_t saddr
, daddr
;
215 options
= "6aACdfghIilnostvD:M:N:P:RS:T:";
217 options
= "aACdfghIilnostvD:M:N:P:RS:T:";
220 saddr
.in4
.s_addr
= INADDR_ANY
; /* default any v4 source addr */
221 daddr
.in4
.s_addr
= INADDR_ANY
; /* default any v4 dest addr */
223 saddr
.in6
= in6addr_any
; /* default any v6 source addr */
224 daddr
.in6
= in6addr_any
; /* default any v6 dest addr */
227 /* Don't warn about invalid flags when we run getopt for the 1st time */
231 * Parse these two arguments now lest there be any buffer overflows
232 * in the parsing of the rest.
235 while ((c
= getopt(argc
, argv
, options
)) != -1) {
250 if (live_kernel
== 1) {
251 if ((state_fd
= open(IPSTATE_NAME
, O_RDONLY
)) == -1) {
252 perror("open(IPSTATE_NAME)");
255 if ((auth_fd
= open(IPAUTH_NAME
, O_RDONLY
)) == -1) {
256 perror("open(IPAUTH_NAME)");
259 if ((nat_fd
= open(IPNAT_NAME
, O_RDONLY
)) == -1) {
260 perror("open(IPAUTH_NAME)");
263 if ((ipf_fd
= open(IPL_NAME
, O_RDONLY
)) == -1) {
264 fprintf(stderr
, "open(%s)", IPL_NAME
);
270 if (kern
!= NULL
|| memf
!= NULL
) {
271 (void)setgid(getgid());
272 (void)setuid(getuid());
275 if (live_kernel
== 1) {
276 (void) checkrev(IPL_NAME
);
278 if (openkmem(kern
, memf
) == -1)
282 (void)setgid(getgid());
283 (void)setuid(getuid());
287 while ((c
= getopt(argc
, argv
, options
)) != -1)
297 opts
|= OPT_ACCNT
|OPT_SHOWLIST
;
300 opts
|= OPT_AUTHSTATS
;
309 parse_ipportstr(optarg
, &daddr
, &dport
);
312 opts
|= OPT_FRSTATES
;
321 opts
|= OPT_INQUE
|OPT_SHOWLIST
;
324 opts
|= OPT_INACTIVE
;
327 opts
|= OPT_SHOWLIST
;
334 opts
|= OPT_SHOWLINENO
;
337 opts
|= OPT_OUTQUE
|OPT_SHOWLIST
;
340 protocol
= getproto(optarg
);
341 if (protocol
== -1) {
342 fprintf(stderr
, "%s: Invalid protocol: %s\n",
348 opts
|= OPT_NORESOLVE
;
351 opts
|= OPT_IPSTATES
;
354 parse_ipportstr(optarg
, &saddr
, &sport
);
358 opts
|= OPT_STATETOP
;
362 "%s: state top facility not compiled in\n",
367 if (!sscanf(optarg
, "%d", &refreshtime
) ||
368 (refreshtime
<= 0)) {
370 "%s: Invalid refreshtime < 1 : %s\n",
384 if (live_kernel
== 1) {
385 bzero((char *)&fio
, sizeof(fio
));
386 bzero((char *)&ipsst
, sizeof(ipsst
));
387 bzero((char *)&ifrst
, sizeof(ifrst
));
389 ipfstate_live(IPL_NAME
, &fiop
, &ipsstp
, &ifrstp
,
392 ipfstate_dead(kern
, &fiop
, &ipsstp
, &ifrstp
, &frauthstp
, &frf
);
394 if (opts
& OPT_IPSTATES
) {
395 showipstates(ipsstp
);
396 } else if (opts
& OPT_SHOWLIST
) {
398 if ((opts
& OPT_OUTQUE
) && (opts
& OPT_INQUE
)){
402 } else if (opts
& OPT_FRSTATES
)
403 showfrstates(ifrstp
, fiop
->f_ticks
);
405 else if (opts
& OPT_STATETOP
)
406 topipstates(saddr
, daddr
, sport
, dport
, protocol
,
407 use_inet6
? 6 : 4, refreshtime
, topclosed
);
409 else if (opts
& OPT_AUTHSTATS
)
410 showauthstates(frauthstp
);
411 else if (opts
& OPT_GROUPS
)
414 showstats(fiop
, frf
);
421 * Fill in the stats structures from the live kernel, using a combination
422 * of ioctl's and copying directly from kernel memory.
424 static void ipfstate_live(device
, fiopp
, ipsstpp
, ifrstpp
, frauthstpp
, frfp
)
427 ips_stat_t
**ipsstpp
;
428 ipfrstat_t
**ifrstpp
;
429 fr_authstat_t
**frauthstpp
;
434 if (checkrev(device
) == -1) {
435 fprintf(stderr
, "User/kernel version check failed\n");
439 if ((opts
& OPT_AUTHSTATS
) == 0) {
440 bzero((caddr_t
)&ipfo
, sizeof(ipfo
));
441 ipfo
.ipfo_rev
= IPFILTER_VERSION
;
442 ipfo
.ipfo_type
= IPFOBJ_IPFSTAT
;
443 ipfo
.ipfo_size
= sizeof(friostat_t
);
444 ipfo
.ipfo_ptr
= (void *)*fiopp
;
446 if (ioctl(ipf_fd
, SIOCGETFS
, &ipfo
) == -1) {
447 perror("ioctl(ipf:SIOCGETFS)");
451 if (ioctl(ipf_fd
, SIOCGETFF
, frfp
) == -1)
452 perror("ioctl(SIOCGETFF)");
455 if ((opts
& OPT_IPSTATES
) != 0) {
457 bzero((caddr_t
)&ipfo
, sizeof(ipfo
));
458 ipfo
.ipfo_rev
= IPFILTER_VERSION
;
459 ipfo
.ipfo_type
= IPFOBJ_STATESTAT
;
460 ipfo
.ipfo_size
= sizeof(ips_stat_t
);
461 ipfo
.ipfo_ptr
= (void *)*ipsstpp
;
463 if ((ioctl(state_fd
, SIOCGETFS
, &ipfo
) == -1)) {
464 perror("ioctl(state:SIOCGETFS)");
467 if (ioctl(state_fd
, SIOCGETLG
, &state_logging
) == -1) {
468 perror("ioctl(state:SIOCGETLG)");
473 if ((opts
& OPT_FRSTATES
) != 0) {
474 bzero((caddr_t
)&ipfo
, sizeof(ipfo
));
475 ipfo
.ipfo_rev
= IPFILTER_VERSION
;
476 ipfo
.ipfo_type
= IPFOBJ_FRAGSTAT
;
477 ipfo
.ipfo_size
= sizeof(ipfrstat_t
);
478 ipfo
.ipfo_ptr
= (void *)*ifrstpp
;
480 if (ioctl(ipf_fd
, SIOCGFRST
, &ipfo
) == -1) {
481 perror("ioctl(SIOCGFRST)");
486 if (opts
& OPT_DEBUG
)
487 PRINTF("opts %#x name %s\n", opts
, device
);
489 if ((opts
& OPT_AUTHSTATS
) != 0) {
490 bzero((caddr_t
)&ipfo
, sizeof(ipfo
));
491 ipfo
.ipfo_rev
= IPFILTER_VERSION
;
492 ipfo
.ipfo_type
= IPFOBJ_AUTHSTAT
;
493 ipfo
.ipfo_size
= sizeof(fr_authstat_t
);
494 ipfo
.ipfo_ptr
= (void *)*frauthstpp
;
496 if (ioctl(auth_fd
, SIOCATHST
, &ipfo
) == -1) {
497 perror("ioctl(SIOCATHST)");
505 * Build up the stats structures from data held in the "core" memory.
506 * This is mainly useful when looking at data in crash dumps and ioctl's
507 * just won't work any more.
509 static void ipfstate_dead(kernel
, fiopp
, ipsstpp
, ifrstpp
, frauthstpp
, frfp
)
512 ips_stat_t
**ipsstpp
;
513 ipfrstat_t
**ifrstpp
;
514 fr_authstat_t
**frauthstpp
;
517 static fr_authstat_t frauthst
, *frauthstp
;
518 static ips_stat_t ipsst
, *ipsstp
;
519 static ipfrstat_t ifrst
, *ifrstp
;
520 static friostat_t fio
, *fiop
;
521 static ipftq_t ipssttab
[IPF_TCP_NSTATES
];
525 struct nlist deadlist
[44] = {
526 { "fr_authstats" }, /* 0 */
531 { "fr_authend" }, /* 5 */
536 { "fr_defaultauthage" }, /* 10 */
541 { "ips_num" }, /* 15 */
546 { "fr_statesize" }, /* 20 */
547 { "fr_state_doflush" },
551 { "ipfr_stats" }, /* 25 */
556 { "fr_nat_lock" }, /* 30 */
561 { "ipl_frouteok" }, /* 35 */
566 { "fr_flags" }, /* 40 */
567 { "ipstate_logging" },
573 frauthstp
= &frauthst
;
582 *frauthstpp
= frauthstp
;
584 bzero((char *)fiop
, sizeof(*fiop
));
585 bzero((char *)ipsstp
, sizeof(*ipsstp
));
586 bzero((char *)ifrstp
, sizeof(*ifrstp
));
587 bzero((char *)frauthstp
, sizeof(*frauthstp
));
589 if (nlist(kernel
, deadlist
) == -1) {
590 fprintf(stderr
, "nlist error\n");
595 * This is for SIOCGETFF.
597 kmemcpy((char *)frfp
, (u_long
)deadlist
[40].n_value
, sizeof(*frfp
));
600 * f_locks is a combination of the lock variable from each part of
601 * ipfilter (state, auth, nat, fragments).
603 kmemcpy((char *)fiop
, (u_long
)deadlist
[13].n_value
, sizeof(*fiop
));
604 kmemcpy((char *)&fiop
->f_locks
[0], (u_long
)deadlist
[22].n_value
,
605 sizeof(fiop
->f_locks
[0]));
606 kmemcpy((char *)&fiop
->f_locks
[0], (u_long
)deadlist
[30].n_value
,
607 sizeof(fiop
->f_locks
[1]));
608 kmemcpy((char *)&fiop
->f_locks
[2], (u_long
)deadlist
[28].n_value
,
609 sizeof(fiop
->f_locks
[2]));
610 kmemcpy((char *)&fiop
->f_locks
[3], (u_long
)deadlist
[12].n_value
,
611 sizeof(fiop
->f_locks
[3]));
614 * Get pointers to each list of rules (active, inactive, in, out)
616 kmemcpy((char *)&rules
, (u_long
)deadlist
[31].n_value
, sizeof(rules
));
617 fiop
->f_fin
[0] = rules
[0][0];
618 fiop
->f_fin
[1] = rules
[0][1];
619 fiop
->f_fout
[0] = rules
[1][0];
620 fiop
->f_fout
[1] = rules
[1][1];
623 * Same for IPv6, except make them null if support for it is not
627 kmemcpy((char *)&rules
, (u_long
)deadlist
[32].n_value
, sizeof(rules
));
628 fiop
->f_fin6
[0] = rules
[0][0];
629 fiop
->f_fin6
[1] = rules
[0][1];
630 fiop
->f_fout6
[0] = rules
[1][0];
631 fiop
->f_fout6
[1] = rules
[1][1];
633 fiop
->f_fin6
[0] = NULL
;
634 fiop
->f_fin6
[1] = NULL
;
635 fiop
->f_fout6
[0] = NULL
;
636 fiop
->f_fout6
[1] = NULL
;
640 * Now get accounting rules pointers.
642 kmemcpy((char *)&rules
, (u_long
)deadlist
[33].n_value
, sizeof(rules
));
643 fiop
->f_acctin
[0] = rules
[0][0];
644 fiop
->f_acctin
[1] = rules
[0][1];
645 fiop
->f_acctout
[0] = rules
[1][0];
646 fiop
->f_acctout
[1] = rules
[1][1];
649 kmemcpy((char *)&rules
, (u_long
)deadlist
[34].n_value
, sizeof(rules
));
650 fiop
->f_acctin6
[0] = rules
[0][0];
651 fiop
->f_acctin6
[1] = rules
[0][1];
652 fiop
->f_acctout6
[0] = rules
[1][0];
653 fiop
->f_acctout6
[1] = rules
[1][1];
655 fiop
->f_acctin6
[0] = NULL
;
656 fiop
->f_acctin6
[1] = NULL
;
657 fiop
->f_acctout6
[0] = NULL
;
658 fiop
->f_acctout6
[1] = NULL
;
662 * A collection of "global" variables used inside the kernel which
663 * are all collected in friostat_t via ioctl.
665 kmemcpy((char *)&fiop
->f_froute
, (u_long
)deadlist
[35].n_value
,
666 sizeof(fiop
->f_froute
));
667 kmemcpy((char *)&fiop
->f_running
, (u_long
)deadlist
[36].n_value
,
668 sizeof(fiop
->f_running
));
669 kmemcpy((char *)&fiop
->f_groups
, (u_long
)deadlist
[37].n_value
,
670 sizeof(fiop
->f_groups
));
671 kmemcpy((char *)&fiop
->f_active
, (u_long
)deadlist
[38].n_value
,
672 sizeof(fiop
->f_active
));
673 kmemcpy((char *)&fiop
->f_defpass
, (u_long
)deadlist
[39].n_value
,
674 sizeof(fiop
->f_defpass
));
677 * Build up the state information stats structure.
679 kmemcpy((char *)ipsstp
, (u_long
)deadlist
[14].n_value
, sizeof(*ipsstp
));
680 kmemcpy((char *)&temp
, (u_long
)deadlist
[15].n_value
, sizeof(temp
));
681 kmemcpy((char *)ipssttab
, (u_long
)deadlist
[42].n_value
,
683 ipsstp
->iss_active
= temp
;
684 ipsstp
->iss_table
= (void *)deadlist
[18].n_value
;
685 ipsstp
->iss_list
= (void *)deadlist
[17].n_value
;
686 ipsstp
->iss_tcptab
= ipssttab
;
689 * Build up the authentiation information stats structure.
691 kmemcpy((char *)frauthstp
, (u_long
)deadlist
[0].n_value
,
693 frauthstp
->fas_faelist
= (void *)deadlist
[1].n_value
;
696 * Build up the fragment information stats structure.
698 kmemcpy((char *)ifrstp
, (u_long
)deadlist
[25].n_value
,
700 ifrstp
->ifs_table
= (void *)deadlist
[23].n_value
;
701 ifrstp
->ifs_nattab
= (void *)deadlist
[24].n_value
;
702 kmemcpy((char *)&ifrstp
->ifs_inuse
, (u_long
)deadlist
[26].n_value
,
703 sizeof(ifrstp
->ifs_inuse
));
706 * Get logging on/off switches
708 kmemcpy((char *)&state_logging
, (u_long
)deadlist
[41].n_value
,
709 sizeof(state_logging
));
714 * Display the kernel stats for packets blocked and passed and other
715 * associated running totals which are kept.
717 static void showstats(fp
, frf
)
722 PRINTF("bad packets:\t\tin %lu\tout %lu\n",
723 fp
->f_st
[0].fr_bad
, fp
->f_st
[1].fr_bad
);
725 PRINTF(" IPv6 packets:\t\tin %lu out %lu\n",
726 fp
->f_st
[0].fr_ipv6
, fp
->f_st
[1].fr_ipv6
);
728 PRINTF(" input packets:\t\tblocked %lu passed %lu nomatch %lu",
729 fp
->f_st
[0].fr_block
, fp
->f_st
[0].fr_pass
,
731 PRINTF(" counted %lu short %lu\n",
732 fp
->f_st
[0].fr_acct
, fp
->f_st
[0].fr_short
);
733 PRINTF("output packets:\t\tblocked %lu passed %lu nomatch %lu",
734 fp
->f_st
[1].fr_block
, fp
->f_st
[1].fr_pass
,
736 PRINTF(" counted %lu short %lu\n",
737 fp
->f_st
[1].fr_acct
, fp
->f_st
[1].fr_short
);
738 PRINTF(" input packets logged:\tblocked %lu passed %lu\n",
739 fp
->f_st
[0].fr_bpkl
, fp
->f_st
[0].fr_ppkl
);
740 PRINTF("output packets logged:\tblocked %lu passed %lu\n",
741 fp
->f_st
[1].fr_bpkl
, fp
->f_st
[1].fr_ppkl
);
742 PRINTF(" packets logged:\tinput %lu output %lu\n",
743 fp
->f_st
[0].fr_pkl
, fp
->f_st
[1].fr_pkl
);
744 PRINTF(" log failures:\t\tinput %lu output %lu\n",
745 fp
->f_st
[0].fr_skip
, fp
->f_st
[1].fr_skip
);
746 PRINTF("fragment state(in):\tkept %lu\tlost %lu\tnot fragmented %lu\n",
747 fp
->f_st
[0].fr_nfr
, fp
->f_st
[0].fr_bnfr
,
749 PRINTF("fragment state(out):\tkept %lu\tlost %lu\tnot fragmented %lu\n",
750 fp
->f_st
[1].fr_nfr
, fp
->f_st
[1].fr_bnfr
,
752 PRINTF("packet state(in):\tkept %lu\tlost %lu\n",
753 fp
->f_st
[0].fr_ads
, fp
->f_st
[0].fr_bads
);
754 PRINTF("packet state(out):\tkept %lu\tlost %lu\n",
755 fp
->f_st
[1].fr_ads
, fp
->f_st
[1].fr_bads
);
756 PRINTF("ICMP replies:\t%lu\tTCP RSTs sent:\t%lu\n",
757 fp
->f_st
[0].fr_ret
, fp
->f_st
[1].fr_ret
);
758 PRINTF("Invalid source(in):\t%lu\n", fp
->f_st
[0].fr_badsrc
);
759 PRINTF("Result cache hits(in):\t%lu\t(out):\t%lu\n",
760 fp
->f_st
[0].fr_chit
, fp
->f_st
[1].fr_chit
);
761 PRINTF("IN Pullups succeeded:\t%lu\tfailed:\t%lu\n",
762 fp
->f_st
[0].fr_pull
[0], fp
->f_st
[0].fr_pull
[1]);
763 PRINTF("OUT Pullups succeeded:\t%lu\tfailed:\t%lu\n",
764 fp
->f_st
[1].fr_pull
[0], fp
->f_st
[1].fr_pull
[1]);
765 PRINTF("Fastroute successes:\t%lu\tfailures:\t%lu\n",
766 fp
->f_froute
[0], fp
->f_froute
[1]);
767 PRINTF("TCP cksum fails(in):\t%lu\t(out):\t%lu\n",
768 fp
->f_st
[0].fr_tcpbad
, fp
->f_st
[1].fr_tcpbad
);
769 PRINTF("IPF Ticks:\t%lu\n", fp
->f_ticks
);
771 PRINTF("Packet log flags set: (%#x)\n", frf
);
772 if (frf
& FF_LOGPASS
)
773 PRINTF("\tpackets passed through filter\n");
774 if (frf
& FF_LOGBLOCK
)
775 PRINTF("\tpackets blocked by filter\n");
776 if (frf
& FF_LOGNOMATCH
)
777 PRINTF("\tpackets not matched by filter\n");
784 * Print out a list of rules from the kernel, starting at the one passed.
786 static void printlivelist(out
, set
, fp
, group
, comment
)
789 char *group
, *comment
;
807 rule
.iri_inout
= out
;
808 rule
.iri_active
= set
;
811 rule
.iri_v
= use_inet6
? 6 : 4;
813 strncpy(rule
.iri_group
, group
, FR_GROUPLEN
);
815 rule
.iri_group
[0] = '\0';
817 bzero((char *)&zero
, sizeof(zero
));
819 bzero((char *)&obj
, sizeof(obj
));
820 obj
.ipfo_rev
= IPFILTER_VERSION
;
821 obj
.ipfo_type
= IPFOBJ_IPFITER
;
822 obj
.ipfo_size
= sizeof(rule
);
823 obj
.ipfo_ptr
= &rule
;
826 * The API does not know how much we need for filter data. Assume
827 * 10K is large enough. XXX: The code silently fails elsewhere on
828 * allocation, we do the same here.
830 if ((buf
= malloc(bufsiz
= sizeof(*fp
) + 10240)) == NULL
)
834 memset(buf
, 0xff, bufsiz
);
837 if (ioctl(ipf_fd
, SIOCIPFITER
, &obj
) == -1) {
838 perror("ioctl(SIOCIPFITER)");
841 if (bcmp(fp
, &zero
, sizeof(zero
)) == 0)
843 if (fp
->fr_data
!= NULL
)
844 fp
->fr_data
= (char *)fp
+ sizeof(*fp
);
848 if (opts
& (OPT_HITS
|OPT_VERBOSE
))
850 PRINTF("%qu ", (unsigned long long) fp
->fr_hits
);
852 PRINTF("%lu ", fp
->fr_hits
);
854 if (opts
& (OPT_ACCNT
|OPT_VERBOSE
))
856 PRINTF("%qu ", (unsigned long long) fp
->fr_bytes
);
858 PRINTF("%lu ", fp
->fr_bytes
);
860 if (opts
& OPT_SHOWLINENO
)
864 if (opts
& OPT_DEBUG
) {
865 binprint(fp
, sizeof(*fp
));
866 if (fp
->fr_data
!= NULL
&& fp
->fr_dsize
> 0)
867 binprint(fp
->fr_data
, fp
->fr_dsize
);
869 if (fp
->fr_grhead
[0] != '\0') {
870 for (g
= grtop
; g
!= NULL
; g
= g
->fg_next
) {
871 if (!strncmp(fp
->fr_grhead
, g
->fg_name
,
876 g
= calloc(1, sizeof(*g
));
879 strncpy(g
->fg_name
, fp
->fr_grhead
,
891 if (fp
->fr_type
== FR_T_CALLFUNC
) {
892 printlivelist(out
, set
, fp
->fr_data
, group
,
895 } while (fp
->fr_next
!= NULL
);
898 while ((g
= grtop
) != NULL
) {
899 printf("# Group %s\n", g
->fg_name
);
900 printlivelist(out
, set
, NULL
, g
->fg_name
, comment
);
909 static void printdeadlist(out
, set
, fp
, group
, comment
)
912 char *group
, *comment
;
914 frgroup_t
*grtop
, *grtail
, *g
;
927 if (kmemcpy((char *)&fb
, (u_long
)fb
.fr_next
,
934 type
= fb
.fr_type
& ~FR_T_BUILTIN
;
935 if (type
== FR_T_IPF
|| type
== FR_T_BPFOPC
) {
937 data
= malloc(fb
.fr_dsize
);
939 if (kmemcpy(data
, (u_long
)fb
.fr_data
,
940 fb
.fr_dsize
) == -1) {
950 if (opts
& (OPT_HITS
|OPT_VERBOSE
))
952 PRINTF("%qu ", (unsigned long long) fb
.fr_hits
);
954 PRINTF("%lu ", fb
.fr_hits
);
956 if (opts
& (OPT_ACCNT
|OPT_VERBOSE
))
958 PRINTF("%qu ", (unsigned long long) fb
.fr_bytes
);
960 PRINTF("%lu ", fb
.fr_bytes
);
962 if (opts
& OPT_SHOWLINENO
)
966 if (opts
& OPT_DEBUG
) {
967 binprint(fp
, sizeof(*fp
));
968 if (fb
.fr_data
!= NULL
&& fb
.fr_dsize
> 0)
969 binprint(fb
.fr_data
, fb
.fr_dsize
);
973 if (fb
.fr_grhead
[0] != '\0') {
974 g
= calloc(1, sizeof(*g
));
977 strncpy(g
->fg_name
, fb
.fr_grhead
,
988 if (type
== FR_T_CALLFUNC
) {
989 printdeadlist(out
, set
, fb
.fr_data
, group
,
992 } while (fb
.fr_next
!= NULL
);
994 while ((g
= grtop
) != NULL
) {
995 printdeadlist(out
, set
, NULL
, g
->fg_name
, comment
);
1002 * print out all of the asked for rule sets, using the stats struct as
1003 * the base from which to get the pointers.
1005 static void showlist(fiop
)
1006 struct friostat
*fiop
;
1008 struct frentry
*fp
= NULL
;
1011 set
= fiop
->f_active
;
1012 if (opts
& OPT_INACTIVE
)
1014 if (opts
& OPT_ACCNT
) {
1016 if ((use_inet6
) && (opts
& OPT_OUTQUE
)) {
1018 fp
= (struct frentry
*)fiop
->f_acctout6
[set
];
1019 } else if ((use_inet6
) && (opts
& OPT_INQUE
)) {
1021 fp
= (struct frentry
*)fiop
->f_acctin6
[set
];
1024 if (opts
& OPT_OUTQUE
) {
1026 fp
= (struct frentry
*)fiop
->f_acctout
[set
];
1027 } else if (opts
& OPT_INQUE
) {
1029 fp
= (struct frentry
*)fiop
->f_acctin
[set
];
1031 FPRINTF(stderr
, "No -i or -o given with -a\n");
1036 if ((use_inet6
) && (opts
& OPT_OUTQUE
)) {
1038 fp
= (struct frentry
*)fiop
->f_fout6
[set
];
1039 } else if ((use_inet6
) && (opts
& OPT_INQUE
)) {
1041 fp
= (struct frentry
*)fiop
->f_fin6
[set
];
1044 if (opts
& OPT_OUTQUE
) {
1046 fp
= (struct frentry
*)fiop
->f_fout
[set
];
1047 } else if (opts
& OPT_INQUE
) {
1049 fp
= (struct frentry
*)fiop
->f_fin
[set
];
1053 if (opts
& OPT_DEBUG
)
1054 FPRINTF(stderr
, "showlist:opts %#x i %d\n", opts
, i
);
1056 if (opts
& OPT_DEBUG
)
1057 PRINTF("fp %p set %d\n", fp
, set
);
1059 FPRINTF(stderr
, "empty list for %s%s\n",
1060 (opts
& OPT_INACTIVE
) ? "inactive " : "", filters
[i
]);
1063 if (live_kernel
== 1)
1064 printlivelist(i
, set
, fp
, NULL
, NULL
);
1066 printdeadlist(i
, set
, fp
, NULL
, NULL
);
1071 * Display ipfilter stateful filtering information
1073 static void showipstates(ipsp
)
1076 u_long minlen
, maxlen
, totallen
, *buckets
;
1082 * If a list of states hasn't been asked for, only print out stats
1084 if (!(opts
& OPT_SHOWLIST
)) {
1086 sz
= sizeof(*buckets
) * ipsp
->iss_statesize
;
1087 buckets
= (u_long
*)malloc(sz
);
1089 obj
.ipfo_rev
= IPFILTER_VERSION
;
1090 obj
.ipfo_type
= IPFOBJ_GTABLE
;
1091 obj
.ipfo_size
= sizeof(table
);
1092 obj
.ipfo_ptr
= &table
;
1094 table
.ita_type
= IPFTABLE_BUCKETS
;
1095 table
.ita_table
= buckets
;
1097 if (live_kernel
== 1) {
1098 if (ioctl(state_fd
, SIOCGTABL
, &obj
) != 0) {
1103 if (kmemcpy((char *)buckets
,
1104 (u_long
)ipsp
->iss_bucketlen
, sz
)) {
1110 PRINTF("IP states added:\n\t%lu TCP\n\t%lu UDP\n\t%lu ICMP\n",
1111 ipsp
->iss_tcp
, ipsp
->iss_udp
, ipsp
->iss_icmp
);
1112 PRINTF("\t%lu hits\n\t%lu misses\n", ipsp
->iss_hits
,
1114 PRINTF("\t%lu bucket full\n", ipsp
->iss_bucketfull
);
1115 PRINTF("\t%lu maximum rule references\n", ipsp
->iss_maxref
);
1116 PRINTF("\t%lu maximum\n\t%lu no memory\n\t%lu bkts in use\n",
1117 ipsp
->iss_max
, ipsp
->iss_nomem
, ipsp
->iss_inuse
);
1118 PRINTF("\t%lu active\n\t%lu expired\n\t%lu closed\n",
1119 ipsp
->iss_active
, ipsp
->iss_expire
, ipsp
->iss_fin
);
1121 PRINTF("State logging %sabled\n",
1122 state_logging
? "en" : "dis");
1124 PRINTF("\nState table bucket statistics:\n");
1125 PRINTF("\t%lu in use\t\n", ipsp
->iss_inuse
);
1126 PRINTF("\t%u%% hash efficiency\n", ipsp
->iss_active
?
1127 (u_int
)(ipsp
->iss_inuse
* 100 / ipsp
->iss_active
) : 0);
1129 minlen
= ipsp
->iss_inuse
;
1133 for (i
= 0; i
< ipsp
->iss_statesize
; i
++) {
1134 if (buckets
[i
] > maxlen
)
1135 maxlen
= buckets
[i
];
1136 if (buckets
[i
] < minlen
)
1137 minlen
= buckets
[i
];
1138 totallen
+= buckets
[i
];
1141 PRINTF("\t%2.2f%% bucket usage\n\t%lu minimal length\n",
1142 ((float)ipsp
->iss_inuse
/ ipsp
->iss_statesize
) * 100.0,
1144 PRINTF("\t%lu maximal length\n\t%.3f average length\n",
1146 ipsp
->iss_inuse
? (float) totallen
/ ipsp
->iss_inuse
:
1149 #define ENTRIES_PER_LINE 5
1151 if (opts
& OPT_VERBOSE
) {
1152 PRINTF("\nCurrent bucket sizes :\n");
1153 for (i
= 0; i
< ipsp
->iss_statesize
; i
++) {
1154 if ((i
% ENTRIES_PER_LINE
) == 0)
1156 PRINTF("%4d -> %4lu", i
, buckets
[i
]);
1157 if ((i
% ENTRIES_PER_LINE
) ==
1158 (ENTRIES_PER_LINE
- 1))
1169 if (live_kernel
== 1) {
1170 showtqtable_live(state_fd
);
1172 printtqtable(ipsp
->iss_tcptab
);
1180 * Print out all the state information currently held in the kernel.
1182 while (ipsp
->iss_list
!= NULL
) {
1185 ipsp
->iss_list
= fetchstate(ipsp
->iss_list
, &ips
);
1187 if (ipsp
->iss_list
!= NULL
) {
1188 ipsp
->iss_list
= ips
.is_next
;
1189 printstate(&ips
, opts
, ipsp
->iss_ticks
);
1196 static int handle_resize
= 0, handle_break
= 0;
1198 static void topipstates(saddr
, daddr
, sport
, dport
, protocol
, ver
,
1199 refreshtime
, topclosed
)
1209 char str1
[STSTRSIZE
], str2
[STSTRSIZE
], str3
[STSTRSIZE
], str4
[STSTRSIZE
];
1210 int maxtsentries
= 0, reverse
= 0, sorting
= STSORT_DEFAULT
;
1211 int i
, j
, winy
, tsentry
, maxx
, maxy
, redraw
= 0, ret
= 0;
1212 int len
, srclen
, dstlen
, forward
= 1, c
= 0;
1213 ips_stat_t ipsst
, *ipsstp
= &ipsst
;
1214 int token_type
= IPFGENITER_STATE
;
1215 statetop_t
*tstable
= NULL
, *tp
;
1216 const char *errstr
= "";
1219 struct timeval selecttimeout
;
1220 char hostnm
[HOSTNMLEN
];
1221 struct protoent
*proto
;
1225 /* install signal handlers */
1226 signal(SIGINT
, sig_break
);
1227 signal(SIGQUIT
, sig_break
);
1228 signal(SIGTERM
, sig_break
);
1229 signal(SIGWINCH
, sig_resize
);
1231 /* init ncurses stuff */
1237 getmaxyx(stdscr
, maxy
, maxx
);
1240 gethostname(hostnm
, sizeof(hostnm
) - 1);
1241 hostnm
[sizeof(hostnm
) - 1] = '\0';
1243 /* init ipfobj_t stuff */
1244 bzero((caddr_t
)&ipfo
, sizeof(ipfo
));
1245 ipfo
.ipfo_rev
= IPFILTER_VERSION
;
1246 ipfo
.ipfo_type
= IPFOBJ_STATESTAT
;
1247 ipfo
.ipfo_size
= sizeof(*ipsstp
);
1248 ipfo
.ipfo_ptr
= (void *)ipsstp
;
1250 /* repeat until user aborts */
1253 /* get state table */
1254 bzero((char *)&ipsst
, sizeof(ipsst
));
1255 if ((ioctl(state_fd
, SIOCGETFS
, &ipfo
) == -1)) {
1256 errstr
= "ioctl(SIOCGETFS)";
1261 /* clear the history */
1264 /* reset max str len */
1265 srclen
= dstlen
= 0;
1267 /* read the state table and store in tstable */
1268 for (; ipsstp
->iss_list
; ipsstp
->iss_list
= ips
.is_next
) {
1270 ipsstp
->iss_list
= fetchstate(ipsstp
->iss_list
, &ips
);
1271 if (ipsstp
->iss_list
== NULL
)
1274 if (ips
.is_v
!= ver
)
1277 /* check v4 src/dest addresses */
1278 if (ips
.is_v
== 4) {
1279 if ((saddr
.in4
.s_addr
!= INADDR_ANY
&&
1280 saddr
.in4
.s_addr
!= ips
.is_saddr
) ||
1281 (daddr
.in4
.s_addr
!= INADDR_ANY
&&
1282 daddr
.in4
.s_addr
!= ips
.is_daddr
))
1286 /* check v6 src/dest addresses */
1287 if (ips
.is_v
== 6) {
1288 if ((IP6_NEQ(&saddr
, &in6addr_any
) &&
1289 IP6_NEQ(&saddr
, &ips
.is_src
)) ||
1290 (IP6_NEQ(&daddr
, &in6addr_any
) &&
1291 IP6_NEQ(&daddr
, &ips
.is_dst
)))
1295 /* check protocol */
1296 if (protocol
> 0 && protocol
!= ips
.is_p
)
1299 /* check ports if protocol is TCP or UDP */
1300 if (((ips
.is_p
== IPPROTO_TCP
) ||
1301 (ips
.is_p
== IPPROTO_UDP
)) &&
1302 (((sport
> 0) && (htons(sport
) != ips
.is_sport
)) ||
1303 ((dport
> 0) && (htons(dport
) != ips
.is_dport
))))
1306 /* show closed TCP sessions ? */
1307 if ((topclosed
== 0) && (ips
.is_p
== IPPROTO_TCP
) &&
1308 (ips
.is_state
[0] >= IPF_TCPS_LAST_ACK
) &&
1309 (ips
.is_state
[1] >= IPF_TCPS_LAST_ACK
))
1313 * if necessary make room for this state
1317 if (!maxtsentries
|| tsentry
== maxtsentries
) {
1318 maxtsentries
+= STGROWSIZE
;
1319 tstable
= realloc(tstable
,
1320 maxtsentries
* sizeof(statetop_t
));
1321 if (tstable
== NULL
) {
1327 /* get max src/dest address string length */
1328 len
= strlen(getip(ips
.is_v
, &ips
.is_src
));
1331 len
= strlen(getip(ips
.is_v
, &ips
.is_dst
));
1335 /* fill structure */
1336 tp
= tstable
+ tsentry
;
1337 tp
->st_src
= ips
.is_src
;
1338 tp
->st_dst
= ips
.is_dst
;
1339 tp
->st_p
= ips
.is_p
;
1340 tp
->st_v
= ips
.is_v
;
1341 tp
->st_state
[0] = ips
.is_state
[0];
1342 tp
->st_state
[1] = ips
.is_state
[1];
1344 tp
->st_pkts
= ips
.is_pkts
[0]+ips
.is_pkts
[1];
1345 tp
->st_bytes
= ips
.is_bytes
[0]+ips
.is_bytes
[1];
1347 tp
->st_pkts
= ips
.is_pkts
[2]+ips
.is_pkts
[3];
1348 tp
->st_bytes
= ips
.is_bytes
[2]+ips
.is_bytes
[3];
1350 tp
->st_age
= ips
.is_die
- ipsstp
->iss_ticks
;
1351 if ((ips
.is_p
== IPPROTO_TCP
) ||
1352 (ips
.is_p
== IPPROTO_UDP
)) {
1353 tp
->st_sport
= ips
.is_sport
;
1354 tp
->st_dport
= ips
.is_dport
;
1358 (void) ioctl(state_fd
, SIOCIPFDELTOK
, &token_type
);
1361 /* sort the array */
1362 if (tsentry
!= -1) {
1366 qsort(tstable
, tsentry
+ 1,
1367 sizeof(statetop_t
), sort_p
);
1370 qsort(tstable
, tsentry
+ 1,
1371 sizeof(statetop_t
), sort_pkts
);
1374 qsort(tstable
, tsentry
+ 1,
1375 sizeof(statetop_t
), sort_bytes
);
1378 qsort(tstable
, tsentry
+ 1,
1379 sizeof(statetop_t
), sort_ttl
);
1382 qsort(tstable
, tsentry
+ 1,
1383 sizeof(statetop_t
), sort_srcip
);
1386 qsort(tstable
, tsentry
+1,
1387 sizeof(statetop_t
), sort_srcpt
);
1390 qsort(tstable
, tsentry
+ 1,
1391 sizeof(statetop_t
), sort_dstip
);
1394 qsort(tstable
, tsentry
+ 1,
1395 sizeof(statetop_t
), sort_dstpt
);
1402 /* handle window resizes */
1403 if (handle_resize
) {
1410 getmaxyx(stdscr
, maxy
, maxx
);
1424 sprintf(str1
, "%s - %s - state top", hostnm
, IPL_VERSION
);
1425 for (j
= 0 ; j
< (maxx
- 8 - strlen(str1
)) / 2; j
++)
1430 /* just for fun add a clock */
1431 move(winy
, maxx
- 8);
1433 strftime(str1
, 80, "%T", localtime(&t
));
1434 printw("%s\n", str1
);
1437 * print the display filters, this is placed in the loop,
1438 * because someday I might add code for changing these
1439 * while the programming is running :-)
1442 sprintf(str1
, "%s,%d", getip(ver
, &saddr
), sport
);
1444 sprintf(str1
, "%s", getip(ver
, &saddr
));
1447 sprintf(str2
, "%s,%d", getip(ver
, &daddr
), dport
);
1449 sprintf(str2
, "%s", getip(ver
, &daddr
));
1452 strcpy(str3
, "any");
1453 else if ((proto
= getprotobynumber(protocol
)) != NULL
)
1454 sprintf(str3
, "%s", proto
->p_name
);
1456 sprintf(str3
, "%d", protocol
);
1461 sprintf(str4
, "proto");
1464 sprintf(str4
, "# pkts");
1467 sprintf(str4
, "# bytes");
1470 sprintf(str4
, "ttl");
1473 sprintf(str4
, "src ip");
1476 sprintf(str4
, "src port");
1479 sprintf(str4
, "dest ip");
1482 sprintf(str4
, "dest port");
1485 sprintf(str4
, "unknown");
1490 strcat(str4
, " (reverse)");
1494 printw("Src: %s, Dest: %s, Proto: %s, Sorted by: %s\n\n",
1495 str1
, str2
, str3
, str4
);
1498 * For an IPv4 IP address we need at most 15 characters,
1499 * 4 tuples of 3 digits, separated by 3 dots. Enforce this
1500 * length, so the colums do not change positions based
1501 * on the size of the IP address. This length makes the
1502 * output fit in a 80 column terminal.
1503 * We are lacking a good solution for IPv6 addresses (that
1504 * can be longer that 15 characters), so we do not enforce
1505 * a maximum on the IP field size.
1512 /* print column description */
1516 printw("%-*s %-*s %3s %4s %7s %9s %9s\n",
1517 srclen
+ 6, "Source IP", dstlen
+ 6, "Destination IP",
1518 "ST", "PR", "#pkts", "#bytes", "ttl");
1521 /* print all the entries */
1526 if (tsentry
> maxy
- 6)
1528 for (i
= 0; i
<= tsentry
; i
++) {
1529 /* print src/dest and port */
1530 if ((tp
->st_p
== IPPROTO_TCP
) ||
1531 (tp
->st_p
== IPPROTO_UDP
)) {
1532 sprintf(str1
, "%s,%hu",
1533 getip(tp
->st_v
, &tp
->st_src
),
1534 ntohs(tp
->st_sport
));
1535 sprintf(str2
, "%s,%hu",
1536 getip(tp
->st_v
, &tp
->st_dst
),
1537 ntohs(tp
->st_dport
));
1539 sprintf(str1
, "%s", getip(tp
->st_v
,
1541 sprintf(str2
, "%s", getip(tp
->st_v
,
1546 printw("%-*s %-*s", srclen
+ 6, str1
, dstlen
+ 6, str2
);
1549 sprintf(str1
, "%X/%X", tp
->st_state
[0],
1551 printw(" %3s", str1
);
1553 /* print protocol */
1554 proto
= getprotobynumber(tp
->st_p
);
1556 strncpy(str1
, proto
->p_name
, 4);
1559 sprintf(str1
, "%d", tp
->st_p
);
1561 /* just print icmp for IPv6-ICMP */
1562 if (tp
->st_p
== IPPROTO_ICMPV6
)
1563 strcpy(str1
, "icmp");
1564 printw(" %4s", str1
);
1566 /* print #pkt/#bytes */
1568 printw(" %7qu %9qu", (unsigned long long) tp
->st_pkts
,
1569 (unsigned long long) tp
->st_bytes
);
1571 printw(" %7lu %9lu", tp
->st_pkts
, tp
->st_bytes
);
1573 printw(" %9s", ttl_to_string(tp
->st_age
));
1581 /* screen data structure is filled, now update the screen */
1585 if (refresh() == ERR
)
1592 /* wait for key press or a 1 second time out period */
1593 selecttimeout
.tv_sec
= refreshtime
;
1594 selecttimeout
.tv_usec
= 0;
1597 select(1, &readfd
, NULL
, NULL
, &selecttimeout
);
1599 /* if key pressed, read all waiting keys */
1600 if (FD_ISSET(0, &readfd
)) {
1605 if (ISALPHA(c
) && ISUPPER(c
))
1609 } else if (c
== 'q') {
1611 } else if (c
== 'r') {
1613 } else if (c
== 'b') {
1615 } else if (c
== 'f') {
1617 } else if (c
== 's') {
1618 if (++sorting
> STSORT_MAX
)
1627 /* nocbreak(); XXX - endwin() should make this redundant */
1638 * Show fragment cache information that's held in the kernel.
1640 static void showfrstates(ifsp
, ticks
)
1644 struct ipfr
*ipfrtab
[IPFT_SIZE
], ifr
;
1648 * print out the numeric statistics
1650 PRINTF("IP fragment states:\n\t%lu new\n\t%lu expired\n\t%lu hits\n",
1651 ifsp
->ifs_new
, ifsp
->ifs_expire
, ifsp
->ifs_hits
);
1652 PRINTF("\t%lu retrans\n\t%lu too short\n",
1653 ifsp
->ifs_retrans0
, ifsp
->ifs_short
);
1654 PRINTF("\t%lu no memory\n\t%lu already exist\n",
1655 ifsp
->ifs_nomem
, ifsp
->ifs_exists
);
1656 PRINTF("\t%lu inuse\n", ifsp
->ifs_inuse
);
1659 if (live_kernel
== 0) {
1660 if (kmemcpy((char *)ipfrtab
, (u_long
)ifsp
->ifs_table
,
1666 * Print out the contents (if any) of the fragment cache table.
1668 if (live_kernel
== 1) {
1670 if (fetchfrag(ipf_fd
, IPFGENITER_FRAG
, &ifr
) != 0)
1672 if (ifr
.ipfr_ifp
== NULL
)
1674 ifr
.ipfr_ttl
-= ticks
;
1675 printfraginfo("", &ifr
);
1678 for (i
= 0; i
< IPFT_SIZE
; i
++)
1679 while (ipfrtab
[i
] != NULL
) {
1680 if (kmemcpy((char *)&ifr
, (u_long
)ipfrtab
[i
],
1683 printfraginfo("", &ifr
);
1684 ipfrtab
[i
] = ifr
.ipfr_next
;
1688 * Print out the contents (if any) of the NAT fragment cache table.
1691 if (live_kernel
== 0) {
1692 if (kmemcpy((char *)ipfrtab
, (u_long
)ifsp
->ifs_nattab
,
1697 if (live_kernel
== 1) {
1699 if (fetchfrag(nat_fd
, IPFGENITER_NATFRAG
, &ifr
) != 0)
1701 if (ifr
.ipfr_ifp
== NULL
)
1703 ifr
.ipfr_ttl
-= ticks
;
1704 printfraginfo("NAT: ", &ifr
);
1707 for (i
= 0; i
< IPFT_SIZE
; i
++)
1708 while (ipfrtab
[i
] != NULL
) {
1709 if (kmemcpy((char *)&ifr
, (u_long
)ipfrtab
[i
],
1712 printfraginfo("NAT: ", &ifr
);
1713 ipfrtab
[i
] = ifr
.ipfr_next
;
1720 * Show stats on how auth within IPFilter has been used
1722 static void showauthstates(asp
)
1725 frauthent_t
*frap
, fra
;
1729 obj
.ipfo_rev
= IPFILTER_VERSION
;
1730 obj
.ipfo_type
= IPFOBJ_GENITER
;
1731 obj
.ipfo_size
= sizeof(auth
);
1732 obj
.ipfo_ptr
= &auth
;
1734 auth
.igi_type
= IPFGENITER_AUTH
;
1735 auth
.igi_nitems
= 1;
1736 auth
.igi_data
= &fra
;
1739 printf("Authorisation hits: %qu\tmisses %qu\n",
1740 (unsigned long long) asp
->fas_hits
,
1741 (unsigned long long) asp
->fas_miss
);
1743 printf("Authorisation hits: %ld\tmisses %ld\n", asp
->fas_hits
,
1746 printf("nospace %ld\nadded %ld\nsendfail %ld\nsendok %ld\n",
1747 asp
->fas_nospace
, asp
->fas_added
, asp
->fas_sendfail
,
1749 printf("queok %ld\nquefail %ld\nexpire %ld\n",
1750 asp
->fas_queok
, asp
->fas_quefail
, asp
->fas_expire
);
1752 frap
= asp
->fas_faelist
;
1754 if (live_kernel
== 1) {
1755 if (ioctl(auth_fd
, SIOCGENITER
, &obj
))
1758 if (kmemcpy((char *)&fra
, (u_long
)frap
,
1762 printf("age %ld\t", fra
.fae_age
);
1763 printfr(&fra
.fae_fr
, ioctl
);
1764 frap
= fra
.fae_next
;
1770 * Display groups used for each of filter rules, accounting rules and
1771 * authentication, separately.
1773 static void showgroups(fiop
)
1774 struct friostat
*fiop
;
1776 static char *gnames
[3] = { "Filter", "Accounting", "Authentication" };
1777 static int gnums
[3] = { IPL_LOGIPF
, IPL_LOGCOUNT
, IPL_LOGAUTH
};
1781 on
= fiop
->f_active
;
1784 for (i
= 0; i
< 3; i
++) {
1785 printf("%s groups (active):\n", gnames
[i
]);
1786 for (fp
= fiop
->f_groups
[gnums
[i
]][on
]; fp
!= NULL
;
1788 if (kmemcpy((char *)&grp
, (u_long
)fp
, sizeof(grp
)))
1791 printf("%s\n", grp
.fg_name
);
1792 printf("%s groups (inactive):\n", gnames
[i
]);
1793 for (fp
= fiop
->f_groups
[gnums
[i
]][off
]; fp
!= NULL
;
1795 if (kmemcpy((char *)&grp
, (u_long
)fp
, sizeof(grp
)))
1798 printf("%s\n", grp
.fg_name
);
1802 static void parse_ipportstr(argument
, ip
, port
)
1803 const char *argument
;
1810 /* make working copy of argument, Theoretically you must be able
1811 * to write to optarg, but that seems very ugly to me....
1813 s
= strdup(argument
);
1818 if ((comma
= strchr(s
, ',')) != NULL
) {
1819 if (!strcasecmp(comma
+ 1, "any")) {
1821 } else if (!sscanf(comma
+ 1, "%d", port
) ||
1822 (*port
< 0) || (*port
> 65535)) {
1823 fprintf(stderr
, "Invalid port specification in %s\n",
1832 /* get ip address */
1833 if (!strcasecmp(s
, "any")) {
1834 ip
->in4
.s_addr
= INADDR_ANY
;
1837 ip
->in6
= in6addr_any
;
1838 } else if (use_inet6
&& inet_pton(AF_INET6
, s
, &ip
->in6
)) {
1841 } else if (inet_aton(s
, &ip
->in4
))
1845 fprintf(stderr
, "Invalid IP address: %s\n", s
);
1850 /* free allocated memory */
1856 static void sig_resize(s
)
1862 static void sig_break(s
)
1868 static char *getip(v
, addr
)
1873 static char hostbuf
[MAXHOSTNAMELEN
+1];
1877 return inet_ntoa(addr
->in4
);
1880 (void) inet_ntop(AF_INET6
, &addr
->in6
, hostbuf
, sizeof(hostbuf
) - 1);
1881 hostbuf
[MAXHOSTNAMELEN
] = '\0';
1889 static char *ttl_to_string(ttl
)
1892 static char ttlbuf
[STSTRSIZE
];
1893 int hours
, minutes
, seconds
;
1895 /* ttl is in half seconds */
1904 sprintf(ttlbuf
, "%2d:%02d:%02d", hours
, minutes
, seconds
);
1906 sprintf(ttlbuf
, "%2d:%02d", minutes
, seconds
);
1911 static int sort_pkts(a
, b
)
1916 register const statetop_t
*ap
= a
;
1917 register const statetop_t
*bp
= b
;
1919 if (ap
->st_pkts
== bp
->st_pkts
)
1921 else if (ap
->st_pkts
< bp
->st_pkts
)
1927 static int sort_bytes(a
, b
)
1931 register const statetop_t
*ap
= a
;
1932 register const statetop_t
*bp
= b
;
1934 if (ap
->st_bytes
== bp
->st_bytes
)
1936 else if (ap
->st_bytes
< bp
->st_bytes
)
1942 static int sort_p(a
, b
)
1946 register const statetop_t
*ap
= a
;
1947 register const statetop_t
*bp
= b
;
1949 if (ap
->st_p
== bp
->st_p
)
1951 else if (ap
->st_p
< bp
->st_p
)
1957 static int sort_ttl(a
, b
)
1961 register const statetop_t
*ap
= a
;
1962 register const statetop_t
*bp
= b
;
1964 if (ap
->st_age
== bp
->st_age
)
1966 else if (ap
->st_age
< bp
->st_age
)
1971 static int sort_srcip(a
, b
)
1975 register const statetop_t
*ap
= a
;
1976 register const statetop_t
*bp
= b
;
1980 if (IP6_EQ(&ap
->st_src
, &bp
->st_src
))
1982 else if (IP6_GT(&ap
->st_src
, &bp
->st_src
))
1987 if (ntohl(ap
->st_src
.in4
.s_addr
) ==
1988 ntohl(bp
->st_src
.in4
.s_addr
))
1990 else if (ntohl(ap
->st_src
.in4
.s_addr
) >
1991 ntohl(bp
->st_src
.in4
.s_addr
))
1997 static int sort_srcpt(a
, b
)
2001 register const statetop_t
*ap
= a
;
2002 register const statetop_t
*bp
= b
;
2004 if (htons(ap
->st_sport
) == htons(bp
->st_sport
))
2006 else if (htons(ap
->st_sport
) > htons(bp
->st_sport
))
2011 static int sort_dstip(a
, b
)
2015 register const statetop_t
*ap
= a
;
2016 register const statetop_t
*bp
= b
;
2020 if (IP6_EQ(&ap
->st_dst
, &bp
->st_dst
))
2022 else if (IP6_GT(&ap
->st_dst
, &bp
->st_dst
))
2027 if (ntohl(ap
->st_dst
.in4
.s_addr
) ==
2028 ntohl(bp
->st_dst
.in4
.s_addr
))
2030 else if (ntohl(ap
->st_dst
.in4
.s_addr
) >
2031 ntohl(bp
->st_dst
.in4
.s_addr
))
2037 static int sort_dstpt(a
, b
)
2041 register const statetop_t
*ap
= a
;
2042 register const statetop_t
*bp
= b
;
2044 if (htons(ap
->st_dport
) == htons(bp
->st_dport
))
2046 else if (htons(ap
->st_dport
) > htons(bp
->st_dport
))
2054 ipstate_t
*fetchstate(src
, dst
)
2055 ipstate_t
*src
, *dst
;
2057 if (live_kernel
== 1) {
2061 obj
.ipfo_rev
= IPFILTER_VERSION
;
2062 obj
.ipfo_type
= IPFOBJ_GENITER
;
2063 obj
.ipfo_size
= sizeof(state
);
2064 obj
.ipfo_ptr
= &state
;
2066 state
.igi_type
= IPFGENITER_STATE
;
2067 state
.igi_nitems
= 1;
2068 state
.igi_data
= dst
;
2070 if (ioctl(state_fd
, SIOCGENITER
, &obj
) != 0)
2073 if (kmemcpy((char *)dst
, (u_long
)src
, sizeof(*dst
)))
2080 static int fetchfrag(fd
, type
, frp
)
2087 obj
.ipfo_rev
= IPFILTER_VERSION
;
2088 obj
.ipfo_type
= IPFOBJ_GENITER
;
2089 obj
.ipfo_size
= sizeof(frag
);
2090 obj
.ipfo_ptr
= &frag
;
2092 frag
.igi_type
= type
;
2093 frag
.igi_nitems
= 1;
2094 frag
.igi_data
= frp
;
2096 if (ioctl(fd
, SIOCGENITER
, &obj
))
2102 static void showtqtable_live(fd
)
2105 ipftq_t table
[IPF_TCP_NSTATES
];
2108 bzero((char *)&obj
, sizeof(obj
));
2109 obj
.ipfo_rev
= IPFILTER_VERSION
;
2110 obj
.ipfo_size
= sizeof(table
);
2111 obj
.ipfo_ptr
= (void *)table
;
2112 obj
.ipfo_type
= IPFOBJ_STATETQTAB
;
2114 if (ioctl(fd
, SIOCGTQTAB
, &obj
) == 0) {
2115 printtqtable(table
);