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__)
78 static const char sccsid
[] = "@(#)fils.c 1.21 4/20/96 (C) 1993-2000 Darren Reed";
79 static const char rcsid
[] = "@(#)$Id: ipfstat.c,v 1.44.2.12 2005/06/12 07:18:46 darrenr Exp $";
82 # define nlist nlist64
89 #define PRINTF (void)printf
90 #define FPRINTF (void)fprintf
91 static char *filters
[4] = { "ipfilter(in)", "ipfilter(out)",
92 "ipacct(in)", "ipacct(out)" };
93 static int state_logging
= -1;
103 #define STGROWSIZE 16
107 #define STSORT_PKTS 1
108 #define STSORT_BYTES 2
110 #define STSORT_SRCIP 4
111 #define STSORT_SRCPT 5
112 #define STSORT_DSTIP 6
113 #define STSORT_DSTPT 7
114 #define STSORT_MAX STSORT_DSTPT
115 #define STSORT_DEFAULT STSORT_BYTES
118 typedef struct statetop
{
132 int main
__P((int, char *[]));
134 static void showstats
__P((friostat_t
*, u_32_t
));
135 static void showfrstates
__P((ipfrstat_t
*, u_long
));
136 static void showlist
__P((friostat_t
*));
137 static void showipstates
__P((ips_stat_t
*));
138 static void showauthstates
__P((fr_authstat_t
*));
139 static void showgroups
__P((friostat_t
*));
140 static void usage
__P((char *));
141 static void printlivelist
__P((int, int, frentry_t
*, char *, char *));
142 static void printdeadlist
__P((int, int, frentry_t
*, char *, char *));
143 static void printlist
__P((frentry_t
*, char *));
144 static void parse_ipportstr
__P((const char *, i6addr_t
*, int *));
145 static void ipfstate_live
__P((char *, friostat_t
**, ips_stat_t
**,
146 ipfrstat_t
**, fr_authstat_t
**, u_32_t
*));
147 static void ipfstate_dead
__P((char *, friostat_t
**, ips_stat_t
**,
148 ipfrstat_t
**, fr_authstat_t
**, u_32_t
*));
150 static void topipstates
__P((i6addr_t
, i6addr_t
, int, int, int,
152 static void sig_break
__P((int));
153 static void sig_resize
__P((int));
154 static char *getip
__P((int, i6addr_t
*));
155 static char *ttl_to_string
__P((long));
156 static int sort_p
__P((const void *, const void *));
157 static int sort_pkts
__P((const void *, const void *));
158 static int sort_bytes
__P((const void *, const void *));
159 static int sort_ttl
__P((const void *, const void *));
160 static int sort_srcip
__P((const void *, const void *));
161 static int sort_srcpt
__P((const void *, const void *));
162 static int sort_dstip
__P((const void *, const void *));
163 static int sort_dstpt
__P((const void *, const void *));
167 static void usage(name
)
171 fprintf(stderr
, "Usage: %s [-6aAdfghIilnoRsv]\n", name
);
173 fprintf(stderr
, "Usage: %s [-aAdfghIilnoRsv]\n", name
);
175 fprintf(stderr
, " %s [-M corefile] [-N symbol-list]\n", name
);
177 fprintf(stderr
, " %s -t [-6C] ", name
);
179 fprintf(stderr
, " %s -t [-C] ", name
);
181 fprintf(stderr
, "[-G|-z zonename] ");
182 fprintf(stderr
, "[-D destination address] [-P protocol] [-S source address] [-T refresh time]\n");
191 fr_authstat_t frauthst
;
192 fr_authstat_t
*frauthstp
= &frauthst
;
194 friostat_t
*fiop
= &fio
;
196 ips_stat_t
*ipsstp
= &ipsst
;
198 ipfrstat_t
*ifrstp
= &ifrst
;
199 char *device
= IPL_NAME
, *memf
= NULL
;
200 char *options
, *kern
= NULL
;
203 int protocol
= -1; /* -1 = wild card for any protocol */
204 int refreshtime
= 1; /* default update time */
205 int sport
= -1; /* -1 = wild card for any source port */
206 int dport
= -1; /* -1 = wild card for any dest port */
207 int topclosed
= 0; /* do not show closed tcp sessions */
208 i6addr_t saddr
, daddr
;
212 options
= "6aACdfgG:hIilnostvD:M:N:P:RS:T:z:";
214 options
= "aACdfgG:hIilnostvD:M:N:P:RS:T:z:";
217 saddr
.in4
.s_addr
= INADDR_ANY
; /* default any v4 source addr */
218 daddr
.in4
.s_addr
= INADDR_ANY
; /* default any v4 dest addr */
220 saddr
.in6
= in6addr_any
; /* default any v6 source addr */
221 daddr
.in6
= in6addr_any
; /* default any v6 dest addr */
224 /* Don't warn about invalid flags when we run getopt for the 1st time */
228 * Parse these four arguments now lest there be any buffer overflows
229 * in the parsing of the rest.
232 while ((c
= getopt(argc
, argv
, options
)) != -1) {
236 setzonename_global(optarg
);
253 if (live_kernel
== 1) {
254 if ((state_fd
= open(IPSTATE_NAME
, O_RDONLY
)) == -1) {
255 perror("open(IPSTATE_NAME)");
259 if (setzone(state_fd
) != 0) {
264 if ((ipf_fd
= open(device
, O_RDONLY
)) == -1) {
265 fprintf(stderr
, "open(%s)", device
);
270 if (setzone(ipf_fd
) != 0) {
276 if (kern
!= NULL
|| memf
!= NULL
) {
277 (void)setgid(getgid());
278 (void)setreuid(getuid(), getuid());
279 if (openkmem(kern
, memf
) == -1)
283 if (live_kernel
== 1)
284 (void) checkrev(device
);
285 (void)setgid(getgid());
286 (void)setreuid(getuid(), getuid());
290 while ((c
= getopt(argc
, argv
, options
)) != -1)
300 opts
|= OPT_ACCNT
|OPT_SHOWLIST
;
303 opts
|= OPT_AUTHSTATS
;
312 parse_ipportstr(optarg
, &daddr
, &dport
);
315 opts
|= OPT_FRSTATES
;
321 /* Already handled by getzoneopt() above */
327 opts
|= OPT_INQUE
|OPT_SHOWLIST
;
330 opts
|= OPT_INACTIVE
;
333 opts
|= OPT_SHOWLIST
;
340 opts
|= OPT_SHOWLINENO
;
343 opts
|= OPT_OUTQUE
|OPT_SHOWLIST
;
346 protocol
= getproto(optarg
);
347 if (protocol
== -1) {
348 fprintf(stderr
, "%s: Invalid protocol: %s\n",
354 opts
|= OPT_NORESOLVE
;
357 opts
|= OPT_IPSTATES
;
360 parse_ipportstr(optarg
, &saddr
, &sport
);
364 opts
|= OPT_STATETOP
;
368 "%s: state top facility not compiled in\n",
373 if (!sscanf(optarg
, "%d", &refreshtime
) ||
374 (refreshtime
<= 0)) {
376 "%s: Invalid refreshtime < 1 : %s\n",
386 /* Already handled by getzoneopt() above */
394 if (live_kernel
== 1) {
395 bzero((char *)&fio
, sizeof(fio
));
396 bzero((char *)&ipsst
, sizeof(ipsst
));
397 bzero((char *)&ifrst
, sizeof(ifrst
));
399 ipfstate_live(device
, &fiop
, &ipsstp
, &ifrstp
,
402 ipfstate_dead(kern
, &fiop
, &ipsstp
, &ifrstp
, &frauthstp
, &frf
);
404 if (opts
& OPT_IPSTATES
) {
405 showipstates(ipsstp
);
406 } else if (opts
& OPT_SHOWLIST
) {
408 if ((opts
& OPT_OUTQUE
) && (opts
& OPT_INQUE
)){
412 } else if (opts
& OPT_FRSTATES
)
413 showfrstates(ifrstp
, fiop
->f_ticks
);
415 else if (opts
& OPT_STATETOP
)
416 topipstates(saddr
, daddr
, sport
, dport
, protocol
,
417 use_inet6
? 6 : 4, refreshtime
, topclosed
);
419 else if (opts
& OPT_AUTHSTATS
)
420 showauthstates(frauthstp
);
421 else if (opts
& OPT_GROUPS
)
424 showstats(fiop
, frf
);
431 * Fill in the stats structures from the live kernel, using a combination
432 * of ioctl's and copying directly from kernel memory.
434 static void ipfstate_live(device
, fiopp
, ipsstpp
, ifrstpp
, frauthstpp
, frfp
)
437 ips_stat_t
**ipsstpp
;
438 ipfrstat_t
**ifrstpp
;
439 fr_authstat_t
**frauthstpp
;
444 if (checkrev(device
) == -1) {
445 fprintf(stderr
, "User/kernel version check failed\n");
449 if ((opts
& OPT_AUTHSTATS
) == 0) {
450 bzero((caddr_t
)&ipfo
, sizeof(ipfo
));
451 ipfo
.ipfo_rev
= IPFILTER_VERSION
;
452 ipfo
.ipfo_size
= sizeof(friostat_t
);
453 ipfo
.ipfo_ptr
= (void *)*fiopp
;
454 ipfo
.ipfo_type
= IPFOBJ_IPFSTAT
;
456 if (ioctl(ipf_fd
, SIOCGETFS
, &ipfo
) == -1) {
457 perror("ioctl(ipf:SIOCGETFS)");
461 if (ioctl(ipf_fd
, SIOCGETFF
, frfp
) == -1)
462 perror("ioctl(SIOCGETFF)");
465 if ((opts
& OPT_IPSTATES
) != 0) {
467 bzero((caddr_t
)&ipfo
, sizeof(ipfo
));
468 ipfo
.ipfo_rev
= IPFILTER_VERSION
;
469 ipfo
.ipfo_size
= sizeof(ips_stat_t
);
470 ipfo
.ipfo_ptr
= (void *)*ipsstpp
;
471 ipfo
.ipfo_type
= IPFOBJ_STATESTAT
;
473 if ((ioctl(state_fd
, SIOCGETFS
, &ipfo
) == -1)) {
474 perror("ioctl(state:SIOCGETFS)");
477 if (ioctl(state_fd
, SIOCGETLG
, &state_logging
) == -1) {
478 perror("ioctl(state:SIOCGETLG)");
483 if ((opts
& OPT_FRSTATES
) != 0) {
484 bzero((caddr_t
)&ipfo
, sizeof(ipfo
));
485 ipfo
.ipfo_rev
= IPFILTER_VERSION
;
486 ipfo
.ipfo_size
= sizeof(ipfrstat_t
);
487 ipfo
.ipfo_ptr
= (void *)*ifrstpp
;
488 ipfo
.ipfo_type
= IPFOBJ_FRAGSTAT
;
490 if (ioctl(ipf_fd
, SIOCGFRST
, &ipfo
) == -1) {
491 perror("ioctl(SIOCGFRST)");
496 if (opts
& OPT_VERBOSE
)
497 PRINTF("opts %#x name %s\n", opts
, device
);
499 if ((opts
& OPT_AUTHSTATS
) != 0) {
504 device
= IPAUTH_NAME
;
505 if ((ipf_fd
= open(device
, O_RDONLY
)) == -1) {
510 if (setzone(ipf_fd
) != 0) {
515 bzero((caddr_t
)&ipfo
, sizeof(ipfo
));
516 ipfo
.ipfo_rev
= IPFILTER_VERSION
;
517 ipfo
.ipfo_size
= sizeof(fr_authstat_t
);
518 ipfo
.ipfo_ptr
= (void *)*frauthstpp
;
519 ipfo
.ipfo_type
= IPFOBJ_AUTHSTAT
;
521 if (ioctl(ipf_fd
, SIOCATHST
, &ipfo
) == -1) {
522 perror("ioctl(SIOCATHST)");
530 * Build up the stats structures from data held in the "core" memory.
531 * This is mainly useful when looking at data in crash dumps and ioctl's
532 * just won't work any more.
534 static void ipfstate_dead(kernel
, fiopp
, ipsstpp
, ifrstpp
, frauthstpp
, frfp
)
537 ips_stat_t
**ipsstpp
;
538 ipfrstat_t
**ifrstpp
;
539 fr_authstat_t
**frauthstpp
;
542 static fr_authstat_t frauthst
, *frauthstp
;
543 static ips_stat_t ipsst
, *ipsstp
;
544 static ipfrstat_t ifrst
, *ifrstp
;
545 static friostat_t fio
, *fiop
;
549 struct nlist deadlist
[43] = {
550 { "fr_authstats" }, /* 0 */
555 { "fr_authend" }, /* 5 */
560 { "fr_defaultauthage" }, /* 10 */
565 { "ips_num" }, /* 15 */
570 { "fr_statesize" }, /* 20 */
571 { "fr_state_doflush" },
575 { "ipfr_stats" }, /* 25 */
580 { "fr_nat_lock" }, /* 30 */
585 { "ipl_frouteok" }, /* 35 */
590 { "fr_flags" }, /* 40 */
591 { "ipstate_logging" },
596 frauthstp
= &frauthst
;
605 *frauthstpp
= frauthstp
;
607 bzero((char *)fiop
, sizeof(*fiop
));
608 bzero((char *)ipsstp
, sizeof(*ipsstp
));
609 bzero((char *)ifrstp
, sizeof(*ifrstp
));
610 bzero((char *)frauthstp
, sizeof(*frauthstp
));
612 if (nlist(kernel
, deadlist
) == -1) {
613 fprintf(stderr
, "nlist error\n");
618 * This is for SIOCGETFF.
620 kmemcpy((char *)frfp
, (u_long
)deadlist
[40].n_value
, sizeof(*frfp
));
623 * f_locks is a combination of the lock variable from each part of
624 * ipfilter (state, auth, nat, fragments).
626 kmemcpy((char *)fiop
, (u_long
)deadlist
[13].n_value
, sizeof(*fiop
));
627 kmemcpy((char *)&fiop
->f_locks
[0], (u_long
)deadlist
[22].n_value
,
628 sizeof(fiop
->f_locks
[0]));
629 kmemcpy((char *)&fiop
->f_locks
[0], (u_long
)deadlist
[30].n_value
,
630 sizeof(fiop
->f_locks
[1]));
631 kmemcpy((char *)&fiop
->f_locks
[2], (u_long
)deadlist
[28].n_value
,
632 sizeof(fiop
->f_locks
[2]));
633 kmemcpy((char *)&fiop
->f_locks
[3], (u_long
)deadlist
[12].n_value
,
634 sizeof(fiop
->f_locks
[3]));
637 * Get pointers to each list of rules (active, inactive, in, out)
639 kmemcpy((char *)&rules
, (u_long
)deadlist
[31].n_value
, sizeof(rules
));
640 fiop
->f_fin
[0] = rules
[0][0];
641 fiop
->f_fin
[1] = rules
[0][1];
642 fiop
->f_fout
[0] = rules
[1][0];
643 fiop
->f_fout
[1] = rules
[1][1];
646 * Same for IPv6, except make them null if support for it is not
650 kmemcpy((char *)&rules
, (u_long
)deadlist
[32].n_value
, sizeof(rules
));
651 fiop
->f_fin6
[0] = rules
[0][0];
652 fiop
->f_fin6
[1] = rules
[0][1];
653 fiop
->f_fout6
[0] = rules
[1][0];
654 fiop
->f_fout6
[1] = rules
[1][1];
656 fiop
->f_fin6
[0] = NULL
;
657 fiop
->f_fin6
[1] = NULL
;
658 fiop
->f_fout6
[0] = NULL
;
659 fiop
->f_fout6
[1] = NULL
;
663 * Now get accounting rules pointers.
665 kmemcpy((char *)&rules
, (u_long
)deadlist
[33].n_value
, sizeof(rules
));
666 fiop
->f_acctin
[0] = rules
[0][0];
667 fiop
->f_acctin
[1] = rules
[0][1];
668 fiop
->f_acctout
[0] = rules
[1][0];
669 fiop
->f_acctout
[1] = rules
[1][1];
672 kmemcpy((char *)&rules
, (u_long
)deadlist
[34].n_value
, sizeof(rules
));
673 fiop
->f_acctin6
[0] = rules
[0][0];
674 fiop
->f_acctin6
[1] = rules
[0][1];
675 fiop
->f_acctout6
[0] = rules
[1][0];
676 fiop
->f_acctout6
[1] = rules
[1][1];
678 fiop
->f_acctin6
[0] = NULL
;
679 fiop
->f_acctin6
[1] = NULL
;
680 fiop
->f_acctout6
[0] = NULL
;
681 fiop
->f_acctout6
[1] = NULL
;
685 * A collection of "global" variables used inside the kernel which
686 * are all collected in friostat_t via ioctl.
688 kmemcpy((char *)&fiop
->f_froute
, (u_long
)deadlist
[35].n_value
,
689 sizeof(fiop
->f_froute
));
690 kmemcpy((char *)&fiop
->f_running
, (u_long
)deadlist
[36].n_value
,
691 sizeof(fiop
->f_running
));
692 kmemcpy((char *)&fiop
->f_groups
, (u_long
)deadlist
[37].n_value
,
693 sizeof(fiop
->f_groups
));
694 kmemcpy((char *)&fiop
->f_active
, (u_long
)deadlist
[38].n_value
,
695 sizeof(fiop
->f_active
));
696 kmemcpy((char *)&fiop
->f_defpass
, (u_long
)deadlist
[39].n_value
,
697 sizeof(fiop
->f_defpass
));
700 * Build up the state information stats structure.
702 kmemcpy((char *)ipsstp
, (u_long
)deadlist
[14].n_value
, sizeof(*ipsstp
));
703 kmemcpy((char *)&temp
, (u_long
)deadlist
[15].n_value
, sizeof(temp
));
704 ipsstp
->iss_active
= temp
;
705 ipsstp
->iss_table
= (void *)deadlist
[18].n_value
;
706 ipsstp
->iss_list
= (void *)deadlist
[17].n_value
;
709 * Build up the authentiation information stats structure.
711 kmemcpy((char *)frauthstp
, (u_long
)deadlist
[0].n_value
,
713 frauthstp
->fas_faelist
= (void *)deadlist
[1].n_value
;
716 * Build up the fragment information stats structure.
718 kmemcpy((char *)ifrstp
, (u_long
)deadlist
[25].n_value
,
720 ifrstp
->ifs_table
= (void *)deadlist
[23].n_value
;
721 ifrstp
->ifs_nattab
= (void *)deadlist
[24].n_value
;
722 kmemcpy((char *)&ifrstp
->ifs_inuse
, (u_long
)deadlist
[26].n_value
,
723 sizeof(ifrstp
->ifs_inuse
));
726 * Get logging on/off switches
728 kmemcpy((char *)&state_logging
, (u_long
)deadlist
[41].n_value
,
729 sizeof(state_logging
));
734 * Display the kernel stats for packets blocked and passed and other
735 * associated running totals which are kept.
737 static void showstats(fp
, frf
)
742 PRINTF("bad packets:\t\tin %lu\tout %lu\n",
743 fp
->f_st
[0].fr_bad
, fp
->f_st
[1].fr_bad
);
745 PRINTF(" IPv6 packets:\t\tin %lu out %lu\n",
746 fp
->f_st
[0].fr_ipv6
, fp
->f_st
[1].fr_ipv6
);
748 PRINTF(" input packets:\t\tblocked %lu passed %lu nomatch %lu",
749 fp
->f_st
[0].fr_block
, fp
->f_st
[0].fr_pass
,
751 PRINTF(" counted %lu short %lu\n",
752 fp
->f_st
[0].fr_acct
, fp
->f_st
[0].fr_short
);
753 PRINTF("output packets:\t\tblocked %lu passed %lu nomatch %lu",
754 fp
->f_st
[1].fr_block
, fp
->f_st
[1].fr_pass
,
756 PRINTF(" counted %lu short %lu\n",
757 fp
->f_st
[1].fr_acct
, fp
->f_st
[1].fr_short
);
758 PRINTF(" input packets logged:\tblocked %lu passed %lu\n",
759 fp
->f_st
[0].fr_bpkl
, fp
->f_st
[0].fr_ppkl
);
760 PRINTF("output packets logged:\tblocked %lu passed %lu\n",
761 fp
->f_st
[1].fr_bpkl
, fp
->f_st
[1].fr_ppkl
);
762 PRINTF(" packets logged:\tinput %lu output %lu\n",
763 fp
->f_st
[0].fr_pkl
, fp
->f_st
[1].fr_pkl
);
764 PRINTF(" log failures:\t\tinput %lu output %lu\n",
765 fp
->f_st
[0].fr_skip
, fp
->f_st
[1].fr_skip
);
766 PRINTF("fragment state(in):\tkept %lu\tlost %lu\tnot fragmented %lu\n",
767 fp
->f_st
[0].fr_nfr
, fp
->f_st
[0].fr_bnfr
,
769 PRINTF("fragment state(out):\tkept %lu\tlost %lu\tnot fragmented %lu\n",
770 fp
->f_st
[1].fr_nfr
, fp
->f_st
[1].fr_bnfr
,
772 PRINTF("packet state(in):\tkept %lu\tlost %lu\n",
773 fp
->f_st
[0].fr_ads
, fp
->f_st
[0].fr_bads
);
774 PRINTF("packet state(out):\tkept %lu\tlost %lu\n",
775 fp
->f_st
[1].fr_ads
, fp
->f_st
[1].fr_bads
);
776 PRINTF("ICMP replies:\t%lu\tTCP RSTs sent:\t%lu\n",
777 fp
->f_st
[0].fr_ret
, fp
->f_st
[1].fr_ret
);
778 PRINTF("Invalid source(in):\t%lu\n", fp
->f_st
[0].fr_badsrc
);
779 PRINTF("Result cache hits(in):\t%lu\t(out):\t%lu\n",
780 fp
->f_st
[0].fr_chit
, fp
->f_st
[1].fr_chit
);
781 PRINTF("IN Pullups succeeded:\t%lu\tfailed:\t%lu\n",
782 fp
->f_st
[0].fr_pull
[0], fp
->f_st
[0].fr_pull
[1]);
783 PRINTF("OUT Pullups succeeded:\t%lu\tfailed:\t%lu\n",
784 fp
->f_st
[1].fr_pull
[0], fp
->f_st
[1].fr_pull
[1]);
785 PRINTF("Fastroute successes:\t%lu\tfailures:\t%lu\n",
786 fp
->f_froute
[0], fp
->f_froute
[1]);
787 PRINTF("TCP cksum fails(in):\t%lu\t(out):\t%lu\n",
788 fp
->f_st
[0].fr_tcpbad
, fp
->f_st
[1].fr_tcpbad
);
789 PRINTF("IPF Ticks:\t%lu\n", fp
->f_ticks
);
791 PRINTF("Packet log flags set: (%#x)\n", frf
);
792 if (frf
& FF_LOGPASS
)
793 PRINTF("\tpackets passed through filter\n");
794 if (frf
& FF_LOGBLOCK
)
795 PRINTF("\tpackets blocked by filter\n");
796 if (frf
& FF_LOGNOMATCH
)
797 PRINTF("\tpackets not matched by filter\n");
804 * Print out a list of rules from the kernel, starting at the one passed.
806 static void printlivelist(out
, set
, fp
, group
, comment
)
809 char *group
, *comment
;
811 frgroup_t
*grtop
, *grtail
, *g
;
812 struct frentry fb
, *fg
;
822 rule
.iri_ver
= use_inet6
? AF_INET6
: AF_INET
;
823 rule
.iri_inout
= out
;
824 rule
.iri_active
= set
;
828 strncpy(rule
.iri_group
, group
, FR_GROUPLEN
);
830 rule
.iri_group
[0] = '\0';
832 bzero((char *)&obj
, sizeof(obj
));
833 obj
.ipfo_rev
= IPFILTER_VERSION
;
834 obj
.ipfo_type
= IPFOBJ_IPFITER
;
835 obj
.ipfo_size
= sizeof(rule
);
836 obj
.ipfo_ptr
= &rule
;
841 memset(array
, 0xff, sizeof(array
));
842 fp
= (frentry_t
*)array
;
844 if (ioctl(ipf_fd
, SIOCIPFITER
, &obj
) == -1) {
845 perror("ioctl(SIOCIPFITER)");
848 if (fp
->fr_data
!= NULL
)
849 fp
->fr_data
= (char *)fp
+ sizeof(*fp
);
853 if (opts
& (OPT_HITS
|OPT_VERBOSE
))
855 PRINTF("%qu ", (unsigned long long) fp
->fr_hits
);
857 PRINTF("%lu ", fp
->fr_hits
);
859 if (opts
& (OPT_ACCNT
|OPT_VERBOSE
))
861 PRINTF("%qu ", (unsigned long long) fp
->fr_bytes
);
863 PRINTF("%lu ", fp
->fr_bytes
);
865 if (opts
& OPT_SHOWLINENO
)
869 if (opts
& OPT_DEBUG
) {
870 binprint(fp
, sizeof(*fp
));
871 if (fp
->fr_data
!= NULL
&& fp
->fr_dsize
> 0)
872 binprint(fp
->fr_data
, fp
->fr_dsize
);
875 if (fp
->fr_grhead
[0] != '\0') {
876 g
= calloc(1, sizeof(*g
));
879 strncpy(g
->fg_name
, fp
->fr_grhead
,
890 } while (fp
->fr_next
!= NULL
);
892 while ((g
= grtop
) != NULL
) {
893 printlivelist(out
, set
, NULL
, g
->fg_name
, comment
);
900 static void printdeadlist(out
, set
, fp
, group
, comment
)
903 char *group
, *comment
;
905 frgroup_t
*grtop
, *grtail
, *g
;
906 struct frentry fb
, *fg
;
918 if (kmemcpy((char *)&fb
, (u_long
)fb
.fr_next
,
925 type
= fb
.fr_type
& ~FR_T_BUILTIN
;
926 if (type
== FR_T_IPF
|| type
== FR_T_BPFOPC
) {
928 data
= malloc(fb
.fr_dsize
);
930 if (kmemcpy(data
, (u_long
)fb
.fr_data
,
931 fb
.fr_dsize
) == -1) {
941 if (opts
& (OPT_HITS
|OPT_VERBOSE
))
943 PRINTF("%qu ", (unsigned long long) fb
.fr_hits
);
945 PRINTF("%lu ", fb
.fr_hits
);
947 if (opts
& (OPT_ACCNT
|OPT_VERBOSE
))
949 PRINTF("%qu ", (unsigned long long) fb
.fr_bytes
);
951 PRINTF("%lu ", fb
.fr_bytes
);
953 if (opts
& OPT_SHOWLINENO
)
957 if (opts
& OPT_DEBUG
) {
958 binprint(fp
, sizeof(*fp
));
959 if (fb
.fr_data
!= NULL
&& fb
.fr_dsize
> 0)
960 binprint(fb
.fr_data
, fb
.fr_dsize
);
963 if (fb
.fr_grhead
[0] != '\0') {
964 g
= calloc(1, sizeof(*g
));
967 strncpy(g
->fg_name
, fb
.fr_grhead
,
978 if (type
== FR_T_CALLFUNC
) {
979 printdeadlist(out
, set
, fb
.fr_data
, group
,
982 } while (fb
.fr_next
!= NULL
);
984 while ((g
= grtop
) != NULL
) {
985 printdeadlist(out
, set
, NULL
, g
->fg_name
, comment
);
993 * print out all of the asked for rule sets, using the stats struct as
994 * the base from which to get the pointers.
996 static void showlist(fiop
)
997 struct friostat
*fiop
;
999 struct frentry
*fp
= NULL
;
1002 set
= fiop
->f_active
;
1003 if (opts
& OPT_INACTIVE
)
1005 if (opts
& OPT_ACCNT
) {
1007 if ((use_inet6
) && (opts
& OPT_OUTQUE
)) {
1009 fp
= (struct frentry
*)fiop
->f_acctout6
[set
];
1010 } else if ((use_inet6
) && (opts
& OPT_INQUE
)) {
1012 fp
= (struct frentry
*)fiop
->f_acctin6
[set
];
1015 if (opts
& OPT_OUTQUE
) {
1017 fp
= (struct frentry
*)fiop
->f_acctout
[set
];
1018 } else if (opts
& OPT_INQUE
) {
1020 fp
= (struct frentry
*)fiop
->f_acctin
[set
];
1022 FPRINTF(stderr
, "No -i or -o given with -a\n");
1027 if ((use_inet6
) && (opts
& OPT_OUTQUE
)) {
1029 fp
= (struct frentry
*)fiop
->f_fout6
[set
];
1030 } else if ((use_inet6
) && (opts
& OPT_INQUE
)) {
1032 fp
= (struct frentry
*)fiop
->f_fin6
[set
];
1035 if (opts
& OPT_OUTQUE
) {
1037 fp
= (struct frentry
*)fiop
->f_fout
[set
];
1038 } else if (opts
& OPT_INQUE
) {
1040 fp
= (struct frentry
*)fiop
->f_fin
[set
];
1044 if (opts
& OPT_VERBOSE
)
1045 FPRINTF(stderr
, "showlist:opts %#x i %d\n", opts
, i
);
1047 if (opts
& OPT_VERBOSE
)
1048 PRINTF("fp %p set %d\n", fp
, set
);
1050 FPRINTF(stderr
, "empty list for %s%s\n",
1051 (opts
& OPT_INACTIVE
) ? "inactive " : "", filters
[i
]);
1054 if (live_kernel
== 1)
1055 printlivelist(i
, set
, fp
, NULL
, NULL
);
1057 printdeadlist(i
, set
, fp
, NULL
, NULL
);
1062 * Display ipfilter stateful filtering information
1064 static void showipstates(ipsp
)
1067 u_long minlen
, maxlen
, totallen
, *buckets
;
1070 sz
= sizeof(*buckets
) * ipsp
->iss_statesize
;
1071 buckets
= (u_long
*)malloc(sz
);
1072 if (buckets
== NULL
) {
1076 if (kmemcpy((char *)buckets
, (u_long
)ipsp
->iss_bucketlen
, sz
)) {
1082 * If a list of states hasn't been asked for, only print out stats
1084 if (!(opts
& OPT_SHOWLIST
)) {
1085 PRINTF("IP states added:\n\t%lu TCP\n\t%lu UDP\n\t%lu ICMP\n",
1086 ipsp
->iss_tcp
, ipsp
->iss_udp
, ipsp
->iss_icmp
);
1087 PRINTF("\t%lu hits\n\t%lu misses\n",
1088 ipsp
->iss_hits
, ipsp
->iss_miss
);
1089 PRINTF("\t%lu maximum\n\t%lu no memory\n", ipsp
->iss_max
,
1091 PRINTF("\t%lu active\n\t%lu expired\n",
1092 ipsp
->iss_active
, ipsp
->iss_expire
);
1093 PRINTF("\t%lu closed\n\t%u orphans\n",
1094 ipsp
->iss_fin
, ipsp
->iss_orphans
);
1096 PRINTF("State logging %sabled\n",
1097 state_logging
? "en" : "dis");
1099 PRINTF("\nState table bucket statistics:\n");
1100 PRINTF("\t%lu in use\n\t%lu max bucket\n", ipsp
->iss_inuse
,
1101 ipsp
->iss_bucketfull
);
1103 minlen
= ipsp
->iss_max
;
1107 for (i
= 0; i
< ipsp
->iss_statesize
; i
++) {
1108 if (buckets
[i
] > maxlen
)
1109 maxlen
= buckets
[i
];
1110 if (buckets
[i
] < minlen
)
1111 minlen
= buckets
[i
];
1112 totallen
+= buckets
[i
];
1115 PRINTF("\t%2.2f%% bucket usage\n\t%lu minimal length\n",
1116 ((float)ipsp
->iss_inuse
/ ipsp
->iss_statesize
) * 100.0,
1118 PRINTF("\t%lu maximal length\n\t%.3f average length\n",
1120 ipsp
->iss_inuse
? (float) totallen
/ ipsp
->iss_inuse
:
1123 #define ENTRIES_PER_LINE 5
1125 if (opts
& OPT_VERBOSE
) {
1126 PRINTF("\nCurrent bucket sizes :\n");
1127 for (i
= 0; i
< ipsp
->iss_statesize
; i
++) {
1128 if ((i
% ENTRIES_PER_LINE
) == 0)
1130 PRINTF("%4d -> %4lu", i
, buckets
[i
]);
1131 if ((i
% ENTRIES_PER_LINE
) ==
1132 (ENTRIES_PER_LINE
- 1))
1146 * Print out all the state information currently held in the kernel.
1148 while (ipsp
->iss_list
!= NULL
) {
1149 ipsp
->iss_list
= printstate(ipsp
->iss_list
, opts
,
1158 static int handle_resize
= 0, handle_break
= 0;
1160 static void topipstates(saddr
, daddr
, sport
, dport
, protocol
, ver
,
1161 refreshtime
, topclosed
)
1171 char str1
[STSTRSIZE
], str2
[STSTRSIZE
], str3
[STSTRSIZE
], str4
[STSTRSIZE
];
1172 int maxtsentries
= 0, reverse
= 0, sorting
= STSORT_DEFAULT
;
1173 int i
, j
, winy
, tsentry
, maxx
, maxy
, redraw
= 0, ret
= 0;
1174 int len
, srclen
, dstlen
, forward
= 1, c
= 0;
1175 ips_stat_t ipsst
, *ipsstp
= &ipsst
;
1176 statetop_t
*tstable
= NULL
, *tp
;
1177 const char *errstr
= "";
1180 struct timeval selecttimeout
;
1181 char hostnm
[HOSTNMLEN
];
1182 struct protoent
*proto
;
1186 /* install signal handlers */
1187 signal(SIGINT
, sig_break
);
1188 signal(SIGQUIT
, sig_break
);
1189 signal(SIGTERM
, sig_break
);
1190 signal(SIGWINCH
, sig_resize
);
1192 /* init ncurses stuff */
1198 getmaxyx(stdscr
, maxy
, maxx
);
1201 gethostname(hostnm
, sizeof(hostnm
) - 1);
1202 hostnm
[sizeof(hostnm
) - 1] = '\0';
1204 /* init ipfobj_t stuff */
1205 bzero((caddr_t
)&ipfo
, sizeof(ipfo
));
1206 ipfo
.ipfo_rev
= IPFILTER_VERSION
;
1207 ipfo
.ipfo_size
= sizeof(*ipsstp
);
1208 ipfo
.ipfo_ptr
= (void *)ipsstp
;
1209 ipfo
.ipfo_type
= IPFOBJ_STATESTAT
;
1211 /* repeat until user aborts */
1214 /* get state table */
1215 bzero((char *)&ipsst
, sizeof(ipsst
));
1216 if ((ioctl(state_fd
, SIOCGETFS
, &ipfo
) == -1)) {
1217 errstr
= "ioctl(SIOCGETFS)";
1222 /* clear the history */
1225 /* reset max str len */
1226 srclen
= dstlen
= 0;
1228 /* read the state table and store in tstable */
1229 for (; ipsstp
->iss_list
; ipsstp
->iss_list
= ips
.is_next
) {
1231 if (kmemcpy((char *)&ips
, (u_long
)ipsstp
->iss_list
,
1235 if (ips
.is_v
!= ver
)
1238 /* check v4 src/dest addresses */
1239 if (ips
.is_v
== 4) {
1240 if ((saddr
.in4
.s_addr
!= INADDR_ANY
&&
1241 saddr
.in4
.s_addr
!= ips
.is_saddr
) ||
1242 (daddr
.in4
.s_addr
!= INADDR_ANY
&&
1243 daddr
.in4
.s_addr
!= ips
.is_daddr
))
1247 /* check v6 src/dest addresses */
1248 if (ips
.is_v
== 6) {
1249 if ((IP6_NEQ(&saddr
, &in6addr_any
) &&
1250 IP6_NEQ(&saddr
, &ips
.is_src
)) ||
1251 (IP6_NEQ(&daddr
, &in6addr_any
) &&
1252 IP6_NEQ(&daddr
, &ips
.is_dst
)))
1256 /* check protocol */
1257 if (protocol
> 0 && protocol
!= ips
.is_p
)
1260 /* check ports if protocol is TCP or UDP */
1261 if (((ips
.is_p
== IPPROTO_TCP
) ||
1262 (ips
.is_p
== IPPROTO_UDP
)) &&
1263 (((sport
> 0) && (htons(sport
) != ips
.is_sport
)) ||
1264 ((dport
> 0) && (htons(dport
) != ips
.is_dport
))))
1267 /* show closed TCP sessions ? */
1268 if ((topclosed
== 0) && (ips
.is_p
== IPPROTO_TCP
) &&
1269 (ips
.is_state
[0] >= IPF_TCPS_LAST_ACK
) &&
1270 (ips
.is_state
[1] >= IPF_TCPS_LAST_ACK
))
1274 * if necessary make room for this state
1278 if (!maxtsentries
|| tsentry
== maxtsentries
) {
1279 maxtsentries
+= STGROWSIZE
;
1280 tstable
= reallocarray(tstable
, maxtsentries
,
1281 sizeof (statetop_t
));
1282 if (tstable
== NULL
) {
1288 /* get max src/dest address string length */
1289 len
= strlen(getip(ips
.is_v
, &ips
.is_src
));
1292 len
= strlen(getip(ips
.is_v
, &ips
.is_dst
));
1296 /* fill structure */
1297 tp
= tstable
+ tsentry
;
1298 tp
->st_src
= ips
.is_src
;
1299 tp
->st_dst
= ips
.is_dst
;
1300 tp
->st_p
= ips
.is_p
;
1301 tp
->st_v
= ips
.is_v
;
1302 tp
->st_state
[0] = ips
.is_state
[0];
1303 tp
->st_state
[1] = ips
.is_state
[1];
1305 tp
->st_pkts
= ips
.is_pkts
[0]+ips
.is_pkts
[1];
1306 tp
->st_bytes
= ips
.is_bytes
[0]+ips
.is_bytes
[1];
1308 tp
->st_pkts
= ips
.is_pkts
[2]+ips
.is_pkts
[3];
1309 tp
->st_bytes
= ips
.is_bytes
[2]+ips
.is_bytes
[3];
1311 tp
->st_age
= ips
.is_die
- ipsstp
->iss_ticks
;
1312 if ((ips
.is_p
== IPPROTO_TCP
) ||
1313 (ips
.is_p
== IPPROTO_UDP
)) {
1314 tp
->st_sport
= ips
.is_sport
;
1315 tp
->st_dport
= ips
.is_dport
;
1320 /* sort the array */
1321 if (tsentry
!= -1) {
1325 qsort(tstable
, tsentry
+ 1,
1326 sizeof(statetop_t
), sort_p
);
1329 qsort(tstable
, tsentry
+ 1,
1330 sizeof(statetop_t
), sort_pkts
);
1333 qsort(tstable
, tsentry
+ 1,
1334 sizeof(statetop_t
), sort_bytes
);
1337 qsort(tstable
, tsentry
+ 1,
1338 sizeof(statetop_t
), sort_ttl
);
1341 qsort(tstable
, tsentry
+ 1,
1342 sizeof(statetop_t
), sort_srcip
);
1345 qsort(tstable
, tsentry
+1,
1346 sizeof(statetop_t
), sort_srcpt
);
1349 qsort(tstable
, tsentry
+ 1,
1350 sizeof(statetop_t
), sort_dstip
);
1353 qsort(tstable
, tsentry
+ 1,
1354 sizeof(statetop_t
), sort_dstpt
);
1361 /* handle window resizes */
1362 if (handle_resize
) {
1369 getmaxyx(stdscr
, maxy
, maxx
);
1383 sprintf(str1
, "%s - %s - state top", hostnm
, IPL_VERSION
);
1384 for (j
= 0 ; j
< (maxx
- 8 - strlen(str1
)) / 2; j
++)
1389 /* just for fun add a clock */
1390 move(winy
, maxx
- 8);
1392 strftime(str1
, 80, "%T", localtime(&t
));
1393 printw("%s\n", str1
);
1396 * print the display filters, this is placed in the loop,
1397 * because someday I might add code for changing these
1398 * while the programming is running :-)
1401 sprintf(str1
, "%s,%d", getip(ver
, &saddr
), sport
);
1403 sprintf(str1
, "%s", getip(ver
, &saddr
));
1406 sprintf(str2
, "%s,%d", getip(ver
, &daddr
), dport
);
1408 sprintf(str2
, "%s", getip(ver
, &daddr
));
1411 strcpy(str3
, "any");
1412 else if ((proto
= getprotobynumber(protocol
)) != NULL
)
1413 sprintf(str3
, "%s", proto
->p_name
);
1415 sprintf(str3
, "%d", protocol
);
1420 sprintf(str4
, "proto");
1423 sprintf(str4
, "# pkts");
1426 sprintf(str4
, "# bytes");
1429 sprintf(str4
, "ttl");
1432 sprintf(str4
, "src ip");
1435 sprintf(str4
, "src port");
1438 sprintf(str4
, "dest ip");
1441 sprintf(str4
, "dest port");
1444 sprintf(str4
, "unknown");
1449 strcat(str4
, " (reverse)");
1453 printw("Src: %s, Dest: %s, Proto: %s, Sorted by: %s\n\n",
1454 str1
, str2
, str3
, str4
);
1457 * For an IPv4 IP address we need at most 15 characters,
1458 * 4 tuples of 3 digits, separated by 3 dots. Enforce this
1459 * length, so the colums do not change positions based
1460 * on the size of the IP address. This length makes the
1461 * output fit in a 80 column terminal.
1462 * We are lacking a good solution for IPv6 addresses (that
1463 * can be longer that 15 characters), so we do not enforce
1464 * a maximum on the IP field size.
1471 /* print column description */
1475 printw("%-*s %-*s %3s %4s %7s %9s %9s\n",
1476 srclen
+ 6, "Source IP", dstlen
+ 6, "Destination IP",
1477 "ST", "PR", "#pkts", "#bytes", "ttl");
1480 /* print all the entries */
1485 if (tsentry
> maxy
- 6)
1487 for (i
= 0; i
<= tsentry
; i
++) {
1488 /* print src/dest and port */
1489 if ((tp
->st_p
== IPPROTO_TCP
) ||
1490 (tp
->st_p
== IPPROTO_UDP
)) {
1491 sprintf(str1
, "%s,%hu",
1492 getip(tp
->st_v
, &tp
->st_src
),
1493 ntohs(tp
->st_sport
));
1494 sprintf(str2
, "%s,%hu",
1495 getip(tp
->st_v
, &tp
->st_dst
),
1496 ntohs(tp
->st_dport
));
1498 sprintf(str1
, "%s", getip(tp
->st_v
,
1500 sprintf(str2
, "%s", getip(tp
->st_v
,
1505 printw("%-*s %-*s", srclen
+ 6, str1
, dstlen
+ 6, str2
);
1508 sprintf(str1
, "%X/%X", tp
->st_state
[0],
1510 printw(" %3s", str1
);
1512 /* print protocol */
1513 proto
= getprotobynumber(tp
->st_p
);
1515 strncpy(str1
, proto
->p_name
, 4);
1518 sprintf(str1
, "%d", tp
->st_p
);
1520 /* just print icmp for IPv6-ICMP */
1521 if (tp
->st_p
== IPPROTO_ICMPV6
)
1522 strcpy(str1
, "icmp");
1523 printw(" %4s", str1
);
1525 /* print #pkt/#bytes */
1527 printw(" %7qu %9qu", (unsigned long long) tp
->st_pkts
,
1528 (unsigned long long) tp
->st_bytes
);
1530 printw(" %7lu %9lu", tp
->st_pkts
, tp
->st_bytes
);
1532 printw(" %9s", ttl_to_string(tp
->st_age
));
1540 /* screen data structure is filled, now update the screen */
1544 if (refresh() == ERR
)
1551 /* wait for key press or a 1 second time out period */
1552 selecttimeout
.tv_sec
= refreshtime
;
1553 selecttimeout
.tv_usec
= 0;
1556 select(1, &readfd
, NULL
, NULL
, &selecttimeout
);
1558 /* if key pressed, read all waiting keys */
1559 if (FD_ISSET(0, &readfd
)) {
1564 if (ISALPHA(c
) && ISUPPER(c
))
1568 } else if (c
== 'q') {
1570 } else if (c
== 'r') {
1572 } else if (c
== 'b') {
1574 } else if (c
== 'f') {
1576 } else if (c
== 's') {
1577 if (++sorting
> STSORT_MAX
)
1595 * Show fragment cache information that's held in the kernel.
1597 static void showfrstates(ifsp
, ticks
)
1601 struct ipfr
*ipfrtab
[IPFT_SIZE
], ifr
;
1605 * print out the numeric statistics
1607 PRINTF("IP fragment states:\n\t%lu new\n\t%lu expired\n\t%lu hits\n",
1608 ifsp
->ifs_new
, ifsp
->ifs_expire
, ifsp
->ifs_hits
);
1609 PRINTF("\t%lu retrans\n\t%lu too short\n",
1610 ifsp
->ifs_retrans0
, ifsp
->ifs_short
);
1611 PRINTF("\t%lu no memory\n\t%lu already exist\n",
1612 ifsp
->ifs_nomem
, ifsp
->ifs_exists
);
1613 PRINTF("\t%lu inuse\n", ifsp
->ifs_inuse
);
1614 if (kmemcpy((char *)ipfrtab
, (u_long
)ifsp
->ifs_table
, sizeof(ipfrtab
)))
1618 * Print out the contents (if any) of the fragment cache table.
1621 for (i
= 0; i
< IPFT_SIZE
; i
++)
1622 while (ipfrtab
[i
] != NULL
) {
1623 if (kmemcpy((char *)&ifr
, (u_long
)ipfrtab
[i
],
1626 ifr
.ipfr_ttl
-= ticks
;
1627 printfraginfo("", &ifr
);
1628 ipfrtab
[i
] = ifr
.ipfr_next
;
1631 * Print out the contents (if any) of the NAT fragment cache table.
1633 if (kmemcpy((char *)ipfrtab
, (u_long
)ifsp
->ifs_nattab
,sizeof(ipfrtab
)))
1635 for (i
= 0; i
< IPFT_SIZE
; i
++)
1636 while (ipfrtab
[i
] != NULL
) {
1637 if (kmemcpy((char *)&ifr
, (u_long
)ipfrtab
[i
],
1640 ifr
.ipfr_ttl
-= ticks
;
1641 printfraginfo("NAT: ", &ifr
);
1642 ipfrtab
[i
] = ifr
.ipfr_next
;
1648 * Show stats on how auth within IPFilter has been used
1650 static void showauthstates(asp
)
1653 frauthent_t
*frap
, fra
;
1656 printf("Authorisation hits: %qu\tmisses %qu\n",
1657 (unsigned long long) asp
->fas_hits
,
1658 (unsigned long long) asp
->fas_miss
);
1660 printf("Authorisation hits: %ld\tmisses %ld\n", asp
->fas_hits
,
1663 printf("nospace %ld\nadded %ld\nsendfail %ld\nsendok %ld\n",
1664 asp
->fas_nospace
, asp
->fas_added
, asp
->fas_sendfail
,
1666 printf("queok %ld\nquefail %ld\nexpire %ld\n",
1667 asp
->fas_queok
, asp
->fas_quefail
, asp
->fas_expire
);
1669 frap
= asp
->fas_faelist
;
1671 if (kmemcpy((char *)&fra
, (u_long
)frap
, sizeof(fra
)) == -1)
1674 printf("age %ld\t", fra
.fae_age
);
1675 printfr(&fra
.fae_fr
, ioctl
);
1676 frap
= fra
.fae_next
;
1682 * Display groups used for each of filter rules, accounting rules and
1683 * authentication, separately.
1685 static void showgroups(fiop
)
1686 struct friostat
*fiop
;
1688 static char *gnames
[3] = { "Filter", "Accounting", "Authentication" };
1689 static int gnums
[3] = { IPL_LOGIPF
, IPL_LOGCOUNT
, IPL_LOGAUTH
};
1693 on
= fiop
->f_active
;
1696 for (i
= 0; i
< 3; i
++) {
1697 printf("%s groups (active):\n", gnames
[i
]);
1698 for (fp
= fiop
->f_groups
[gnums
[i
]][on
]; fp
!= NULL
;
1700 if (kmemcpy((char *)&grp
, (u_long
)fp
, sizeof(grp
)))
1703 printf("%s\n", grp
.fg_name
);
1704 printf("%s groups (inactive):\n", gnames
[i
]);
1705 for (fp
= fiop
->f_groups
[gnums
[i
]][off
]; fp
!= NULL
;
1707 if (kmemcpy((char *)&grp
, (u_long
)fp
, sizeof(grp
)))
1710 printf("%s\n", grp
.fg_name
);
1714 static void parse_ipportstr(argument
, ip
, port
)
1715 const char *argument
;
1722 /* make working copy of argument, Theoretically you must be able
1723 * to write to optarg, but that seems very ugly to me....
1725 s
= strdup(argument
);
1730 if ((comma
= strchr(s
, ',')) != NULL
) {
1731 if (!strcasecmp(comma
+ 1, "any")) {
1733 } else if (!sscanf(comma
+ 1, "%d", port
) ||
1734 (*port
< 0) || (*port
> 65535)) {
1735 fprintf(stderr
, "Invalid port specfication in %s\n",
1744 /* get ip address */
1745 if (!strcasecmp(s
, "any")) {
1746 ip
->in4
.s_addr
= INADDR_ANY
;
1748 ip
->in6
= in6addr_any
;
1749 } else if (use_inet6
&& inet_pton(AF_INET6
, s
, &ip
->in6
)) {
1752 } else if (inet_aton(s
, &ip
->in4
))
1756 fprintf(stderr
, "Invalid IP address: %s\n", s
);
1761 /* free allocated memory */
1767 static void sig_resize(s
)
1773 static void sig_break(s
)
1779 static char *getip(v
, addr
)
1784 static char hostbuf
[MAXHOSTNAMELEN
+1];
1788 return inet_ntoa(addr
->in4
);
1791 (void) inet_ntop(AF_INET6
, &addr
->in6
, hostbuf
, sizeof(hostbuf
) - 1);
1792 hostbuf
[MAXHOSTNAMELEN
] = '\0';
1800 static char *ttl_to_string(ttl
)
1803 static char ttlbuf
[STSTRSIZE
];
1804 int hours
, minutes
, seconds
;
1806 /* ttl is in half seconds */
1815 sprintf(ttlbuf
, "%2d:%02d:%02d", hours
, minutes
, seconds
);
1817 sprintf(ttlbuf
, "%2d:%02d", minutes
, seconds
);
1822 static int sort_pkts(a
, b
)
1827 register const statetop_t
*ap
= a
;
1828 register const statetop_t
*bp
= b
;
1830 if (ap
->st_pkts
== bp
->st_pkts
)
1832 else if (ap
->st_pkts
< bp
->st_pkts
)
1838 static int sort_bytes(a
, b
)
1842 register const statetop_t
*ap
= a
;
1843 register const statetop_t
*bp
= b
;
1845 if (ap
->st_bytes
== bp
->st_bytes
)
1847 else if (ap
->st_bytes
< bp
->st_bytes
)
1853 static int sort_p(a
, b
)
1857 register const statetop_t
*ap
= a
;
1858 register const statetop_t
*bp
= b
;
1860 if (ap
->st_p
== bp
->st_p
)
1862 else if (ap
->st_p
< bp
->st_p
)
1868 static int sort_ttl(a
, b
)
1872 register const statetop_t
*ap
= a
;
1873 register const statetop_t
*bp
= b
;
1875 if (ap
->st_age
== bp
->st_age
)
1877 else if (ap
->st_age
< bp
->st_age
)
1882 static int sort_srcip(a
, b
)
1886 register const statetop_t
*ap
= a
;
1887 register const statetop_t
*bp
= b
;
1891 if (IP6_EQ(&ap
->st_src
, &bp
->st_src
))
1893 else if (IP6_GT(&ap
->st_src
, &bp
->st_src
))
1898 if (ntohl(ap
->st_src
.in4
.s_addr
) ==
1899 ntohl(bp
->st_src
.in4
.s_addr
))
1901 else if (ntohl(ap
->st_src
.in4
.s_addr
) >
1902 ntohl(bp
->st_src
.in4
.s_addr
))
1908 static int sort_srcpt(a
, b
)
1912 register const statetop_t
*ap
= a
;
1913 register const statetop_t
*bp
= b
;
1915 if (htons(ap
->st_sport
) == htons(bp
->st_sport
))
1917 else if (htons(ap
->st_sport
) > htons(bp
->st_sport
))
1922 static int sort_dstip(a
, b
)
1926 register const statetop_t
*ap
= a
;
1927 register const statetop_t
*bp
= b
;
1931 if (IP6_EQ(&ap
->st_dst
, &bp
->st_dst
))
1933 else if (IP6_GT(&ap
->st_dst
, &bp
->st_dst
))
1938 if (ntohl(ap
->st_dst
.in4
.s_addr
) ==
1939 ntohl(bp
->st_dst
.in4
.s_addr
))
1941 else if (ntohl(ap
->st_dst
.in4
.s_addr
) >
1942 ntohl(bp
->st_dst
.in4
.s_addr
))
1948 static int sort_dstpt(a
, b
)
1952 register const statetop_t
*ap
= a
;
1953 register const statetop_t
*bp
= b
;
1955 if (htons(ap
->st_dport
) == htons(bp
->st_dport
))
1957 else if (htons(ap
->st_dport
) > htons(bp
->st_dport
))