Merge commit 'crater/master'
[dragonfly.git] / contrib / ipfilter / fils.c
blobe21af892a577b7828853311bf9d25daf77d66edb
1 /*
2 * Copyright (C) 1993-2001 by Darren Reed.
4 * See the IPFILTER.LICENCE file for details on licencing.
5 */
6 #ifdef __FreeBSD__
7 # ifndef __FreeBSD_cc_version
8 # include <osreldate.h>
9 # else
10 # if __FreeBSD_cc_version < 430000
11 # include <osreldate.h>
12 # endif
13 # endif
14 #endif
15 #if defined(__sgi) && (IRIX > 602)
16 # include <sys/ptimers.h>
17 #endif
18 #include <stdio.h>
19 #include <string.h>
20 #if !defined(__SVR4) && !defined(__svr4__)
21 # include <strings.h>
22 #endif
23 #include <sys/types.h>
24 #include <sys/time.h>
25 #include <sys/param.h>
26 #include <sys/file.h>
27 #if defined(STATETOP)
28 # if defined(_BSDI_VERSION)
29 # undef STATETOP)
30 # endif
31 # if defined(__FreeBSD__) && \
32 (!defined(__FreeBSD_version) || (__FreeBSD_version < 430000))
33 # undef STATETOP
34 # endif
35 # if defined(__NetBSD_Version__)
36 # if (__NetBSD_Version__ < 105000000)
37 # undef STATETOP
38 # else
39 # include <poll.h>
40 # define USE_POLL
41 # endif
42 # endif
43 # if defined(sun)
44 # if defined(__svr4__) || defined(__SVR4)
45 # include <sys/select.h>
46 # else
47 # undef STATETOP /* NOT supported on SunOS4 */
48 # endif
49 # endif
50 #endif
51 #include <stdlib.h>
52 #include <unistd.h>
53 #include <fcntl.h>
54 #include <stddef.h>
55 #include <nlist.h>
56 #include <sys/socket.h>
57 #include <sys/ioctl.h>
58 #include <netinet/in.h>
59 #include <arpa/inet.h>
60 #include <netinet/in_systm.h>
61 #include <netinet/ip.h>
62 #include <net/if.h>
63 #if __FreeBSD_version >= 300000
64 # include <net/if_var.h>
65 #endif
66 #include <netdb.h>
67 #include <arpa/nameser.h>
68 #include <resolv.h>
69 #include <netinet/tcp.h>
70 #if defined(STATETOP) && !defined(linux)
71 # include <netinet/ip_var.h>
72 # include <netinet/tcp_fsm.h>
73 #endif
74 #include "netinet/ip_compat.h"
75 #include "netinet/ip_fil.h"
76 #include "ipf.h"
77 #include "netinet/ip_nat.h"
78 #include "netinet/ip_frag.h"
79 #include "netinet/ip_state.h"
80 #include "netinet/ip_proxy.h"
81 #include "netinet/ip_auth.h"
82 #ifdef STATETOP
83 # include "netinet/ipl.h"
84 # include <ctype.h>
85 # if SOLARIS || defined(__NetBSD__) || defined(_BSDI_VERSION) || \
86 defined(__sgi)
87 # ifdef ERR
88 # undef ERR
89 # endif
90 # include <curses.h>
91 # else /* SOLARIS */
92 # include <ncurses.h>
93 # endif /* SOLARIS */
94 #endif /* STATETOP */
95 #include "kmem.h"
96 #if defined(__NetBSD__) || (__OpenBSD__)
97 # include <paths.h>
98 #endif
100 #if !defined(lint)
101 static const char sccsid[] = "@(#)fils.c 1.21 4/20/96 (C) 1993-2000 Darren Reed";
102 static const char rcsid[] = "@(#)$Id: fils.c,v 2.21.2.45 2004/04/10 11:45:48 darrenr Exp $";
103 #endif
105 extern char *optarg;
106 extern int optind;
108 #define PRINTF (void)printf
109 #define FPRINTF (void)fprintf
110 #define F_IN 0
111 #define F_OUT 1
112 #define F_ACIN 2
113 #define F_ACOUT 3
114 static char *filters[4] = { "ipfilter(in)", "ipfilter(out)",
115 "ipacct(in)", "ipacct(out)" };
117 int opts = 0;
118 int use_inet6 = 0;
119 int live_kernel = 1;
120 int state_fd = -1;
121 int auth_fd = -1;
122 int ipf_fd = -1;
124 #ifdef STATETOP
125 #define STSTRSIZE 80
126 #define STGROWSIZE 16
127 #define HOSTNMLEN 40
129 #define STSORT_PR 0
130 #define STSORT_PKTS 1
131 #define STSORT_BYTES 2
132 #define STSORT_TTL 3
133 #define STSORT_SRCIP 4
134 #define STSORT_DSTIP 5
135 #define STSORT_MAX STSORT_DSTIP
136 #define STSORT_DEFAULT STSORT_BYTES
139 typedef struct statetop {
140 union i6addr st_src;
141 union i6addr st_dst;
142 u_short st_sport;
143 u_short st_dport;
144 u_char st_p;
145 u_char st_state[2];
146 U_QUAD_T st_pkts;
147 U_QUAD_T st_bytes;
148 u_long st_age;
149 } statetop_t;
150 #endif
152 extern int main __P((int, char *[]));
153 static void showstats __P((friostat_t *, u_32_t));
154 static void showfrstates __P((ipfrstat_t *));
155 static void showlist __P((friostat_t *));
156 static void showipstates __P((ips_stat_t *));
157 static void showauthstates __P((fr_authstat_t *));
158 static void showgroups __P((friostat_t *));
159 static void Usage __P((char *));
160 static void printlist __P((frentry_t *));
161 static void parse_ipportstr __P((const char *, struct in_addr *, int *));
162 static int ipfstate_live __P((char *, friostat_t **, ips_stat_t **,
163 ipfrstat_t **, fr_authstat_t **, u_32_t *));
164 static void ipfstate_dead __P((char *, friostat_t **, ips_stat_t **,
165 ipfrstat_t **, fr_authstat_t **, u_32_t *));
166 #ifdef STATETOP
167 static void topipstates __P((struct in_addr, struct in_addr, int, int, int, int, int));
168 static char *ttl_to_string __P((long));
169 static int sort_p __P((const void *, const void *));
170 static int sort_pkts __P((const void *, const void *));
171 static int sort_bytes __P((const void *, const void *));
172 static int sort_ttl __P((const void *, const void *));
173 static int sort_srcip __P((const void *, const void *));
174 static int sort_dstip __P((const void *, const void *));
175 #endif
176 #if SOLARIS
177 void showqiflist __P((char *));
178 #endif
181 static void Usage(name)
182 char *name;
184 #ifdef USE_INET6
185 fprintf(stderr, "Usage: %s [-6aAfhIinosv] [-d <device>]\n", name);
186 #else
187 fprintf(stderr, "Usage: %s [-aAfhIinosv] [-d <device>]\n", name);
188 #endif
189 fprintf(stderr, "\t\t[-M corefile] [-N symbol-list]\n");
190 fprintf(stderr, " %s -t [-S source address] [-D destination address] [-P protocol] [-T refreshtime] [-C] [-d <device>]\n", name);
191 exit(1);
195 int main(argc,argv)
196 int argc;
197 char *argv[];
199 fr_authstat_t frauthst;
200 fr_authstat_t *frauthstp = &frauthst;
201 friostat_t fio;
202 friostat_t *fiop = &fio;
203 ips_stat_t ipsst;
204 ips_stat_t *ipsstp = &ipsst;
205 ipfrstat_t ifrst;
206 ipfrstat_t *ifrstp = &ifrst;
207 char *device = IPL_NAME, *memf = NULL;
208 char *kern = NULL;
209 int c, myoptind;
210 struct protoent *proto;
212 int protocol = -1; /* -1 = wild card for any protocol */
213 int refreshtime = 1; /* default update time */
214 int sport = -1; /* -1 = wild card for any source port */
215 int dport = -1; /* -1 = wild card for any dest port */
216 int topclosed = 0; /* do not show closed tcp sessions */
217 struct in_addr saddr, daddr;
218 u_32_t frf;
220 saddr.s_addr = INADDR_ANY; /* default any source addr */
221 daddr.s_addr = INADDR_ANY; /* default any dest addr */
224 * Parse these two arguments now lest there be any buffer overflows
225 * in the parsing of the rest.
227 myoptind = optind;
228 while ((c = getopt(argc, argv, "6aACfghIilnoqstvd:D:M:N:P:S:T:")) != -1)
229 switch (c)
231 case 'M' :
232 memf = optarg;
233 live_kernel = 0;
234 break;
235 case 'N' :
236 kern = optarg;
237 live_kernel = 0;
238 break;
240 optind = myoptind;
242 if (live_kernel == 1) {
243 if ((state_fd = open(IPL_STATE, O_RDONLY)) == -1) {
244 perror("open");
245 exit(-1);
247 if ((auth_fd = open(IPL_AUTH, O_RDONLY)) == -1) {
248 perror("open");
249 exit(-1);
251 if ((ipf_fd = open(device, O_RDONLY)) == -1) {
252 perror("open");
253 exit(-1);
257 if (kern != NULL || memf != NULL)
259 (void)setuid(getuid());
260 (void)setgid(getgid());
263 if (openkmem(kern, memf) == -1)
264 exit(-1);
266 (void)setuid(getuid());
267 (void)setgid(getgid());
269 while ((c = getopt(argc, argv, "6aACfghIilnoqstvd:D:M:N:P:S:T:")) != -1)
271 switch (c)
273 #ifdef USE_INET6
274 case '6' :
275 use_inet6 = 1;
276 break;
277 #endif
278 case 'a' :
279 opts |= OPT_ACCNT|OPT_SHOWLIST;
280 break;
281 case 'A' :
282 device = IPAUTH_NAME;
283 opts |= OPT_AUTHSTATS;
284 break;
285 case 'C' :
286 topclosed = 1;
287 break;
288 case 'd' :
289 device = optarg;
290 break;
291 case 'D' :
292 parse_ipportstr(optarg, &daddr, &dport);
293 break;
294 case 'f' :
295 opts |= OPT_FRSTATES;
296 break;
297 case 'g' :
298 opts |= OPT_GROUPS;
299 break;
300 case 'h' :
301 opts |= OPT_HITS;
302 break;
303 case 'i' :
304 opts |= OPT_INQUE|OPT_SHOWLIST;
305 break;
306 case 'I' :
307 opts |= OPT_INACTIVE;
308 break;
309 case 'l' :
310 opts |= OPT_SHOWLIST;
311 break;
312 case 'M' :
313 break;
314 case 'N' :
315 break;
316 case 'n' :
317 opts |= OPT_SHOWLINENO;
318 break;
319 case 'o' :
320 opts |= OPT_OUTQUE|OPT_SHOWLIST;
321 break;
322 case 'P' :
323 if ((proto = getprotobyname(optarg)) != NULL) {
324 protocol = proto->p_proto;
325 } else if (!sscanf(optarg, "%ud", &protocol) ||
326 (protocol < 0)) {
327 fprintf(stderr, "%s : Invalid protocol: %s\n",
328 argv[0], optarg);
329 exit(-2);
331 break;
332 case 'q' :
333 #if SOLARIS
334 showqiflist(kern);
335 exit(0);
336 break;
337 #else
338 fprintf(stderr, "-q only availble on Solaris\n");
339 exit(1);
340 break;
341 #endif
342 case 's' :
343 opts |= OPT_IPSTATES;
344 break;
345 case 'S' :
346 parse_ipportstr(optarg, &saddr, &sport);
347 break;
348 case 't' :
349 #ifdef STATETOP
350 opts |= OPT_STATETOP;
351 break;
352 #else
353 fprintf(stderr,
354 "%s : state top facility not compiled in\n",
355 argv[0]);
356 exit(-2);
357 #endif
358 case 'T' :
359 if (!sscanf(optarg, "%d", &refreshtime) ||
360 (refreshtime <= 0)) {
361 fprintf(stderr,
362 "%s : Invalid refreshtime < 1 : %s\n",
363 argv[0], optarg);
364 exit(-2);
366 break;
367 case 'v' :
368 opts |= OPT_VERBOSE;
369 break;
370 default :
371 Usage(argv[0]);
372 break;
376 if (live_kernel == 1) {
377 bzero((char *)&fio, sizeof(fio));
378 bzero((char *)&ipsst, sizeof(ipsst));
379 bzero((char *)&ifrst, sizeof(ifrst));
381 ipfstate_live(device, &fiop, &ipsstp, &ifrstp,
382 &frauthstp, &frf);
383 } else
384 ipfstate_dead(kern, &fiop, &ipsstp, &ifrstp, &frauthstp, &frf);
386 if (opts & OPT_IPSTATES) {
387 showipstates(ipsstp);
388 } else if (opts & OPT_SHOWLIST) {
389 showlist(fiop);
390 if ((opts & OPT_OUTQUE) && (opts & OPT_INQUE)){
391 opts &= ~OPT_OUTQUE;
392 showlist(fiop);
394 } else {
395 if (opts & OPT_FRSTATES)
396 showfrstates(ifrstp);
397 #ifdef STATETOP
398 else if (opts & OPT_STATETOP)
399 topipstates(saddr, daddr, sport, dport,
400 protocol, refreshtime, topclosed);
401 #endif
402 else if (opts & OPT_AUTHSTATS)
403 showauthstates(frauthstp);
404 else if (opts & OPT_GROUPS)
405 showgroups(fiop);
406 else
407 showstats(fiop, frf);
409 return 0;
414 * Fill in the stats structures from the live kernel, using a combination
415 * of ioctl's and copying directly from kernel memory.
417 int ipfstate_live(device, fiopp, ipsstpp, ifrstpp, frauthstpp, frfp)
418 char *device;
419 friostat_t **fiopp;
420 ips_stat_t **ipsstpp;
421 ipfrstat_t **ifrstpp;
422 fr_authstat_t **frauthstpp;
423 u_32_t *frfp;
426 if (!(opts & OPT_AUTHSTATS) && ioctl(ipf_fd, SIOCGETFS, fiopp) == -1) {
427 perror("ioctl(ipf:SIOCGETFS)");
428 exit(-1);
431 if ((opts & OPT_IPSTATES)) {
432 if ((ioctl(state_fd, SIOCGETFS, ipsstpp) == -1)) {
433 perror("ioctl(state:SIOCGETFS)");
434 exit(-1);
437 if ((opts & OPT_FRSTATES) &&
438 (ioctl(ipf_fd, SIOCGFRST, ifrstpp) == -1)) {
439 perror("ioctl(SIOCGFRST)");
440 exit(-1);
443 if (opts & OPT_VERBOSE)
444 PRINTF("opts %#x name %s\n", opts, device);
446 if ((opts & OPT_AUTHSTATS) &&
447 (ioctl(auth_fd, SIOCATHST, frauthstpp) == -1)) {
448 perror("ioctl(SIOCATHST)");
449 exit(-1);
452 if (ioctl(ipf_fd, SIOCGETFF, frfp) == -1)
453 perror("ioctl(SIOCGETFF)");
455 return ipf_fd;
460 * Build up the stats structures from data held in the "core" memory.
461 * This is mainly useful when looking at data in crash dumps and ioctl's
462 * just won't work any more.
464 void ipfstate_dead(kernel, fiopp, ipsstpp, ifrstpp, frauthstpp, frfp)
465 char *kernel;
466 friostat_t **fiopp;
467 ips_stat_t **ipsstpp;
468 ipfrstat_t **ifrstpp;
469 fr_authstat_t **frauthstpp;
470 u_32_t *frfp;
472 static fr_authstat_t frauthst, *frauthstp;
473 static ips_stat_t ipsst, *ipsstp;
474 static ipfrstat_t ifrst, *ifrstp;
475 static friostat_t fio, *fiop;
477 void *rules[2][2];
478 struct nlist deadlist[42] = {
479 { "fr_authstats" }, /* 0 */
480 { "fae_list" },
481 { "ipauth" },
482 { "fr_authlist" },
483 { "fr_authstart" },
484 { "fr_authend" }, /* 5 */
485 { "fr_authnext" },
486 { "fr_auth" },
487 { "fr_authused" },
488 { "fr_authsize" },
489 { "fr_defaultauthage" }, /* 10 */
490 { "fr_authpkts" },
491 { "fr_auth_lock" },
492 { "frstats" },
493 { "ips_stats" },
494 { "ips_num" }, /* 15 */
495 { "ips_wild" },
496 { "ips_list" },
497 { "ips_table" },
498 { "fr_statemax" },
499 { "fr_statesize" }, /* 20 */
500 { "fr_state_doflush" },
501 { "fr_state_lock" },
502 { "ipfr_heads" },
503 { "ipfr_nattab" },
504 { "ipfr_stats" }, /* 25 */
505 { "ipfr_inuse" },
506 { "fr_ipfrttl" },
507 { "fr_frag_lock" },
508 { "ipfr_timer_id" },
509 { "fr_nat_lock" }, /* 30 */
510 { "ipfilter" },
511 { "ipfilter6" },
512 { "ipacct" },
513 { "ipacct6" },
514 { "ipl_frouteok" }, /* 35 */
515 { "fr_running" },
516 { "ipfgroups" },
517 { "fr_active" },
518 { "fr_pass" },
519 { "fr_flags" }, /* 40 */
520 { NULL }
524 frauthstp = &frauthst;
525 ipsstp = &ipsst;
526 ifrstp = &ifrst;
527 fiop = &fio;
529 *frfp = 0;
530 *fiopp = fiop;
531 *ipsstpp = ipsstp;
532 *ifrstpp = ifrstp;
533 *frauthstpp = frauthstp;
535 bzero((char *)fiop, sizeof(*fiop));
536 bzero((char *)ipsstp, sizeof(*ipsstp));
537 bzero((char *)ifrstp, sizeof(*ifrstp));
538 bzero((char *)frauthstp, sizeof(*frauthstp));
540 if (nlist(kernel, deadlist) == -1) {
541 fprintf(stderr, "nlist error\n");
542 return;
546 * This is for SIOCGETFF.
548 kmemcpy((char *)frfp, (u_long)deadlist[40].n_value, sizeof(*frfp));
551 * f_locks is a combination of the lock variable from each part of
552 * ipfilter (state, auth, nat, fragments).
554 kmemcpy((char *)fiop, (u_long)deadlist[13].n_value, sizeof(*fiop));
555 kmemcpy((char *)&fiop->f_locks[0], (u_long)deadlist[22].n_value,
556 sizeof(fiop->f_locks[0]));
557 kmemcpy((char *)&fiop->f_locks[0], (u_long)deadlist[30].n_value,
558 sizeof(fiop->f_locks[1]));
559 kmemcpy((char *)&fiop->f_locks[2], (u_long)deadlist[28].n_value,
560 sizeof(fiop->f_locks[2]));
561 kmemcpy((char *)&fiop->f_locks[3], (u_long)deadlist[12].n_value,
562 sizeof(fiop->f_locks[3]));
565 * Get pointers to each list of rules (active, inactive, in, out)
567 kmemcpy((char *)&rules, (u_long)deadlist[31].n_value, sizeof(rules));
568 fiop->f_fin[0] = rules[0][0];
569 fiop->f_fin[1] = rules[0][1];
570 fiop->f_fout[0] = rules[1][0];
571 fiop->f_fout[1] = rules[1][1];
574 * Same for IPv6, except make them null if support for it is not
575 * being compiled in.
577 #ifdef USE_INET6
578 kmemcpy((char *)&rules, (u_long)deadlist[32].n_value, sizeof(rules));
579 fiop->f_fin6[0] = rules[0][0];
580 fiop->f_fin6[1] = rules[0][1];
581 fiop->f_fout6[0] = rules[1][0];
582 fiop->f_fout6[1] = rules[1][1];
583 #else
584 fiop->f_fin6[0] = NULL;
585 fiop->f_fin6[1] = NULL;
586 fiop->f_fout6[0] = NULL;
587 fiop->f_fout6[1] = NULL;
588 #endif
591 * Now get accounting rules pointers.
593 kmemcpy((char *)&rules, (u_long)deadlist[33].n_value, sizeof(rules));
594 fiop->f_acctin[0] = rules[0][0];
595 fiop->f_acctin[1] = rules[0][1];
596 fiop->f_acctout[0] = rules[1][0];
597 fiop->f_acctout[1] = rules[1][1];
599 #ifdef USE_INET6
600 kmemcpy((char *)&rules, (u_long)deadlist[34].n_value, sizeof(rules));
601 fiop->f_acctin6[0] = rules[0][0];
602 fiop->f_acctin6[1] = rules[0][1];
603 fiop->f_acctout6[0] = rules[1][0];
604 fiop->f_acctout6[1] = rules[1][1];
605 #else
606 fiop->f_acctin6[0] = NULL;
607 fiop->f_acctin6[1] = NULL;
608 fiop->f_acctout6[0] = NULL;
609 fiop->f_acctout6[1] = NULL;
610 #endif
613 * A collection of "global" variables used inside the kernel which
614 * are all collected in friostat_t via ioctl.
616 kmemcpy((char *)&fiop->f_froute, (u_long)deadlist[35].n_value,
617 sizeof(fiop->f_froute));
618 kmemcpy((char *)&fiop->f_running, (u_long)deadlist[36].n_value,
619 sizeof(fiop->f_running));
620 kmemcpy((char *)&fiop->f_groups, (u_long)deadlist[37].n_value,
621 sizeof(fiop->f_groups));
622 kmemcpy((char *)&fiop->f_active, (u_long)deadlist[38].n_value,
623 sizeof(fiop->f_active));
624 kmemcpy((char *)&fiop->f_defpass, (u_long)deadlist[39].n_value,
625 sizeof(fiop->f_defpass));
628 * Build up the state information stats structure.
630 kmemcpy((char *)ipsstp, (u_long)deadlist[14].n_value, sizeof(*ipsstp));
631 kmemcpy((char *)&ipsstp->iss_active, (u_long)deadlist[15].n_value,
632 sizeof(ipsstp->iss_active));
633 ipsstp->iss_table = (void *)deadlist[18].n_value;
634 ipsstp->iss_list = (void *)deadlist[17].n_value;
637 * Build up the authentiation information stats structure.
639 kmemcpy((char *)frauthstp, (u_long)deadlist[0].n_value,
640 sizeof(*frauthstp));
641 frauthstp->fas_faelist = (void *)deadlist[1].n_value;
644 * Build up the fragment information stats structure.
646 kmemcpy((char *)ifrstp, (u_long)deadlist[25].n_value,
647 sizeof(*ifrstp));
648 ifrstp->ifs_table = (void *)deadlist[23].n_value;
649 ifrstp->ifs_nattab = (void *)deadlist[24].n_value;
650 kmemcpy((char *)&ifrstp->ifs_inuse, (u_long)deadlist[26].n_value,
651 sizeof(ifrstp->ifs_inuse));
656 * Display the kernel stats for packets blocked and passed and other
657 * associated running totals which are kept.
659 static void showstats(fp, frf)
660 struct friostat *fp;
661 u_32_t frf;
664 #if SOLARIS
665 PRINTF("dropped packets:\tin %lu\tout %lu\n",
666 fp->f_st[0].fr_drop, fp->f_st[1].fr_drop);
667 PRINTF("non-data packets:\tin %lu\tout %lu\n",
668 fp->f_st[0].fr_notdata, fp->f_st[1].fr_notdata);
669 PRINTF("no-data packets:\tin %lu\tout %lu\n",
670 fp->f_st[0].fr_nodata, fp->f_st[1].fr_nodata);
671 PRINTF("non-ip packets:\t\tin %lu\tout %lu\n",
672 fp->f_st[0].fr_notip, fp->f_st[1].fr_notip);
673 PRINTF(" bad packets:\t\tin %lu\tout %lu\n",
674 fp->f_st[0].fr_bad, fp->f_st[1].fr_bad);
675 PRINTF("copied messages:\tin %lu\tout %lu\n",
676 fp->f_st[0].fr_copy, fp->f_st[1].fr_copy);
677 #endif
678 #ifdef USE_INET6
679 PRINTF(" IPv6 packets:\t\tin %lu out %lu\n",
680 fp->f_st[0].fr_ipv6[0], fp->f_st[0].fr_ipv6[1]);
681 #endif
682 PRINTF(" input packets:\t\tblocked %lu passed %lu nomatch %lu",
683 fp->f_st[0].fr_block, fp->f_st[0].fr_pass,
684 fp->f_st[0].fr_nom);
685 PRINTF(" counted %lu short %lu\n",
686 fp->f_st[0].fr_acct, fp->f_st[0].fr_short);
687 PRINTF("output packets:\t\tblocked %lu passed %lu nomatch %lu",
688 fp->f_st[1].fr_block, fp->f_st[1].fr_pass,
689 fp->f_st[1].fr_nom);
690 PRINTF(" counted %lu short %lu\n",
691 fp->f_st[1].fr_acct, fp->f_st[1].fr_short);
692 PRINTF(" input packets logged:\tblocked %lu passed %lu\n",
693 fp->f_st[0].fr_bpkl, fp->f_st[0].fr_ppkl);
694 PRINTF("output packets logged:\tblocked %lu passed %lu\n",
695 fp->f_st[1].fr_bpkl, fp->f_st[1].fr_ppkl);
696 PRINTF(" packets logged:\tinput %lu output %lu\n",
697 fp->f_st[0].fr_pkl, fp->f_st[1].fr_pkl);
698 PRINTF(" log failures:\t\tinput %lu output %lu\n",
699 fp->f_st[0].fr_skip, fp->f_st[1].fr_skip);
700 PRINTF("fragment state(in):\tkept %lu\tlost %lu\tnot fragmented %lu\n",
701 fp->f_st[0].fr_nfr, fp->f_st[0].fr_bnfr, fp->f_st[0].fr_cfr);
702 PRINTF("fragment state(out):\tkept %lu\tlost %lu\tnot fragmented %lu\n",
703 fp->f_st[1].fr_nfr, fp->f_st[1].fr_bnfr, fp->f_st[1].fr_cfr);
704 PRINTF("packet state(in):\tkept %lu\tlost %lu\n",
705 fp->f_st[0].fr_ads, fp->f_st[0].fr_bads);
706 PRINTF("packet state(out):\tkept %lu\tlost %lu\n",
707 fp->f_st[1].fr_ads, fp->f_st[1].fr_bads);
708 PRINTF("ICMP replies:\t%lu\tTCP RSTs sent:\t%lu\n",
709 fp->f_st[0].fr_ret, fp->f_st[1].fr_ret);
710 PRINTF("Invalid source(in):\t%lu\n", fp->f_st[0].fr_badsrc);
711 PRINTF("Result cache hits(in):\t%lu\t(out):\t%lu\n",
712 fp->f_st[0].fr_chit, fp->f_st[1].fr_chit);
713 PRINTF("IN Pullups succeeded:\t%lu\tfailed:\t%lu\n",
714 fp->f_st[0].fr_pull[0], fp->f_st[0].fr_pull[1]);
715 PRINTF("OUT Pullups succeeded:\t%lu\tfailed:\t%lu\n",
716 fp->f_st[1].fr_pull[0], fp->f_st[1].fr_pull[1]);
717 PRINTF("Fastroute successes:\t%lu\tfailures:\t%lu\n",
718 fp->f_froute[0], fp->f_froute[1]);
719 PRINTF("TCP cksum fails(in):\t%lu\t(out):\t%lu\n",
720 fp->f_st[0].fr_tcpbad, fp->f_st[1].fr_tcpbad);
722 PRINTF("Packet log flags set: (%#x)\n", frf);
723 if (frf & FF_LOGPASS)
724 PRINTF("\tpackets passed through filter\n");
725 if (frf & FF_LOGBLOCK)
726 PRINTF("\tpackets blocked by filter\n");
727 if (frf & FF_LOGNOMATCH)
728 PRINTF("\tpackets not matched by filter\n");
729 if (!frf)
730 PRINTF("\tnone\n");
735 * Print out a list of rules from the kernel, starting at the one passed.
737 static void printlist(fp)
738 frentry_t *fp;
740 struct frentry fb;
741 int n;
743 for (n = 1; fp; n++) {
744 if (kmemcpy((char *)&fb, (u_long)fp, sizeof(fb)) == -1) {
745 perror("kmemcpy");
746 return;
748 fp = &fb;
749 if (opts & OPT_OUTQUE)
750 fp->fr_flags |= FR_OUTQUE;
751 if (opts & (OPT_HITS|OPT_VERBOSE))
752 #ifdef USE_QUAD_T
753 PRINTF("%qu ", (unsigned long long) fp->fr_hits);
754 #else
755 PRINTF("%lu ", fp->fr_hits);
756 #endif
757 if (opts & (OPT_ACCNT|OPT_VERBOSE))
758 #ifdef USE_QUAD_T
759 PRINTF("%qu ", (unsigned long long) fp->fr_bytes);
760 #else
761 PRINTF("%lu ", fp->fr_bytes);
762 #endif
763 if (opts & OPT_SHOWLINENO)
764 PRINTF("@%d ", n);
765 printfr(fp);
766 if (opts & OPT_VERBOSE)
767 binprint(fp);
768 if (fp->fr_grp)
769 printlist(fp->fr_grp);
770 fp = fp->fr_next;
775 * print out all of the asked for rule sets, using the stats struct as
776 * the base from which to get the pointers.
778 static void showlist(fiop)
779 struct friostat *fiop;
781 struct frentry *fp = NULL;
782 int i, set;
784 set = fiop->f_active;
785 if (opts & OPT_INACTIVE)
786 set = 1 - set;
787 if (opts & OPT_ACCNT) {
788 #ifdef USE_INET6
789 if ((use_inet6) && (opts & OPT_OUTQUE)) {
790 i = F_ACOUT;
791 fp = (struct frentry *)fiop->f_acctout6[set];
792 } else if ((use_inet6) && (opts & OPT_INQUE)) {
793 i = F_ACIN;
794 fp = (struct frentry *)fiop->f_acctin6[set];
795 } else
796 #endif
797 if (opts & OPT_OUTQUE) {
798 i = F_ACOUT;
799 fp = (struct frentry *)fiop->f_acctout[set];
800 } else if (opts & OPT_INQUE) {
801 i = F_ACIN;
802 fp = (struct frentry *)fiop->f_acctin[set];
803 } else {
804 FPRINTF(stderr, "No -i or -o given with -a\n");
805 return;
807 } else {
808 #ifdef USE_INET6
809 if ((use_inet6) && (opts & OPT_OUTQUE)) {
810 i = F_OUT;
811 fp = (struct frentry *)fiop->f_fout6[set];
812 } else if ((use_inet6) && (opts & OPT_INQUE)) {
813 i = F_IN;
814 fp = (struct frentry *)fiop->f_fin6[set];
815 } else
816 #endif
817 if (opts & OPT_OUTQUE) {
818 i = F_OUT;
819 fp = (struct frentry *)fiop->f_fout[set];
820 } else if (opts & OPT_INQUE) {
821 i = F_IN;
822 fp = (struct frentry *)fiop->f_fin[set];
823 } else
824 return;
826 if (opts & OPT_VERBOSE)
827 FPRINTF(stderr, "showlist:opts %#x i %d\n", opts, i);
829 if (opts & OPT_VERBOSE)
830 PRINTF("fp %p set %d\n", fp, set);
831 if (fp == NULL) {
832 FPRINTF(stderr, "empty list for %s%s\n",
833 (opts & OPT_INACTIVE) ? "inactive " : "", filters[i]);
834 return;
836 printlist(fp);
841 * Display ipfilter stateful filtering information
843 static void showipstates(ipsp)
844 ips_stat_t *ipsp;
846 ipstate_t *istab[IPSTATE_SIZE];
849 * If a list of states hasn't been asked for, only print out stats
851 if (!(opts & OPT_SHOWLIST)) {
852 PRINTF("IP states added:\n\t%lu TCP\n\t%lu UDP\n\t%lu ICMP\n",
853 ipsp->iss_tcp, ipsp->iss_udp, ipsp->iss_icmp);
854 PRINTF("\t%lu hits\n\t%lu misses\n", ipsp->iss_hits,
855 ipsp->iss_miss);
856 PRINTF("\t%lu maximum\n\t%lu no memory\n\t%lu bkts in use\n",
857 ipsp->iss_max, ipsp->iss_nomem, ipsp->iss_inuse);
858 PRINTF("\t%lu logged\n\t%lu log failures\n",
859 ipsp->iss_logged, ipsp->iss_logfail);
860 PRINTF("\t%lu active\n\t%lu expired\n\t%lu closed\n",
861 ipsp->iss_active, ipsp->iss_expire, ipsp->iss_fin);
862 return;
865 if (kmemcpy((char *)istab, (u_long)ipsp->iss_table, sizeof(istab)))
866 return;
869 * Print out all the state information currently held in the kernel.
871 while (ipsp->iss_list != NULL) {
872 ipsp->iss_list = printstate(ipsp->iss_list, opts);
877 #if SOLARIS
879 * Displays the list of interfaces of which IPFilter has taken control in
880 * Solaris.
882 void showqiflist(kern)
883 char *kern;
885 struct nlist qifnlist[2] = {
886 { "_qif_head" },
887 { NULL }
889 qif_t qif, *qf;
890 ill_t ill;
892 if (kern == NULL)
893 kern = "/dev/ksyms";
895 if (nlist(kern, qifnlist) == -1) {
896 fprintf(stderr, "nlist error\n");
897 return;
900 printf("List of interfaces bound by IPFilter:\n");
901 if (kmemcpy((char *)&qf, (u_long)qifnlist[0].n_value, sizeof(qf)))
902 return;
903 while (qf) {
904 if (kmemcpy((char *)&qif, (u_long)qf, sizeof(qif)))
905 break;
906 if (kmemcpy((char *)&ill, (u_long)qif.qf_ill, sizeof(ill)))
907 ill.ill_ppa = -1;
908 printf("Name: %-8s Header Length: %2d SAP: %s (%04x) PPA %d",
909 qif.qf_name, qif.qf_hl,
910 #ifdef IP6_DL_SAP
911 (qif.qf_sap == IP6_DL_SAP) ? "IPv6" : "IPv4"
912 #else
913 "IPv4"
914 #endif
915 , qif.qf_sap, ill.ill_ppa);
916 printf(" %ld %ld", qif.qf_incnt, qif.qf_outcnt);
917 qf = qif.qf_next;
918 putchar('\n');
921 #endif
924 #ifdef STATETOP
925 static void topipstates(saddr, daddr, sport, dport, protocol,
926 refreshtime, topclosed)
927 struct in_addr saddr;
928 struct in_addr daddr;
929 int sport;
930 int dport;
931 int protocol;
932 int refreshtime;
933 int topclosed;
935 char str1[STSTRSIZE], str2[STSTRSIZE], str3[STSTRSIZE], str4[STSTRSIZE];
936 int maxtsentries = 0, reverse = 0, sorting = STSORT_DEFAULT;
937 int i, j, winx, tsentry, maxx, maxy, redraw = 0;
938 ipstate_t *istab[IPSTATE_SIZE], ips;
939 ips_stat_t ipsst, *ipsstp = &ipsst;
940 statetop_t *tstable = NULL, *tp;
941 char hostnm[HOSTNMLEN];
942 struct protoent *proto;
943 int c = 0;
944 time_t t;
945 #ifdef USE_POLL
946 struct pollfd set[1];
947 #else
948 struct timeval selecttimeout;
949 fd_set readfd;
950 #endif
952 /* init ncurses stuff */
953 initscr();
954 cbreak();
955 noecho();
957 /* init hostname */
958 gethostname(hostnm, sizeof(hostnm) - 1);
959 hostnm[sizeof(hostnm) - 1] = '\0';
961 /* repeat until user aborts */
962 while ( 1 ) {
964 /* get state table */
965 bzero((char *)&ipsst, sizeof(&ipsst));
966 if ((ioctl(state_fd, SIOCGETFS, &ipsstp) == -1)) {
967 perror("ioctl(SIOCGETFS)");
968 exit(-1);
970 if (kmemcpy((char *)istab, (u_long)ipsstp->iss_table,
971 sizeof(ips)))
972 return;
974 /* clear the history */
975 tsentry = -1;
977 /* read the state table and store in tstable */
978 while (ipsstp->iss_list) {
979 if (kmemcpy((char *)&ips, (u_long)ipsstp->iss_list,
980 sizeof(ips)))
981 break;
982 ipsstp->iss_list = ips.is_next;
984 if (((saddr.s_addr == INADDR_ANY) ||
985 (saddr.s_addr == ips.is_saddr)) &&
986 ((daddr.s_addr == INADDR_ANY) ||
987 (daddr.s_addr == ips.is_daddr)) &&
988 ((protocol < 0) || (protocol == ips.is_p)) &&
989 (((ips.is_p != IPPROTO_TCP) &&
990 (ips.is_p != IPPROTO_UDP)) ||
991 (((sport < 0) ||
992 (htons(sport) == ips.is_sport)) &&
993 ((dport < 0) ||
994 (htons(dport) == ips.is_dport)))) &&
995 (topclosed || (ips.is_p != IPPROTO_TCP) ||
996 (ips.is_state[0] < TCPS_LAST_ACK) ||
997 (ips.is_state[1] < TCPS_LAST_ACK))) {
999 * if necessary make room for this state
1000 * entry
1002 tsentry++;
1003 if (!maxtsentries ||
1004 (tsentry == maxtsentries)) {
1006 maxtsentries += STGROWSIZE;
1007 tstable = realloc(tstable, maxtsentries * sizeof(statetop_t));
1008 if (!tstable) {
1009 perror("malloc");
1010 exit(-1);
1014 /* fill structure */
1015 tp = tstable + tsentry;
1016 tp->st_src = ips.is_src;
1017 tp->st_dst = ips.is_dst;
1018 tp->st_p = ips.is_p;
1019 tp->st_state[0] = ips.is_state[0];
1020 tp->st_state[1] = ips.is_state[1];
1021 tp->st_pkts = ips.is_pkts;
1022 tp->st_bytes = ips.is_bytes;
1023 tp->st_age = ips.is_age;
1024 if ((ips.is_p == IPPROTO_TCP) ||
1025 (ips.is_p == IPPROTO_UDP)) {
1026 tp->st_sport = ips.is_sport;
1027 tp->st_dport = ips.is_dport;
1034 /* sort the array */
1035 if (tsentry != -1)
1036 switch (sorting)
1038 case STSORT_PR:
1039 qsort(tstable, tsentry + 1,
1040 sizeof(statetop_t), sort_p);
1041 break;
1042 case STSORT_PKTS:
1043 qsort(tstable, tsentry + 1,
1044 sizeof(statetop_t), sort_pkts);
1045 break;
1046 case STSORT_BYTES:
1047 qsort(tstable, tsentry + 1,
1048 sizeof(statetop_t), sort_bytes);
1049 break;
1050 case STSORT_TTL:
1051 qsort(tstable, tsentry + 1,
1052 sizeof(statetop_t), sort_ttl);
1053 break;
1054 case STSORT_SRCIP:
1055 qsort(tstable, tsentry + 1,
1056 sizeof(statetop_t), sort_srcip);
1057 break;
1058 case STSORT_DSTIP:
1059 qsort(tstable, tsentry + 1,
1060 sizeof(statetop_t), sort_dstip);
1061 break;
1062 default:
1063 break;
1066 /* print title */
1067 erase();
1068 getmaxyx(stdscr, maxy, maxx);
1069 attron(A_BOLD);
1070 winx = 0;
1071 move(winx,0);
1072 sprintf(str1, "%s - %s - state top", hostnm, IPL_VERSION);
1073 for (j = 0 ; j < (maxx - 8 - strlen(str1)) / 2; j++)
1074 printw(" ");
1075 printw("%s", str1);
1076 attroff(A_BOLD);
1078 /* just for fun add a clock */
1079 move(winx, maxx - 8);
1080 t = time(NULL);
1081 strftime(str1, 80, "%T", localtime(&t));
1082 printw("%s\n", str1);
1085 * print the display filters, this is placed in the loop,
1086 * because someday I might add code for changing these
1087 * while the programming is running :-)
1089 if (sport >= 0)
1090 sprintf(str1, "%s,%d", inet_ntoa(saddr), sport);
1091 else
1092 sprintf(str1, "%s", inet_ntoa(saddr));
1094 if (dport >= 0)
1095 sprintf(str2, "%s,%d", inet_ntoa(daddr), dport);
1096 else
1097 sprintf(str2, "%s", inet_ntoa(daddr));
1099 if (protocol < 0)
1100 strcpy(str3, "any");
1101 else if ((proto = getprotobynumber(protocol)) != NULL)
1102 sprintf(str3, "%s", proto->p_name);
1103 else
1104 sprintf(str3, "%d", protocol);
1106 switch (sorting)
1108 case STSORT_PR:
1109 sprintf(str4, "proto");
1110 break;
1111 case STSORT_PKTS:
1112 sprintf(str4, "# pkts");
1113 break;
1114 case STSORT_BYTES:
1115 sprintf(str4, "# bytes");
1116 break;
1117 case STSORT_TTL:
1118 sprintf(str4, "ttl");
1119 break;
1120 case STSORT_SRCIP:
1121 sprintf(str4, "srcip");
1122 break;
1123 case STSORT_DSTIP:
1124 sprintf(str4, "dstip");
1125 break;
1126 default:
1127 sprintf(str4, "unknown");
1128 break;
1131 if (reverse)
1132 strcat(str4, " (reverse)");
1134 winx += 2;
1135 move(winx,0);
1136 printw("Src = %s Dest = %s Proto = %s Sorted by = %s\n\n",
1137 str1, str2, str3, str4);
1139 /* print column description */
1140 winx += 2;
1141 move(winx,0);
1142 attron(A_BOLD);
1143 printw("%-21s %-21s %3s %4s %7s %9s %9s\n", "Source IP",
1144 "Destination IP", "ST", "PR", "#pkts", "#bytes", "ttl");
1145 attroff(A_BOLD);
1147 /* print all the entries */
1148 tp = tstable;
1149 if (reverse)
1150 tp += tsentry;
1152 if (tsentry > maxy - 6)
1153 tsentry = maxy - 6;
1154 for (i = 0; i <= tsentry; i++) {
1155 /* print src/dest and port */
1156 if ((tp->st_p == IPPROTO_TCP) ||
1157 (tp->st_p == IPPROTO_UDP)) {
1158 sprintf(str1, "%s,%hu",
1159 inet_ntoa(tp->st_src.in4),
1160 ntohs(tp->st_sport));
1161 sprintf(str2, "%s,%hu",
1162 inet_ntoa(tp->st_dst.in4),
1163 ntohs(tp->st_dport));
1164 } else {
1165 sprintf(str1, "%s", inet_ntoa(tp->st_src.in4));
1166 sprintf(str2, "%s", inet_ntoa(tp->st_dst.in4));
1168 winx++;
1169 move(winx, 0);
1170 printw("%-21s %-21s", str1, str2);
1172 /* print state */
1173 sprintf(str1, "%X/%X", tp->st_state[0],
1174 tp->st_state[1]);
1175 printw(" %3s", str1);
1177 /* print proto */
1178 proto = getprotobynumber(tp->st_p);
1179 if (proto) {
1180 strncpy(str1, proto->p_name, 4);
1181 str1[4] = '\0';
1182 } else {
1183 sprintf(str1, "%d", tp->st_p);
1185 printw(" %4s", str1);
1186 /* print #pkt/#bytes */
1187 #ifdef USE_QUAD_T
1188 printw(" %7qu %9qu", (unsigned long long) tp->st_pkts,
1189 (unsigned long long) tp->st_bytes);
1190 #else
1191 printw(" %7lu %9lu", tp->st_pkts, tp->st_bytes);
1192 #endif
1193 printw(" %9s", ttl_to_string(tp->st_age));
1195 if (reverse)
1196 tp--;
1197 else
1198 tp++;
1201 /* screen data structure is filled, now update the screen */
1202 if (redraw)
1203 clearok(stdscr,1);
1205 refresh();
1206 if (redraw) {
1207 clearok(stdscr,0);
1208 redraw = 0;
1211 /* wait for key press or a 1 second time out period */
1212 #ifdef USE_POLL
1213 set[0].fd = 0;
1214 set[0].events = POLLIN;
1215 poll(set, 1, refreshtime * 1000);
1217 /* if key pressed, read all waiting keys */
1218 if (set[0].revents & POLLIN)
1219 #else
1220 selecttimeout.tv_sec = refreshtime;
1221 selecttimeout.tv_usec = 0;
1222 FD_ZERO(&readfd);
1223 FD_SET(0, &readfd);
1224 select(1, &readfd, NULL, NULL, &selecttimeout);
1226 /* if key pressed, read all waiting keys */
1227 if (FD_ISSET(0, &readfd))
1228 #endif
1231 c = wgetch(stdscr);
1232 if (c == ERR)
1233 continue;
1235 if (isalpha(c) && isupper(c))
1236 c = tolower(c);
1237 if (c == 'l') {
1238 redraw = 1;
1239 } else if (c == 'q') {
1240 break; /* exits while() loop */
1241 } else if (c == 'r') {
1242 reverse = !reverse;
1243 } else if (c == 's') {
1244 sorting++;
1245 if (sorting > STSORT_MAX)
1246 sorting = 0;
1249 } /* while */
1251 printw("\n");
1252 nocbreak();
1253 endwin();
1255 #endif
1259 * Show fragment cache information that's held in the kernel.
1261 static void showfrstates(ifsp)
1262 ipfrstat_t *ifsp;
1264 struct ipfr *ipfrtab[IPFT_SIZE], ifr;
1265 frentry_t fr;
1266 int i;
1269 * print out the numeric statistics
1271 PRINTF("IP fragment states:\n\t%lu new\n\t%lu expired\n\t%lu hits\n",
1272 ifsp->ifs_new, ifsp->ifs_expire, ifsp->ifs_hits);
1273 PRINTF("\t%lu no memory\n\t%lu already exist\n",
1274 ifsp->ifs_nomem, ifsp->ifs_exists);
1275 PRINTF("\t%lu inuse\n", ifsp->ifs_inuse);
1276 if (kmemcpy((char *)ipfrtab, (u_long)ifsp->ifs_table, sizeof(ipfrtab)))
1277 return;
1280 * Print out the contents (if any) of the fragment cache table.
1282 PRINTF("\n");
1283 for (i = 0; i < IPFT_SIZE; i++)
1284 while (ipfrtab[i]) {
1285 if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i],
1286 sizeof(ifr)) == -1)
1287 break;
1288 PRINTF("%s -> ", hostname(4, &ifr.ipfr_src));
1289 if (kmemcpy((char *)&fr, (u_long)ifr.ipfr_rule,
1290 sizeof(fr)) == -1)
1291 break;
1292 PRINTF("%s id %d ttl %d pr %d seen0 %d ifp %p tos %#02x = fl %#x\n",
1293 hostname(4, &ifr.ipfr_dst), ntohs(ifr.ipfr_id),
1294 ifr.ipfr_ttl, ifr.ipfr_p, ifr.ipfr_seen0,
1295 ifr.ipfr_ifp, ifr.ipfr_tos, fr.fr_flags);
1296 ipfrtab[i] = ifr.ipfr_next;
1298 if (kmemcpy((char *)ipfrtab, (u_long)ifsp->ifs_nattab,sizeof(ipfrtab)))
1299 return;
1300 for (i = 0; i < IPFT_SIZE; i++)
1301 while (ipfrtab[i]) {
1302 if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i],
1303 sizeof(ifr)) == -1)
1304 break;
1305 PRINTF("NAT: %s -> ", hostname(4, &ifr.ipfr_src));
1306 if (kmemcpy((char *)&fr, (u_long)ifr.ipfr_rule,
1307 sizeof(fr)) == -1)
1308 break;
1309 PRINTF("%s %d %d %d %#02x = %#x\n",
1310 hostname(4, &ifr.ipfr_dst), ifr.ipfr_id,
1311 ifr.ipfr_ttl, ifr.ipfr_p, ifr.ipfr_tos,
1312 fr.fr_flags);
1313 ipfrtab[i] = ifr.ipfr_next;
1319 * Show stats on how auth within IPFilter has been used
1321 static void showauthstates(asp)
1322 fr_authstat_t *asp;
1324 frauthent_t *frap, fra;
1326 #ifdef USE_QUAD_T
1327 printf("Authorisation hits: %qu\tmisses %qu\n",
1328 (unsigned long long) asp->fas_hits,
1329 (unsigned long long) asp->fas_miss);
1330 #else
1331 printf("Authorisation hits: %ld\tmisses %ld\n", asp->fas_hits,
1332 asp->fas_miss);
1333 #endif
1334 printf("nospace %ld\nadded %ld\nsendfail %ld\nsendok %ld\n",
1335 asp->fas_nospace, asp->fas_added, asp->fas_sendfail,
1336 asp->fas_sendok);
1337 printf("queok %ld\nquefail %ld\nexpire %ld\n",
1338 asp->fas_queok, asp->fas_quefail, asp->fas_expire);
1340 frap = asp->fas_faelist;
1341 while (frap) {
1342 if (kmemcpy((char *)&fra, (u_long)frap, sizeof(fra)) == -1)
1343 break;
1345 printf("age %ld\t", fra.fae_age);
1346 printfr(&fra.fae_fr);
1347 frap = fra.fae_next;
1353 * Display groups used for each of filter rules, accounting rules and
1354 * authentication, separately.
1356 static void showgroups(fiop)
1357 struct friostat *fiop;
1359 static char *gnames[3] = { "Filter", "Accounting", "Authentication" };
1360 frgroup_t *fp, grp;
1361 int on, off, i;
1363 on = fiop->f_active;
1364 off = 1 - on;
1366 for (i = 0; i < 3; i++) {
1367 printf("%s groups (active):\n", gnames[i]);
1368 for (fp = fiop->f_groups[i][on]; fp; fp = grp.fg_next)
1369 if (kmemcpy((char *)&grp, (u_long)fp, sizeof(grp)))
1370 break;
1371 else
1372 printf("%hu\n", grp.fg_num);
1373 printf("%s groups (inactive):\n", gnames[i]);
1374 for (fp = fiop->f_groups[i][off]; fp; fp = grp.fg_next)
1375 if (kmemcpy((char *)&grp, (u_long)fp, sizeof(grp)))
1376 break;
1377 else
1378 printf("%hu\n", grp.fg_num);
1382 static void parse_ipportstr(argument, ip, port)
1383 const char *argument;
1384 struct in_addr *ip;
1385 int *port;
1388 char *s, *comma;
1390 /* make working copy of argument, Theoretically you must be able
1391 * to write to optarg, but that seems very ugly to me....
1393 if ((s = malloc(strlen(argument) + 1)) == NULL)
1394 perror("malloc");
1395 strcpy(s, argument);
1397 /* get port */
1398 if ((comma = strchr(s, ',')) != NULL) {
1399 if (!strcasecmp(s, "any")) {
1400 *port = -1;
1401 } else if (!sscanf(comma + 1, "%d", port) ||
1402 (*port < 0) || (*port > 65535)) {
1403 fprintf(stderr, "Invalid port specfication in %s\n",
1404 argument);
1405 exit(-2);
1407 *comma = '\0';
1411 /* get ip address */
1412 if (!strcasecmp(s, "any")) {
1413 ip->s_addr = INADDR_ANY;
1414 } else if (!inet_aton(s, ip)) {
1415 fprintf(stderr, "Invalid IP address: %s\n", s);
1416 exit(-2);
1419 /* free allocated memory */
1420 free(s);
1424 #ifdef STATETOP
1425 static char ttlbuf[STSTRSIZE];
1427 static char *ttl_to_string(ttl)
1428 long int ttl;
1431 int hours, minutes, seconds;
1433 /* ttl is in half seconds */
1434 ttl /= 2;
1436 hours = ttl / 3600;
1437 ttl = ttl % 3600;
1438 minutes = ttl / 60;
1439 seconds = ttl % 60;
1441 if (hours > 0 )
1442 sprintf(ttlbuf, "%2d:%02d:%02d", hours, minutes, seconds);
1443 else
1444 sprintf(ttlbuf, "%2d:%02d", minutes, seconds);
1445 return ttlbuf;
1449 static int sort_pkts(a, b)
1450 const void *a;
1451 const void *b;
1454 register const statetop_t *ap = a;
1455 register const statetop_t *bp = b;
1457 if (ap->st_pkts == bp->st_pkts)
1458 return 0;
1459 else if (ap->st_pkts < bp->st_pkts)
1460 return 1;
1461 return -1;
1465 static int sort_bytes(a, b)
1466 const void *a;
1467 const void *b;
1469 register const statetop_t *ap = a;
1470 register const statetop_t *bp = b;
1472 if (ap->st_bytes == bp->st_bytes)
1473 return 0;
1474 else if (ap->st_bytes < bp->st_bytes)
1475 return 1;
1476 return -1;
1480 static int sort_p(a, b)
1481 const void *a;
1482 const void *b;
1484 register const statetop_t *ap = a;
1485 register const statetop_t *bp = b;
1487 if (ap->st_p == bp->st_p)
1488 return 0;
1489 else if (ap->st_p < bp->st_p)
1490 return 1;
1491 return -1;
1495 static int sort_ttl(a, b)
1496 const void *a;
1497 const void *b;
1499 register const statetop_t *ap = a;
1500 register const statetop_t *bp = b;
1502 if (ap->st_age == bp->st_age)
1503 return 0;
1504 else if (ap->st_age < bp->st_age)
1505 return 1;
1506 return -1;
1509 static int sort_srcip(a, b)
1510 const void *a;
1511 const void *b;
1513 register const statetop_t *ap = a;
1514 register const statetop_t *bp = b;
1516 if (ntohl(ap->st_src.in4.s_addr) == ntohl(bp->st_src.in4.s_addr))
1517 return 0;
1518 else if (ntohl(ap->st_src.in4.s_addr) > ntohl(bp->st_src.in4.s_addr))
1519 return 1;
1520 return -1;
1523 static int sort_dstip(a, b)
1524 const void *a;
1525 const void *b;
1527 register const statetop_t *ap = a;
1528 register const statetop_t *bp = b;
1530 if (ntohl(ap->st_dst.in4.s_addr) == ntohl(bp->st_dst.in4.s_addr))
1531 return 0;
1532 else if (ntohl(ap->st_dst.in4.s_addr) > ntohl(bp->st_dst.in4.s_addr))
1533 return 1;
1534 return -1;
1536 #endif