2 * Copyright (C) 1993-2001, 2003 by Darren Reed.
4 * See the IPFILTER.LICENCE file for details on licencing.
6 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
7 * Use is subject to license terms.
9 * Copyright (c) 2014, Joyent, Inc. All rights reserved.
13 # ifndef __FreeBSD_cc_version
14 # include <osreldate.h>
16 # if __FreeBSD_cc_version < 430000
17 # include <osreldate.h>
21 #include <sys/ioctl.h>
24 # include <linux/a.out.h>
29 #if defined(sun) && (defined(__svr4__) || defined(__SVR4))
33 #include "netinet/ipl.h"
35 # if defined(_BSDI_VERSION)
38 # if defined(__FreeBSD__) && \
39 (!defined(__FreeBSD_version) || (__FreeBSD_version < 430000))
42 # if defined(__NetBSD_Version__) && (__NetBSD_Version__ < 105000000)
46 # if defined(__svr4__) || defined(__SVR4)
47 # include <sys/select.h>
49 # undef STATETOP /* NOT supported on SunOS4 */
53 #if defined(STATETOP) && !defined(linux)
54 # include <netinet/ip_var.h>
55 # include <netinet/tcp_fsm.h>
60 # if defined(SOLARIS) || defined(__NetBSD__) || defined(_BSDI_VERSION) || \
73 #if defined(__NetBSD__) || (__OpenBSD__)
79 static const char sccsid
[] = "@(#)fils.c 1.21 4/20/96 (C) 1993-2000 Darren Reed";
80 static const char rcsid
[] = "@(#)$Id: ipfstat.c,v 1.44.2.12 2005/06/12 07:18:46 darrenr Exp $";
84 # define nlist nlist64
91 #define PRINTF (void)printf
92 #define FPRINTF (void)fprintf
93 static char *filters
[4] = { "ipfilter(in)", "ipfilter(out)",
94 "ipacct(in)", "ipacct(out)" };
95 static int state_logging
= -1;
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 void showstats
__P((friostat_t
*, u_32_t
));
137 static void showfrstates
__P((ipfrstat_t
*, u_long
));
138 static void showlist
__P((friostat_t
*));
139 static void showipstates
__P((ips_stat_t
*));
140 static void showauthstates
__P((fr_authstat_t
*));
141 static void showgroups
__P((friostat_t
*));
142 static void usage
__P((char *));
143 static void printlivelist
__P((int, int, frentry_t
*, char *, char *));
144 static void printdeadlist
__P((int, int, frentry_t
*, char *, char *));
145 static void printlist
__P((frentry_t
*, char *));
146 static void parse_ipportstr
__P((const char *, i6addr_t
*, int *));
147 static void ipfstate_live
__P((char *, friostat_t
**, ips_stat_t
**,
148 ipfrstat_t
**, fr_authstat_t
**, u_32_t
*));
149 static void ipfstate_dead
__P((char *, friostat_t
**, ips_stat_t
**,
150 ipfrstat_t
**, fr_authstat_t
**, u_32_t
*));
152 static void topipstates
__P((i6addr_t
, i6addr_t
, int, int, int,
154 static void sig_break
__P((int));
155 static void sig_resize
__P((int));
156 static char *getip
__P((int, i6addr_t
*));
157 static char *ttl_to_string
__P((long));
158 static int sort_p
__P((const void *, const void *));
159 static int sort_pkts
__P((const void *, const void *));
160 static int sort_bytes
__P((const void *, const void *));
161 static int sort_ttl
__P((const void *, const void *));
162 static int sort_srcip
__P((const void *, const void *));
163 static int sort_srcpt
__P((const void *, const void *));
164 static int sort_dstip
__P((const void *, const void *));
165 static int sort_dstpt
__P((const void *, const void *));
169 static void usage(name
)
173 fprintf(stderr
, "Usage: %s [-6aAdfghIilnoRsv]\n", name
);
175 fprintf(stderr
, "Usage: %s [-aAdfghIilnoRsv]\n", name
);
177 fprintf(stderr
, " %s [-M corefile] [-N symbol-list]\n", name
);
179 fprintf(stderr
, " %s -t [-6C] ", name
);
181 fprintf(stderr
, " %s -t [-C] ", name
);
183 fprintf(stderr
, "[-G|-z zonename] ");
184 fprintf(stderr
, "[-D destination address] [-P protocol] [-S source address] [-T refresh time]\n");
193 fr_authstat_t frauthst
;
194 fr_authstat_t
*frauthstp
= &frauthst
;
196 friostat_t
*fiop
= &fio
;
198 ips_stat_t
*ipsstp
= &ipsst
;
200 ipfrstat_t
*ifrstp
= &ifrst
;
201 char *device
= IPL_NAME
, *memf
= NULL
;
202 char *options
, *kern
= NULL
;
205 int protocol
= -1; /* -1 = wild card for any protocol */
206 int refreshtime
= 1; /* default update time */
207 int sport
= -1; /* -1 = wild card for any source port */
208 int dport
= -1; /* -1 = wild card for any dest port */
209 int topclosed
= 0; /* do not show closed tcp sessions */
210 i6addr_t saddr
, daddr
;
214 options
= "6aACdfgG:hIilnostvD:M:N:P:RS:T:z:";
216 options
= "aACdfgG:hIilnostvD:M:N:P:RS:T:z:";
219 saddr
.in4
.s_addr
= INADDR_ANY
; /* default any v4 source addr */
220 daddr
.in4
.s_addr
= INADDR_ANY
; /* default any v4 dest addr */
222 saddr
.in6
= in6addr_any
; /* default any v6 source addr */
223 daddr
.in6
= in6addr_any
; /* default any v6 dest addr */
226 /* Don't warn about invalid flags when we run getopt for the 1st time */
230 * Parse these four arguments now lest there be any buffer overflows
231 * in the parsing of the rest.
234 while ((c
= getopt(argc
, argv
, options
)) != -1) {
238 setzonename_global(optarg
);
255 if (live_kernel
== 1) {
256 if ((state_fd
= open(IPSTATE_NAME
, O_RDONLY
)) == -1) {
257 perror("open(IPSTATE_NAME)");
261 if (setzone(state_fd
) != 0) {
266 if ((ipf_fd
= open(device
, O_RDONLY
)) == -1) {
267 fprintf(stderr
, "open(%s)", device
);
272 if (setzone(ipf_fd
) != 0) {
278 if (kern
!= NULL
|| memf
!= NULL
) {
279 (void)setgid(getgid());
280 (void)setreuid(getuid(), getuid());
281 if (openkmem(kern
, memf
) == -1)
285 if (live_kernel
== 1)
286 (void) checkrev(device
);
287 (void)setgid(getgid());
288 (void)setreuid(getuid(), getuid());
292 while ((c
= getopt(argc
, argv
, options
)) != -1)
302 opts
|= OPT_ACCNT
|OPT_SHOWLIST
;
305 opts
|= OPT_AUTHSTATS
;
314 parse_ipportstr(optarg
, &daddr
, &dport
);
317 opts
|= OPT_FRSTATES
;
323 /* Already handled by getzoneopt() above */
329 opts
|= OPT_INQUE
|OPT_SHOWLIST
;
332 opts
|= OPT_INACTIVE
;
335 opts
|= OPT_SHOWLIST
;
342 opts
|= OPT_SHOWLINENO
;
345 opts
|= OPT_OUTQUE
|OPT_SHOWLIST
;
348 protocol
= getproto(optarg
);
349 if (protocol
== -1) {
350 fprintf(stderr
, "%s: Invalid protocol: %s\n",
356 opts
|= OPT_NORESOLVE
;
359 opts
|= OPT_IPSTATES
;
362 parse_ipportstr(optarg
, &saddr
, &sport
);
366 opts
|= OPT_STATETOP
;
370 "%s: state top facility not compiled in\n",
375 if (!sscanf(optarg
, "%d", &refreshtime
) ||
376 (refreshtime
<= 0)) {
378 "%s: Invalid refreshtime < 1 : %s\n",
388 /* Already handled by getzoneopt() above */
396 if (live_kernel
== 1) {
397 bzero((char *)&fio
, sizeof(fio
));
398 bzero((char *)&ipsst
, sizeof(ipsst
));
399 bzero((char *)&ifrst
, sizeof(ifrst
));
401 ipfstate_live(device
, &fiop
, &ipsstp
, &ifrstp
,
404 ipfstate_dead(kern
, &fiop
, &ipsstp
, &ifrstp
, &frauthstp
, &frf
);
406 if (opts
& OPT_IPSTATES
) {
407 showipstates(ipsstp
);
408 } else if (opts
& OPT_SHOWLIST
) {
410 if ((opts
& OPT_OUTQUE
) && (opts
& OPT_INQUE
)){
414 } else if (opts
& OPT_FRSTATES
)
415 showfrstates(ifrstp
, fiop
->f_ticks
);
417 else if (opts
& OPT_STATETOP
)
418 topipstates(saddr
, daddr
, sport
, dport
, protocol
,
419 use_inet6
? 6 : 4, refreshtime
, topclosed
);
421 else if (opts
& OPT_AUTHSTATS
)
422 showauthstates(frauthstp
);
423 else if (opts
& OPT_GROUPS
)
426 showstats(fiop
, frf
);
433 * Fill in the stats structures from the live kernel, using a combination
434 * of ioctl's and copying directly from kernel memory.
436 static void ipfstate_live(device
, fiopp
, ipsstpp
, ifrstpp
, frauthstpp
, frfp
)
439 ips_stat_t
**ipsstpp
;
440 ipfrstat_t
**ifrstpp
;
441 fr_authstat_t
**frauthstpp
;
446 if (checkrev(device
) == -1) {
447 fprintf(stderr
, "User/kernel version check failed\n");
451 if ((opts
& OPT_AUTHSTATS
) == 0) {
452 bzero((caddr_t
)&ipfo
, sizeof(ipfo
));
453 ipfo
.ipfo_rev
= IPFILTER_VERSION
;
454 ipfo
.ipfo_size
= sizeof(friostat_t
);
455 ipfo
.ipfo_ptr
= (void *)*fiopp
;
456 ipfo
.ipfo_type
= IPFOBJ_IPFSTAT
;
458 if (ioctl(ipf_fd
, SIOCGETFS
, &ipfo
) == -1) {
459 perror("ioctl(ipf:SIOCGETFS)");
463 if (ioctl(ipf_fd
, SIOCGETFF
, frfp
) == -1)
464 perror("ioctl(SIOCGETFF)");
467 if ((opts
& OPT_IPSTATES
) != 0) {
469 bzero((caddr_t
)&ipfo
, sizeof(ipfo
));
470 ipfo
.ipfo_rev
= IPFILTER_VERSION
;
471 ipfo
.ipfo_size
= sizeof(ips_stat_t
);
472 ipfo
.ipfo_ptr
= (void *)*ipsstpp
;
473 ipfo
.ipfo_type
= IPFOBJ_STATESTAT
;
475 if ((ioctl(state_fd
, SIOCGETFS
, &ipfo
) == -1)) {
476 perror("ioctl(state:SIOCGETFS)");
479 if (ioctl(state_fd
, SIOCGETLG
, &state_logging
) == -1) {
480 perror("ioctl(state:SIOCGETLG)");
485 if ((opts
& OPT_FRSTATES
) != 0) {
486 bzero((caddr_t
)&ipfo
, sizeof(ipfo
));
487 ipfo
.ipfo_rev
= IPFILTER_VERSION
;
488 ipfo
.ipfo_size
= sizeof(ipfrstat_t
);
489 ipfo
.ipfo_ptr
= (void *)*ifrstpp
;
490 ipfo
.ipfo_type
= IPFOBJ_FRAGSTAT
;
492 if (ioctl(ipf_fd
, SIOCGFRST
, &ipfo
) == -1) {
493 perror("ioctl(SIOCGFRST)");
498 if (opts
& OPT_VERBOSE
)
499 PRINTF("opts %#x name %s\n", opts
, device
);
501 if ((opts
& OPT_AUTHSTATS
) != 0) {
506 device
= IPAUTH_NAME
;
507 if ((ipf_fd
= open(device
, O_RDONLY
)) == -1) {
512 if (setzone(ipf_fd
) != 0) {
517 bzero((caddr_t
)&ipfo
, sizeof(ipfo
));
518 ipfo
.ipfo_rev
= IPFILTER_VERSION
;
519 ipfo
.ipfo_size
= sizeof(fr_authstat_t
);
520 ipfo
.ipfo_ptr
= (void *)*frauthstpp
;
521 ipfo
.ipfo_type
= IPFOBJ_AUTHSTAT
;
523 if (ioctl(ipf_fd
, SIOCATHST
, &ipfo
) == -1) {
524 perror("ioctl(SIOCATHST)");
532 * Build up the stats structures from data held in the "core" memory.
533 * This is mainly useful when looking at data in crash dumps and ioctl's
534 * just won't work any more.
536 static void ipfstate_dead(kernel
, fiopp
, ipsstpp
, ifrstpp
, frauthstpp
, frfp
)
539 ips_stat_t
**ipsstpp
;
540 ipfrstat_t
**ifrstpp
;
541 fr_authstat_t
**frauthstpp
;
544 static fr_authstat_t frauthst
, *frauthstp
;
545 static ips_stat_t ipsst
, *ipsstp
;
546 static ipfrstat_t ifrst
, *ifrstp
;
547 static friostat_t fio
, *fiop
;
551 struct nlist deadlist
[43] = {
552 { "fr_authstats" }, /* 0 */
557 { "fr_authend" }, /* 5 */
562 { "fr_defaultauthage" }, /* 10 */
567 { "ips_num" }, /* 15 */
572 { "fr_statesize" }, /* 20 */
573 { "fr_state_doflush" },
577 { "ipfr_stats" }, /* 25 */
582 { "fr_nat_lock" }, /* 30 */
587 { "ipl_frouteok" }, /* 35 */
592 { "fr_flags" }, /* 40 */
593 { "ipstate_logging" },
598 frauthstp
= &frauthst
;
607 *frauthstpp
= frauthstp
;
609 bzero((char *)fiop
, sizeof(*fiop
));
610 bzero((char *)ipsstp
, sizeof(*ipsstp
));
611 bzero((char *)ifrstp
, sizeof(*ifrstp
));
612 bzero((char *)frauthstp
, sizeof(*frauthstp
));
614 if (nlist(kernel
, deadlist
) == -1) {
615 fprintf(stderr
, "nlist error\n");
620 * This is for SIOCGETFF.
622 kmemcpy((char *)frfp
, (u_long
)deadlist
[40].n_value
, sizeof(*frfp
));
625 * f_locks is a combination of the lock variable from each part of
626 * ipfilter (state, auth, nat, fragments).
628 kmemcpy((char *)fiop
, (u_long
)deadlist
[13].n_value
, sizeof(*fiop
));
629 kmemcpy((char *)&fiop
->f_locks
[0], (u_long
)deadlist
[22].n_value
,
630 sizeof(fiop
->f_locks
[0]));
631 kmemcpy((char *)&fiop
->f_locks
[0], (u_long
)deadlist
[30].n_value
,
632 sizeof(fiop
->f_locks
[1]));
633 kmemcpy((char *)&fiop
->f_locks
[2], (u_long
)deadlist
[28].n_value
,
634 sizeof(fiop
->f_locks
[2]));
635 kmemcpy((char *)&fiop
->f_locks
[3], (u_long
)deadlist
[12].n_value
,
636 sizeof(fiop
->f_locks
[3]));
639 * Get pointers to each list of rules (active, inactive, in, out)
641 kmemcpy((char *)&rules
, (u_long
)deadlist
[31].n_value
, sizeof(rules
));
642 fiop
->f_fin
[0] = rules
[0][0];
643 fiop
->f_fin
[1] = rules
[0][1];
644 fiop
->f_fout
[0] = rules
[1][0];
645 fiop
->f_fout
[1] = rules
[1][1];
648 * Same for IPv6, except make them null if support for it is not
652 kmemcpy((char *)&rules
, (u_long
)deadlist
[32].n_value
, sizeof(rules
));
653 fiop
->f_fin6
[0] = rules
[0][0];
654 fiop
->f_fin6
[1] = rules
[0][1];
655 fiop
->f_fout6
[0] = rules
[1][0];
656 fiop
->f_fout6
[1] = rules
[1][1];
658 fiop
->f_fin6
[0] = NULL
;
659 fiop
->f_fin6
[1] = NULL
;
660 fiop
->f_fout6
[0] = NULL
;
661 fiop
->f_fout6
[1] = NULL
;
665 * Now get accounting rules pointers.
667 kmemcpy((char *)&rules
, (u_long
)deadlist
[33].n_value
, sizeof(rules
));
668 fiop
->f_acctin
[0] = rules
[0][0];
669 fiop
->f_acctin
[1] = rules
[0][1];
670 fiop
->f_acctout
[0] = rules
[1][0];
671 fiop
->f_acctout
[1] = rules
[1][1];
674 kmemcpy((char *)&rules
, (u_long
)deadlist
[34].n_value
, sizeof(rules
));
675 fiop
->f_acctin6
[0] = rules
[0][0];
676 fiop
->f_acctin6
[1] = rules
[0][1];
677 fiop
->f_acctout6
[0] = rules
[1][0];
678 fiop
->f_acctout6
[1] = rules
[1][1];
680 fiop
->f_acctin6
[0] = NULL
;
681 fiop
->f_acctin6
[1] = NULL
;
682 fiop
->f_acctout6
[0] = NULL
;
683 fiop
->f_acctout6
[1] = NULL
;
687 * A collection of "global" variables used inside the kernel which
688 * are all collected in friostat_t via ioctl.
690 kmemcpy((char *)&fiop
->f_froute
, (u_long
)deadlist
[35].n_value
,
691 sizeof(fiop
->f_froute
));
692 kmemcpy((char *)&fiop
->f_running
, (u_long
)deadlist
[36].n_value
,
693 sizeof(fiop
->f_running
));
694 kmemcpy((char *)&fiop
->f_groups
, (u_long
)deadlist
[37].n_value
,
695 sizeof(fiop
->f_groups
));
696 kmemcpy((char *)&fiop
->f_active
, (u_long
)deadlist
[38].n_value
,
697 sizeof(fiop
->f_active
));
698 kmemcpy((char *)&fiop
->f_defpass
, (u_long
)deadlist
[39].n_value
,
699 sizeof(fiop
->f_defpass
));
702 * Build up the state information stats structure.
704 kmemcpy((char *)ipsstp
, (u_long
)deadlist
[14].n_value
, sizeof(*ipsstp
));
705 kmemcpy((char *)&temp
, (u_long
)deadlist
[15].n_value
, sizeof(temp
));
706 ipsstp
->iss_active
= temp
;
707 ipsstp
->iss_table
= (void *)deadlist
[18].n_value
;
708 ipsstp
->iss_list
= (void *)deadlist
[17].n_value
;
711 * Build up the authentiation information stats structure.
713 kmemcpy((char *)frauthstp
, (u_long
)deadlist
[0].n_value
,
715 frauthstp
->fas_faelist
= (void *)deadlist
[1].n_value
;
718 * Build up the fragment information stats structure.
720 kmemcpy((char *)ifrstp
, (u_long
)deadlist
[25].n_value
,
722 ifrstp
->ifs_table
= (void *)deadlist
[23].n_value
;
723 ifrstp
->ifs_nattab
= (void *)deadlist
[24].n_value
;
724 kmemcpy((char *)&ifrstp
->ifs_inuse
, (u_long
)deadlist
[26].n_value
,
725 sizeof(ifrstp
->ifs_inuse
));
728 * Get logging on/off switches
730 kmemcpy((char *)&state_logging
, (u_long
)deadlist
[41].n_value
,
731 sizeof(state_logging
));
736 * Display the kernel stats for packets blocked and passed and other
737 * associated running totals which are kept.
739 static void showstats(fp
, frf
)
744 PRINTF("bad packets:\t\tin %lu\tout %lu\n",
745 fp
->f_st
[0].fr_bad
, fp
->f_st
[1].fr_bad
);
747 PRINTF(" IPv6 packets:\t\tin %lu out %lu\n",
748 fp
->f_st
[0].fr_ipv6
, fp
->f_st
[1].fr_ipv6
);
750 PRINTF(" input packets:\t\tblocked %lu passed %lu nomatch %lu",
751 fp
->f_st
[0].fr_block
, fp
->f_st
[0].fr_pass
,
753 PRINTF(" counted %lu short %lu\n",
754 fp
->f_st
[0].fr_acct
, fp
->f_st
[0].fr_short
);
755 PRINTF("output packets:\t\tblocked %lu passed %lu nomatch %lu",
756 fp
->f_st
[1].fr_block
, fp
->f_st
[1].fr_pass
,
758 PRINTF(" counted %lu short %lu\n",
759 fp
->f_st
[1].fr_acct
, fp
->f_st
[1].fr_short
);
760 PRINTF(" input packets logged:\tblocked %lu passed %lu\n",
761 fp
->f_st
[0].fr_bpkl
, fp
->f_st
[0].fr_ppkl
);
762 PRINTF("output packets logged:\tblocked %lu passed %lu\n",
763 fp
->f_st
[1].fr_bpkl
, fp
->f_st
[1].fr_ppkl
);
764 PRINTF(" packets logged:\tinput %lu output %lu\n",
765 fp
->f_st
[0].fr_pkl
, fp
->f_st
[1].fr_pkl
);
766 PRINTF(" log failures:\t\tinput %lu output %lu\n",
767 fp
->f_st
[0].fr_skip
, fp
->f_st
[1].fr_skip
);
768 PRINTF("fragment state(in):\tkept %lu\tlost %lu\tnot fragmented %lu\n",
769 fp
->f_st
[0].fr_nfr
, fp
->f_st
[0].fr_bnfr
,
771 PRINTF("fragment state(out):\tkept %lu\tlost %lu\tnot fragmented %lu\n",
772 fp
->f_st
[1].fr_nfr
, fp
->f_st
[1].fr_bnfr
,
774 PRINTF("packet state(in):\tkept %lu\tlost %lu\n",
775 fp
->f_st
[0].fr_ads
, fp
->f_st
[0].fr_bads
);
776 PRINTF("packet state(out):\tkept %lu\tlost %lu\n",
777 fp
->f_st
[1].fr_ads
, fp
->f_st
[1].fr_bads
);
778 PRINTF("ICMP replies:\t%lu\tTCP RSTs sent:\t%lu\n",
779 fp
->f_st
[0].fr_ret
, fp
->f_st
[1].fr_ret
);
780 PRINTF("Invalid source(in):\t%lu\n", fp
->f_st
[0].fr_badsrc
);
781 PRINTF("Result cache hits(in):\t%lu\t(out):\t%lu\n",
782 fp
->f_st
[0].fr_chit
, fp
->f_st
[1].fr_chit
);
783 PRINTF("IN Pullups succeeded:\t%lu\tfailed:\t%lu\n",
784 fp
->f_st
[0].fr_pull
[0], fp
->f_st
[0].fr_pull
[1]);
785 PRINTF("OUT Pullups succeeded:\t%lu\tfailed:\t%lu\n",
786 fp
->f_st
[1].fr_pull
[0], fp
->f_st
[1].fr_pull
[1]);
787 PRINTF("Fastroute successes:\t%lu\tfailures:\t%lu\n",
788 fp
->f_froute
[0], fp
->f_froute
[1]);
789 PRINTF("TCP cksum fails(in):\t%lu\t(out):\t%lu\n",
790 fp
->f_st
[0].fr_tcpbad
, fp
->f_st
[1].fr_tcpbad
);
791 PRINTF("IPF Ticks:\t%lu\n", fp
->f_ticks
);
793 PRINTF("Packet log flags set: (%#x)\n", frf
);
794 if (frf
& FF_LOGPASS
)
795 PRINTF("\tpackets passed through filter\n");
796 if (frf
& FF_LOGBLOCK
)
797 PRINTF("\tpackets blocked by filter\n");
798 if (frf
& FF_LOGNOMATCH
)
799 PRINTF("\tpackets not matched by filter\n");
806 * Print out a list of rules from the kernel, starting at the one passed.
808 static void printlivelist(out
, set
, fp
, group
, comment
)
811 char *group
, *comment
;
813 frgroup_t
*grtop
, *grtail
, *g
;
814 struct frentry fb
, *fg
;
824 rule
.iri_ver
= use_inet6
? AF_INET6
: AF_INET
;
825 rule
.iri_inout
= out
;
826 rule
.iri_active
= set
;
830 strncpy(rule
.iri_group
, group
, FR_GROUPLEN
);
832 rule
.iri_group
[0] = '\0';
834 bzero((char *)&obj
, sizeof(obj
));
835 obj
.ipfo_rev
= IPFILTER_VERSION
;
836 obj
.ipfo_type
= IPFOBJ_IPFITER
;
837 obj
.ipfo_size
= sizeof(rule
);
838 obj
.ipfo_ptr
= &rule
;
843 memset(array
, 0xff, sizeof(array
));
844 fp
= (frentry_t
*)array
;
846 if (ioctl(ipf_fd
, SIOCIPFITER
, &obj
) == -1) {
847 perror("ioctl(SIOCIPFITER)");
850 if (fp
->fr_data
!= NULL
)
851 fp
->fr_data
= (char *)fp
+ sizeof(*fp
);
855 if (opts
& (OPT_HITS
|OPT_VERBOSE
))
857 PRINTF("%qu ", (unsigned long long) fp
->fr_hits
);
859 PRINTF("%lu ", fp
->fr_hits
);
861 if (opts
& (OPT_ACCNT
|OPT_VERBOSE
))
863 PRINTF("%qu ", (unsigned long long) fp
->fr_bytes
);
865 PRINTF("%lu ", fp
->fr_bytes
);
867 if (opts
& OPT_SHOWLINENO
)
871 if (opts
& OPT_DEBUG
) {
872 binprint(fp
, sizeof(*fp
));
873 if (fp
->fr_data
!= NULL
&& fp
->fr_dsize
> 0)
874 binprint(fp
->fr_data
, fp
->fr_dsize
);
877 if (fp
->fr_grhead
[0] != '\0') {
878 g
= calloc(1, sizeof(*g
));
881 strncpy(g
->fg_name
, fp
->fr_grhead
,
892 } while (fp
->fr_next
!= NULL
);
894 while ((g
= grtop
) != NULL
) {
895 printlivelist(out
, set
, NULL
, g
->fg_name
, comment
);
902 static void printdeadlist(out
, set
, fp
, group
, comment
)
905 char *group
, *comment
;
907 frgroup_t
*grtop
, *grtail
, *g
;
908 struct frentry fb
, *fg
;
920 if (kmemcpy((char *)&fb
, (u_long
)fb
.fr_next
,
927 type
= fb
.fr_type
& ~FR_T_BUILTIN
;
928 if (type
== FR_T_IPF
|| type
== FR_T_BPFOPC
) {
930 data
= malloc(fb
.fr_dsize
);
932 if (kmemcpy(data
, (u_long
)fb
.fr_data
,
933 fb
.fr_dsize
) == -1) {
943 if (opts
& (OPT_HITS
|OPT_VERBOSE
))
945 PRINTF("%qu ", (unsigned long long) fb
.fr_hits
);
947 PRINTF("%lu ", fb
.fr_hits
);
949 if (opts
& (OPT_ACCNT
|OPT_VERBOSE
))
951 PRINTF("%qu ", (unsigned long long) fb
.fr_bytes
);
953 PRINTF("%lu ", fb
.fr_bytes
);
955 if (opts
& OPT_SHOWLINENO
)
959 if (opts
& OPT_DEBUG
) {
960 binprint(fp
, sizeof(*fp
));
961 if (fb
.fr_data
!= NULL
&& fb
.fr_dsize
> 0)
962 binprint(fb
.fr_data
, fb
.fr_dsize
);
966 if (fb
.fr_grhead
[0] != '\0') {
967 g
= calloc(1, sizeof(*g
));
970 strncpy(g
->fg_name
, fb
.fr_grhead
,
981 if (type
== FR_T_CALLFUNC
) {
982 printdeadlist(out
, set
, fb
.fr_data
, group
,
985 } while (fb
.fr_next
!= NULL
);
987 while ((g
= grtop
) != NULL
) {
988 printdeadlist(out
, set
, NULL
, g
->fg_name
, comment
);
996 * print out all of the asked for rule sets, using the stats struct as
997 * the base from which to get the pointers.
999 static void showlist(fiop
)
1000 struct friostat
*fiop
;
1002 struct frentry
*fp
= NULL
;
1005 set
= fiop
->f_active
;
1006 if (opts
& OPT_INACTIVE
)
1008 if (opts
& OPT_ACCNT
) {
1010 if ((use_inet6
) && (opts
& OPT_OUTQUE
)) {
1012 fp
= (struct frentry
*)fiop
->f_acctout6
[set
];
1013 } else if ((use_inet6
) && (opts
& OPT_INQUE
)) {
1015 fp
= (struct frentry
*)fiop
->f_acctin6
[set
];
1018 if (opts
& OPT_OUTQUE
) {
1020 fp
= (struct frentry
*)fiop
->f_acctout
[set
];
1021 } else if (opts
& OPT_INQUE
) {
1023 fp
= (struct frentry
*)fiop
->f_acctin
[set
];
1025 FPRINTF(stderr
, "No -i or -o given with -a\n");
1030 if ((use_inet6
) && (opts
& OPT_OUTQUE
)) {
1032 fp
= (struct frentry
*)fiop
->f_fout6
[set
];
1033 } else if ((use_inet6
) && (opts
& OPT_INQUE
)) {
1035 fp
= (struct frentry
*)fiop
->f_fin6
[set
];
1038 if (opts
& OPT_OUTQUE
) {
1040 fp
= (struct frentry
*)fiop
->f_fout
[set
];
1041 } else if (opts
& OPT_INQUE
) {
1043 fp
= (struct frentry
*)fiop
->f_fin
[set
];
1047 if (opts
& OPT_VERBOSE
)
1048 FPRINTF(stderr
, "showlist:opts %#x i %d\n", opts
, i
);
1050 if (opts
& OPT_VERBOSE
)
1051 PRINTF("fp %p set %d\n", fp
, set
);
1053 FPRINTF(stderr
, "empty list for %s%s\n",
1054 (opts
& OPT_INACTIVE
) ? "inactive " : "", filters
[i
]);
1057 if (live_kernel
== 1)
1058 printlivelist(i
, set
, fp
, NULL
, NULL
);
1060 printdeadlist(i
, set
, fp
, NULL
, NULL
);
1065 * Display ipfilter stateful filtering information
1067 static void showipstates(ipsp
)
1070 u_long minlen
, maxlen
, totallen
, *buckets
;
1073 sz
= sizeof(*buckets
) * ipsp
->iss_statesize
;
1074 buckets
= (u_long
*)malloc(sz
);
1075 if (buckets
== NULL
) {
1079 if (kmemcpy((char *)buckets
, (u_long
)ipsp
->iss_bucketlen
, sz
)) {
1085 * If a list of states hasn't been asked for, only print out stats
1087 if (!(opts
& OPT_SHOWLIST
)) {
1088 PRINTF("IP states added:\n\t%lu TCP\n\t%lu UDP\n\t%lu ICMP\n",
1089 ipsp
->iss_tcp
, ipsp
->iss_udp
, ipsp
->iss_icmp
);
1090 PRINTF("\t%lu hits\n\t%lu misses\n",
1091 ipsp
->iss_hits
, ipsp
->iss_miss
);
1092 PRINTF("\t%lu maximum\n\t%lu no memory\n", ipsp
->iss_max
,
1094 PRINTF("\t%lu active\n\t%lu expired\n",
1095 ipsp
->iss_active
, ipsp
->iss_expire
);
1096 PRINTF("\t%lu closed\n\t%u orphans\n",
1097 ipsp
->iss_fin
, ipsp
->iss_orphans
);
1099 PRINTF("State logging %sabled\n",
1100 state_logging
? "en" : "dis");
1102 PRINTF("\nState table bucket statistics:\n");
1103 PRINTF("\t%lu in use\n\t%lu max bucket\n", ipsp
->iss_inuse
,
1104 ipsp
->iss_bucketfull
);
1106 minlen
= ipsp
->iss_max
;
1110 for (i
= 0; i
< ipsp
->iss_statesize
; i
++) {
1111 if (buckets
[i
] > maxlen
)
1112 maxlen
= buckets
[i
];
1113 if (buckets
[i
] < minlen
)
1114 minlen
= buckets
[i
];
1115 totallen
+= buckets
[i
];
1118 PRINTF("\t%2.2f%% bucket usage\n\t%lu minimal length\n",
1119 ((float)ipsp
->iss_inuse
/ ipsp
->iss_statesize
) * 100.0,
1121 PRINTF("\t%lu maximal length\n\t%.3f average length\n",
1123 ipsp
->iss_inuse
? (float) totallen
/ ipsp
->iss_inuse
:
1126 #define ENTRIES_PER_LINE 5
1128 if (opts
& OPT_VERBOSE
) {
1129 PRINTF("\nCurrent bucket sizes :\n");
1130 for (i
= 0; i
< ipsp
->iss_statesize
; i
++) {
1131 if ((i
% ENTRIES_PER_LINE
) == 0)
1133 PRINTF("%4d -> %4lu", i
, buckets
[i
]);
1134 if ((i
% ENTRIES_PER_LINE
) ==
1135 (ENTRIES_PER_LINE
- 1))
1149 * Print out all the state information currently held in the kernel.
1151 while (ipsp
->iss_list
!= NULL
) {
1152 ipsp
->iss_list
= printstate(ipsp
->iss_list
, opts
,
1161 static int handle_resize
= 0, handle_break
= 0;
1163 static void topipstates(saddr
, daddr
, sport
, dport
, protocol
, ver
,
1164 refreshtime
, topclosed
)
1174 char str1
[STSTRSIZE
], str2
[STSTRSIZE
], str3
[STSTRSIZE
], str4
[STSTRSIZE
];
1175 int maxtsentries
= 0, reverse
= 0, sorting
= STSORT_DEFAULT
;
1176 int i
, j
, winy
, tsentry
, maxx
, maxy
, redraw
= 0, ret
= 0;
1177 int len
, srclen
, dstlen
, forward
= 1, c
= 0;
1178 ips_stat_t ipsst
, *ipsstp
= &ipsst
;
1179 statetop_t
*tstable
= NULL
, *tp
;
1180 const char *errstr
= "";
1183 struct timeval selecttimeout
;
1184 char hostnm
[HOSTNMLEN
];
1185 struct protoent
*proto
;
1189 /* install signal handlers */
1190 signal(SIGINT
, sig_break
);
1191 signal(SIGQUIT
, sig_break
);
1192 signal(SIGTERM
, sig_break
);
1193 signal(SIGWINCH
, sig_resize
);
1195 /* init ncurses stuff */
1201 getmaxyx(stdscr
, maxy
, maxx
);
1204 gethostname(hostnm
, sizeof(hostnm
) - 1);
1205 hostnm
[sizeof(hostnm
) - 1] = '\0';
1207 /* init ipfobj_t stuff */
1208 bzero((caddr_t
)&ipfo
, sizeof(ipfo
));
1209 ipfo
.ipfo_rev
= IPFILTER_VERSION
;
1210 ipfo
.ipfo_size
= sizeof(*ipsstp
);
1211 ipfo
.ipfo_ptr
= (void *)ipsstp
;
1212 ipfo
.ipfo_type
= IPFOBJ_STATESTAT
;
1214 /* repeat until user aborts */
1217 /* get state table */
1218 bzero((char *)&ipsst
, sizeof(ipsst
));
1219 if ((ioctl(state_fd
, SIOCGETFS
, &ipfo
) == -1)) {
1220 errstr
= "ioctl(SIOCGETFS)";
1225 /* clear the history */
1228 /* reset max str len */
1229 srclen
= dstlen
= 0;
1231 /* read the state table and store in tstable */
1232 for (; ipsstp
->iss_list
; ipsstp
->iss_list
= ips
.is_next
) {
1234 if (kmemcpy((char *)&ips
, (u_long
)ipsstp
->iss_list
,
1238 if (ips
.is_v
!= ver
)
1241 /* check v4 src/dest addresses */
1242 if (ips
.is_v
== 4) {
1243 if ((saddr
.in4
.s_addr
!= INADDR_ANY
&&
1244 saddr
.in4
.s_addr
!= ips
.is_saddr
) ||
1245 (daddr
.in4
.s_addr
!= INADDR_ANY
&&
1246 daddr
.in4
.s_addr
!= ips
.is_daddr
))
1250 /* check v6 src/dest addresses */
1251 if (ips
.is_v
== 6) {
1252 if ((IP6_NEQ(&saddr
, &in6addr_any
) &&
1253 IP6_NEQ(&saddr
, &ips
.is_src
)) ||
1254 (IP6_NEQ(&daddr
, &in6addr_any
) &&
1255 IP6_NEQ(&daddr
, &ips
.is_dst
)))
1259 /* check protocol */
1260 if (protocol
> 0 && protocol
!= ips
.is_p
)
1263 /* check ports if protocol is TCP or UDP */
1264 if (((ips
.is_p
== IPPROTO_TCP
) ||
1265 (ips
.is_p
== IPPROTO_UDP
)) &&
1266 (((sport
> 0) && (htons(sport
) != ips
.is_sport
)) ||
1267 ((dport
> 0) && (htons(dport
) != ips
.is_dport
))))
1270 /* show closed TCP sessions ? */
1271 if ((topclosed
== 0) && (ips
.is_p
== IPPROTO_TCP
) &&
1272 (ips
.is_state
[0] >= IPF_TCPS_LAST_ACK
) &&
1273 (ips
.is_state
[1] >= IPF_TCPS_LAST_ACK
))
1277 * if necessary make room for this state
1281 if (!maxtsentries
|| tsentry
== maxtsentries
) {
1282 maxtsentries
+= STGROWSIZE
;
1283 tstable
= realloc(tstable
,
1284 maxtsentries
* sizeof(statetop_t
));
1285 if (tstable
== NULL
) {
1291 /* get max src/dest address string length */
1292 len
= strlen(getip(ips
.is_v
, &ips
.is_src
));
1295 len
= strlen(getip(ips
.is_v
, &ips
.is_dst
));
1299 /* fill structure */
1300 tp
= tstable
+ tsentry
;
1301 tp
->st_src
= ips
.is_src
;
1302 tp
->st_dst
= ips
.is_dst
;
1303 tp
->st_p
= ips
.is_p
;
1304 tp
->st_v
= ips
.is_v
;
1305 tp
->st_state
[0] = ips
.is_state
[0];
1306 tp
->st_state
[1] = ips
.is_state
[1];
1308 tp
->st_pkts
= ips
.is_pkts
[0]+ips
.is_pkts
[1];
1309 tp
->st_bytes
= ips
.is_bytes
[0]+ips
.is_bytes
[1];
1311 tp
->st_pkts
= ips
.is_pkts
[2]+ips
.is_pkts
[3];
1312 tp
->st_bytes
= ips
.is_bytes
[2]+ips
.is_bytes
[3];
1314 tp
->st_age
= ips
.is_die
- ipsstp
->iss_ticks
;
1315 if ((ips
.is_p
== IPPROTO_TCP
) ||
1316 (ips
.is_p
== IPPROTO_UDP
)) {
1317 tp
->st_sport
= ips
.is_sport
;
1318 tp
->st_dport
= ips
.is_dport
;
1323 /* sort the array */
1324 if (tsentry
!= -1) {
1328 qsort(tstable
, tsentry
+ 1,
1329 sizeof(statetop_t
), sort_p
);
1332 qsort(tstable
, tsentry
+ 1,
1333 sizeof(statetop_t
), sort_pkts
);
1336 qsort(tstable
, tsentry
+ 1,
1337 sizeof(statetop_t
), sort_bytes
);
1340 qsort(tstable
, tsentry
+ 1,
1341 sizeof(statetop_t
), sort_ttl
);
1344 qsort(tstable
, tsentry
+ 1,
1345 sizeof(statetop_t
), sort_srcip
);
1348 qsort(tstable
, tsentry
+1,
1349 sizeof(statetop_t
), sort_srcpt
);
1352 qsort(tstable
, tsentry
+ 1,
1353 sizeof(statetop_t
), sort_dstip
);
1356 qsort(tstable
, tsentry
+ 1,
1357 sizeof(statetop_t
), sort_dstpt
);
1364 /* handle window resizes */
1365 if (handle_resize
) {
1372 getmaxyx(stdscr
, maxy
, maxx
);
1386 sprintf(str1
, "%s - %s - state top", hostnm
, IPL_VERSION
);
1387 for (j
= 0 ; j
< (maxx
- 8 - strlen(str1
)) / 2; j
++)
1392 /* just for fun add a clock */
1393 move(winy
, maxx
- 8);
1395 strftime(str1
, 80, "%T", localtime(&t
));
1396 printw("%s\n", str1
);
1399 * print the display filters, this is placed in the loop,
1400 * because someday I might add code for changing these
1401 * while the programming is running :-)
1404 sprintf(str1
, "%s,%d", getip(ver
, &saddr
), sport
);
1406 sprintf(str1
, "%s", getip(ver
, &saddr
));
1409 sprintf(str2
, "%s,%d", getip(ver
, &daddr
), dport
);
1411 sprintf(str2
, "%s", getip(ver
, &daddr
));
1414 strcpy(str3
, "any");
1415 else if ((proto
= getprotobynumber(protocol
)) != NULL
)
1416 sprintf(str3
, "%s", proto
->p_name
);
1418 sprintf(str3
, "%d", protocol
);
1423 sprintf(str4
, "proto");
1426 sprintf(str4
, "# pkts");
1429 sprintf(str4
, "# bytes");
1432 sprintf(str4
, "ttl");
1435 sprintf(str4
, "src ip");
1438 sprintf(str4
, "src port");
1441 sprintf(str4
, "dest ip");
1444 sprintf(str4
, "dest port");
1447 sprintf(str4
, "unknown");
1452 strcat(str4
, " (reverse)");
1456 printw("Src: %s, Dest: %s, Proto: %s, Sorted by: %s\n\n",
1457 str1
, str2
, str3
, str4
);
1460 * For an IPv4 IP address we need at most 15 characters,
1461 * 4 tuples of 3 digits, separated by 3 dots. Enforce this
1462 * length, so the colums do not change positions based
1463 * on the size of the IP address. This length makes the
1464 * output fit in a 80 column terminal.
1465 * We are lacking a good solution for IPv6 addresses (that
1466 * can be longer that 15 characters), so we do not enforce
1467 * a maximum on the IP field size.
1474 /* print column description */
1478 printw("%-*s %-*s %3s %4s %7s %9s %9s\n",
1479 srclen
+ 6, "Source IP", dstlen
+ 6, "Destination IP",
1480 "ST", "PR", "#pkts", "#bytes", "ttl");
1483 /* print all the entries */
1488 if (tsentry
> maxy
- 6)
1490 for (i
= 0; i
<= tsentry
; i
++) {
1491 /* print src/dest and port */
1492 if ((tp
->st_p
== IPPROTO_TCP
) ||
1493 (tp
->st_p
== IPPROTO_UDP
)) {
1494 sprintf(str1
, "%s,%hu",
1495 getip(tp
->st_v
, &tp
->st_src
),
1496 ntohs(tp
->st_sport
));
1497 sprintf(str2
, "%s,%hu",
1498 getip(tp
->st_v
, &tp
->st_dst
),
1499 ntohs(tp
->st_dport
));
1501 sprintf(str1
, "%s", getip(tp
->st_v
,
1503 sprintf(str2
, "%s", getip(tp
->st_v
,
1508 printw("%-*s %-*s", srclen
+ 6, str1
, dstlen
+ 6, str2
);
1511 sprintf(str1
, "%X/%X", tp
->st_state
[0],
1513 printw(" %3s", str1
);
1515 /* print protocol */
1516 proto
= getprotobynumber(tp
->st_p
);
1518 strncpy(str1
, proto
->p_name
, 4);
1521 sprintf(str1
, "%d", tp
->st_p
);
1523 /* just print icmp for IPv6-ICMP */
1524 if (tp
->st_p
== IPPROTO_ICMPV6
)
1525 strcpy(str1
, "icmp");
1526 printw(" %4s", str1
);
1528 /* print #pkt/#bytes */
1530 printw(" %7qu %9qu", (unsigned long long) tp
->st_pkts
,
1531 (unsigned long long) tp
->st_bytes
);
1533 printw(" %7lu %9lu", tp
->st_pkts
, tp
->st_bytes
);
1535 printw(" %9s", ttl_to_string(tp
->st_age
));
1543 /* screen data structure is filled, now update the screen */
1547 if (refresh() == ERR
)
1554 /* wait for key press or a 1 second time out period */
1555 selecttimeout
.tv_sec
= refreshtime
;
1556 selecttimeout
.tv_usec
= 0;
1559 select(1, &readfd
, NULL
, NULL
, &selecttimeout
);
1561 /* if key pressed, read all waiting keys */
1562 if (FD_ISSET(0, &readfd
)) {
1567 if (ISALPHA(c
) && ISUPPER(c
))
1571 } else if (c
== 'q') {
1573 } else if (c
== 'r') {
1575 } else if (c
== 'b') {
1577 } else if (c
== 'f') {
1579 } else if (c
== 's') {
1580 if (++sorting
> STSORT_MAX
)
1598 * Show fragment cache information that's held in the kernel.
1600 static void showfrstates(ifsp
, ticks
)
1604 struct ipfr
*ipfrtab
[IPFT_SIZE
], ifr
;
1608 * print out the numeric statistics
1610 PRINTF("IP fragment states:\n\t%lu new\n\t%lu expired\n\t%lu hits\n",
1611 ifsp
->ifs_new
, ifsp
->ifs_expire
, ifsp
->ifs_hits
);
1612 PRINTF("\t%lu retrans\n\t%lu too short\n",
1613 ifsp
->ifs_retrans0
, ifsp
->ifs_short
);
1614 PRINTF("\t%lu no memory\n\t%lu already exist\n",
1615 ifsp
->ifs_nomem
, ifsp
->ifs_exists
);
1616 PRINTF("\t%lu inuse\n", ifsp
->ifs_inuse
);
1617 if (kmemcpy((char *)ipfrtab
, (u_long
)ifsp
->ifs_table
, sizeof(ipfrtab
)))
1621 * Print out the contents (if any) of the fragment cache table.
1624 for (i
= 0; i
< IPFT_SIZE
; i
++)
1625 while (ipfrtab
[i
] != NULL
) {
1626 if (kmemcpy((char *)&ifr
, (u_long
)ipfrtab
[i
],
1629 ifr
.ipfr_ttl
-= ticks
;
1630 printfraginfo("", &ifr
);
1631 ipfrtab
[i
] = ifr
.ipfr_next
;
1634 * Print out the contents (if any) of the NAT fragment cache table.
1636 if (kmemcpy((char *)ipfrtab
, (u_long
)ifsp
->ifs_nattab
,sizeof(ipfrtab
)))
1638 for (i
= 0; i
< IPFT_SIZE
; i
++)
1639 while (ipfrtab
[i
] != NULL
) {
1640 if (kmemcpy((char *)&ifr
, (u_long
)ipfrtab
[i
],
1643 ifr
.ipfr_ttl
-= ticks
;
1644 printfraginfo("NAT: ", &ifr
);
1645 ipfrtab
[i
] = ifr
.ipfr_next
;
1651 * Show stats on how auth within IPFilter has been used
1653 static void showauthstates(asp
)
1656 frauthent_t
*frap
, fra
;
1659 printf("Authorisation hits: %qu\tmisses %qu\n",
1660 (unsigned long long) asp
->fas_hits
,
1661 (unsigned long long) asp
->fas_miss
);
1663 printf("Authorisation hits: %ld\tmisses %ld\n", asp
->fas_hits
,
1666 printf("nospace %ld\nadded %ld\nsendfail %ld\nsendok %ld\n",
1667 asp
->fas_nospace
, asp
->fas_added
, asp
->fas_sendfail
,
1669 printf("queok %ld\nquefail %ld\nexpire %ld\n",
1670 asp
->fas_queok
, asp
->fas_quefail
, asp
->fas_expire
);
1672 frap
= asp
->fas_faelist
;
1674 if (kmemcpy((char *)&fra
, (u_long
)frap
, sizeof(fra
)) == -1)
1677 printf("age %ld\t", fra
.fae_age
);
1678 printfr(&fra
.fae_fr
, ioctl
);
1679 frap
= fra
.fae_next
;
1685 * Display groups used for each of filter rules, accounting rules and
1686 * authentication, separately.
1688 static void showgroups(fiop
)
1689 struct friostat
*fiop
;
1691 static char *gnames
[3] = { "Filter", "Accounting", "Authentication" };
1692 static int gnums
[3] = { IPL_LOGIPF
, IPL_LOGCOUNT
, IPL_LOGAUTH
};
1696 on
= fiop
->f_active
;
1699 for (i
= 0; i
< 3; i
++) {
1700 printf("%s groups (active):\n", gnames
[i
]);
1701 for (fp
= fiop
->f_groups
[gnums
[i
]][on
]; fp
!= NULL
;
1703 if (kmemcpy((char *)&grp
, (u_long
)fp
, sizeof(grp
)))
1706 printf("%s\n", grp
.fg_name
);
1707 printf("%s groups (inactive):\n", gnames
[i
]);
1708 for (fp
= fiop
->f_groups
[gnums
[i
]][off
]; fp
!= NULL
;
1710 if (kmemcpy((char *)&grp
, (u_long
)fp
, sizeof(grp
)))
1713 printf("%s\n", grp
.fg_name
);
1717 static void parse_ipportstr(argument
, ip
, port
)
1718 const char *argument
;
1725 /* make working copy of argument, Theoretically you must be able
1726 * to write to optarg, but that seems very ugly to me....
1728 s
= strdup(argument
);
1733 if ((comma
= strchr(s
, ',')) != NULL
) {
1734 if (!strcasecmp(comma
+ 1, "any")) {
1736 } else if (!sscanf(comma
+ 1, "%d", port
) ||
1737 (*port
< 0) || (*port
> 65535)) {
1738 fprintf(stderr
, "Invalid port specfication in %s\n",
1747 /* get ip address */
1748 if (!strcasecmp(s
, "any")) {
1749 ip
->in4
.s_addr
= INADDR_ANY
;
1751 ip
->in6
= in6addr_any
;
1752 } else if (use_inet6
&& inet_pton(AF_INET6
, s
, &ip
->in6
)) {
1755 } else if (inet_aton(s
, &ip
->in4
))
1759 fprintf(stderr
, "Invalid IP address: %s\n", s
);
1764 /* free allocated memory */
1770 static void sig_resize(s
)
1776 static void sig_break(s
)
1782 static char *getip(v
, addr
)
1787 static char hostbuf
[MAXHOSTNAMELEN
+1];
1791 return inet_ntoa(addr
->in4
);
1794 (void) inet_ntop(AF_INET6
, &addr
->in6
, hostbuf
, sizeof(hostbuf
) - 1);
1795 hostbuf
[MAXHOSTNAMELEN
] = '\0';
1803 static char *ttl_to_string(ttl
)
1806 static char ttlbuf
[STSTRSIZE
];
1807 int hours
, minutes
, seconds
;
1809 /* ttl is in half seconds */
1818 sprintf(ttlbuf
, "%2d:%02d:%02d", hours
, minutes
, seconds
);
1820 sprintf(ttlbuf
, "%2d:%02d", minutes
, seconds
);
1825 static int sort_pkts(a
, b
)
1830 register const statetop_t
*ap
= a
;
1831 register const statetop_t
*bp
= b
;
1833 if (ap
->st_pkts
== bp
->st_pkts
)
1835 else if (ap
->st_pkts
< bp
->st_pkts
)
1841 static int sort_bytes(a
, b
)
1845 register const statetop_t
*ap
= a
;
1846 register const statetop_t
*bp
= b
;
1848 if (ap
->st_bytes
== bp
->st_bytes
)
1850 else if (ap
->st_bytes
< bp
->st_bytes
)
1856 static int sort_p(a
, b
)
1860 register const statetop_t
*ap
= a
;
1861 register const statetop_t
*bp
= b
;
1863 if (ap
->st_p
== bp
->st_p
)
1865 else if (ap
->st_p
< bp
->st_p
)
1871 static int sort_ttl(a
, b
)
1875 register const statetop_t
*ap
= a
;
1876 register const statetop_t
*bp
= b
;
1878 if (ap
->st_age
== bp
->st_age
)
1880 else if (ap
->st_age
< bp
->st_age
)
1885 static int sort_srcip(a
, b
)
1889 register const statetop_t
*ap
= a
;
1890 register const statetop_t
*bp
= b
;
1894 if (IP6_EQ(&ap
->st_src
, &bp
->st_src
))
1896 else if (IP6_GT(&ap
->st_src
, &bp
->st_src
))
1901 if (ntohl(ap
->st_src
.in4
.s_addr
) ==
1902 ntohl(bp
->st_src
.in4
.s_addr
))
1904 else if (ntohl(ap
->st_src
.in4
.s_addr
) >
1905 ntohl(bp
->st_src
.in4
.s_addr
))
1911 static int sort_srcpt(a
, b
)
1915 register const statetop_t
*ap
= a
;
1916 register const statetop_t
*bp
= b
;
1918 if (htons(ap
->st_sport
) == htons(bp
->st_sport
))
1920 else if (htons(ap
->st_sport
) > htons(bp
->st_sport
))
1925 static int sort_dstip(a
, b
)
1929 register const statetop_t
*ap
= a
;
1930 register const statetop_t
*bp
= b
;
1934 if (IP6_EQ(&ap
->st_dst
, &bp
->st_dst
))
1936 else if (IP6_GT(&ap
->st_dst
, &bp
->st_dst
))
1941 if (ntohl(ap
->st_dst
.in4
.s_addr
) ==
1942 ntohl(bp
->st_dst
.in4
.s_addr
))
1944 else if (ntohl(ap
->st_dst
.in4
.s_addr
) >
1945 ntohl(bp
->st_dst
.in4
.s_addr
))
1951 static int sort_dstpt(a
, b
)
1955 register const statetop_t
*ap
= a
;
1956 register const statetop_t
*bp
= b
;
1958 if (htons(ap
->st_dport
) == htons(bp
->st_dport
))
1960 else if (htons(ap
->st_dport
) > htons(bp
->st_dport
))