1
2 /*
3 * Copyright (C) 2012 by Darren Reed.
4 *
5 * See the IPFILTER.LICENCE file for details on licencing.
6 */
7 #include <sys/ioctl.h>
8 #include <ctype.h>
9 #include <fcntl.h>
10 # include <nlist.h>
11 #include <ctype.h>
12 #if defined(sun) && defined(__SVR4)
13 # include <stddef.h>
14 #endif
15 #include "ipf.h"
16 #include "netinet/ipl.h"
17 #if defined(STATETOP)
18 # if defined(sun) && defined(__SVR4)
19 # include <sys/select.h>
20 # endif
21 # include <netinet/ip_var.h>
22 # include <netinet/tcp_fsm.h>
23 # include <ctype.h>
24 # include <signal.h>
25 # include <time.h>
26 # if SOLARIS || defined(__NetBSD__)
27 # ifdef ERR
28 # undef ERR
29 # endif
30 # include <curses.h>
31 # else /* SOLARIS */
32 # include <ncurses.h>
33 # endif /* SOLARIS */
34 #endif /* STATETOP */
35 #include "kmem.h"
36 #if defined(__NetBSD__)
37 # include <paths.h>
38 #endif
39
40 #if !defined(lint)
41 static const char sccsid[] = "@(#)fils.c 1.21 4/20/96 (C) 1993-2000 Darren Reed";
42 static const char rcsid[] = "@(#)$Id$";
43 #endif
44
45
46 extern char *optarg;
47 extern int optind;
48 extern int opterr;
49
50 #define PRINTF (void)printf
51 #define FPRINTF (void)fprintf
52 static char *filters[4] = { "ipfilter(in)", "ipfilter(out)",
53 "ipacct(in)", "ipacct(out)" };
54 static int state_logging = -1;
55 static wordtab_t *state_fields = NULL;
56
57 int nohdrfields = 0;
58 int opts = 0;
59 #ifdef USE_INET6
60 int use_inet4 = 0;
61 int use_inet6 = 0;
62 #endif
63 int live_kernel = 1;
64 int state_fd = -1;
65 int ipf_fd = -1;
66 int auth_fd = -1;
67 int nat_fd = -1;
68 frgroup_t *grtop = NULL;
69 frgroup_t *grtail = NULL;
70
71 char *blockreasons[FRB_MAX_VALUE + 1] = {
72 "packet blocked",
73 "log rule failure",
74 "pps rate exceeded",
75 "jumbogram",
76 "makefrip failed",
77 "cannot add state",
78 "IP ID update failed",
79 "log-or-block failed",
80 "decapsulate failure",
81 "cannot create new auth entry",
82 "packet queued for auth",
83 "buffer coalesce failure",
84 "buffer pullup failure",
85 "auth feedback",
86 "bad fragment",
87 "IPv4 NAT failure",
88 "IPv6 NAT failure"
89 };
90
91 #ifdef STATETOP
92 #define STSTRSIZE 80
93 #define STGROWSIZE 16
94 #define HOSTNMLEN 40
95
96 #define STSORT_PR 0
97 #define STSORT_PKTS 1
98 #define STSORT_BYTES 2
99 #define STSORT_TTL 3
100 #define STSORT_SRCIP 4
101 #define STSORT_SRCPT 5
102 #define STSORT_DSTIP 6
103 #define STSORT_DSTPT 7
104 #define STSORT_MAX STSORT_DSTPT
105 #define STSORT_DEFAULT STSORT_BYTES
106
107
108 typedef struct statetop {
109 i6addr_t st_src;
110 i6addr_t st_dst;
111 u_short st_sport;
112 u_short st_dport;
113 u_char st_p;
114 u_char st_v;
115 u_char st_state[2];
116 U_QUAD_T st_pkts;
117 U_QUAD_T st_bytes;
118 u_long st_age;
119 } statetop_t;
120 #endif
121
122 int main(int, char *[]);
123
124 static int fetchfrag(int, int, ipfr_t *);
125 static void showstats(friostat_t *, u_32_t);
126 static void showfrstates(ipfrstat_t *, u_long);
127 static void showlist(friostat_t *);
128 static void showstatestats(ips_stat_t *);
129 static void showipstates(ips_stat_t *, int *);
130 static void showauthstates(ipf_authstat_t *);
131 static void showtqtable_live(int);
132 static void showgroups(friostat_t *);
133 static void usage(char *);
134 static int state_matcharray(ipstate_t *, int *);
135 static int printlivelist(friostat_t *, int, int, frentry_t *,
136 char *, char *);
137 static void printdeadlist(friostat_t *, int, int, frentry_t *,
138 char *, char *);
139 static void printside(char *, ipf_statistics_t *);
140 static void parse_ipportstr(const char *, i6addr_t *, int *);
141 static void ipfstate_live(char *, friostat_t **, ips_stat_t **,
142 ipfrstat_t **, ipf_authstat_t **, u_32_t *);
143 static void ipfstate_dead(char *, friostat_t **, ips_stat_t **,
144 ipfrstat_t **, ipf_authstat_t **, u_32_t *);
145 static ipstate_t *fetchstate(ipstate_t *, ipstate_t *);
146 #ifdef STATETOP
147 static void topipstates(i6addr_t, i6addr_t, int, int, int,
148 int, int, int, int *);
149 static void sig_break(int);
150 static void sig_resize(int);
151 static char *getip(int, i6addr_t *);
152 static char *ttl_to_string(long);
153 static int sort_p(const void *, const void *);
154 static int sort_pkts(const void *, const void *);
155 static int sort_bytes(const void *, const void *);
156 static int sort_ttl(const void *, const void *);
157 static int sort_srcip(const void *, const void *);
158 static int sort_srcpt(const void *, const void *);
159 static int sort_dstip(const void *, const void *);
160 static int sort_dstpt(const void *, const void *);
161 #endif
162
163
usage(char * name)164 static void usage(char *name)
165 {
166 #ifdef USE_INET6
167 fprintf(stderr, "Usage: %s [-46aAdfghIilnoRsv]\n", name);
168 #else
169 fprintf(stderr, "Usage: %s [-4aAdfghIilnoRsv]\n", name);
170 #endif
171 fprintf(stderr, " %s [-M corefile] [-N symbol-list]\n", name);
172 #ifdef STATETOP
173 #ifdef USE_INET6
174 fprintf(stderr, " %s -t [-46C] ", name);
175 #else
176 fprintf(stderr, " %s -t [-4C] ", name);
177 #endif
178 #endif
179 fprintf(stderr, "[-D destination address] [-P protocol] [-S source address] [-T refresh time]\n");
180 exit(1);
181 }
182
183
main(int argc,char * argv[])184 int main(int argc, char *argv[])
185 {
186 ipf_authstat_t frauthst;
187 ipf_authstat_t *frauthstp = &frauthst;
188 friostat_t fio;
189 friostat_t *fiop = &fio;
190 ips_stat_t ipsst;
191 ips_stat_t *ipsstp = &ipsst;
192 ipfrstat_t ifrst;
193 ipfrstat_t *ifrstp = &ifrst;
194 char *options;
195 char *kern = NULL;
196 char *memf = NULL;
197 int c;
198 int myoptind;
199 int *filter = NULL;
200
201 int protocol = -1; /* -1 = wild card for any protocol */
202 int refreshtime = 1; /* default update time */
203 int sport = -1; /* -1 = wild card for any source port */
204 int dport = -1; /* -1 = wild card for any dest port */
205 int topclosed = 0; /* do not show closed tcp sessions */
206 i6addr_t saddr, daddr;
207 u_32_t frf;
208
209 #ifdef USE_INET6
210 options = "46aACdfghIilnostvD:m:M:N:O:P:RS:T:";
211 #else
212 options = "4aACdfghIilnostvD:m:M:N:O:P:RS:T:";
213 #endif
214
215 saddr.in4.s_addr = INADDR_ANY; /* default any v4 source addr */
216 daddr.in4.s_addr = INADDR_ANY; /* default any v4 dest addr */
217 #ifdef USE_INET6
218 saddr.in6 = in6addr_any; /* default any v6 source addr */
219 daddr.in6 = in6addr_any; /* default any v6 dest addr */
220 #endif
221
222 /* Don't warn about invalid flags when we run getopt for the 1st time */
223 opterr = 0;
224
225 /*
226 * Parse these two arguments now lest there be any buffer overflows
227 * in the parsing of the rest.
228 */
229 myoptind = optind;
230 while ((c = getopt(argc, argv, options)) != -1) {
231 switch (c)
232 {
233 case 'M' :
234 memf = optarg;
235 live_kernel = 0;
236 break;
237 case 'N' :
238 kern = optarg;
239 live_kernel = 0;
240 break;
241 }
242 }
243 optind = myoptind;
244
245 if (live_kernel == 1) {
246 if ((state_fd = open(IPSTATE_NAME, O_RDONLY)) == -1) {
247 perror("open(IPSTATE_NAME)");
248 exit(-1);
249 }
250 if ((auth_fd = open(IPAUTH_NAME, O_RDONLY)) == -1) {
251 perror("open(IPAUTH_NAME)");
252 exit(-1);
253 }
254 if ((nat_fd = open(IPNAT_NAME, O_RDONLY)) == -1) {
255 perror("open(IPAUTH_NAME)");
256 exit(-1);
257 }
258 if ((ipf_fd = open(IPL_NAME, O_RDONLY)) == -1) {
259 fprintf(stderr, "open(%s)", IPL_NAME);
260 perror("");
261 exit(-1);
262 }
263 }
264
265 if (kern != NULL || memf != NULL) {
266 (void)setgid(getgid());
267 (void)setuid(getuid());
268 }
269
270 if (live_kernel == 1) {
271 (void) checkrev(IPL_NAME);
272 } else {
273 if (openkmem(kern, memf) == -1)
274 exit(-1);
275 }
276
277 (void)setgid(getgid());
278 (void)setuid(getuid());
279
280 opterr = 1;
281
282 while ((c = getopt(argc, argv, options)) != -1)
283 {
284 switch (c)
285 {
286 #ifdef USE_INET6
287 case '4' :
288 use_inet4 = 1;
289 break;
290 case '6' :
291 use_inet6 = 1;
292 break;
293 #endif
294 case 'a' :
295 opts |= OPT_ACCNT|OPT_SHOWLIST;
296 break;
297 case 'A' :
298 opts |= OPT_AUTHSTATS;
299 break;
300 case 'C' :
301 topclosed = 1;
302 break;
303 case 'd' :
304 opts |= OPT_DEBUG;
305 break;
306 case 'D' :
307 parse_ipportstr(optarg, &daddr, &dport);
308 break;
309 case 'f' :
310 opts |= OPT_FRSTATES;
311 break;
312 case 'g' :
313 opts |= OPT_GROUPS;
314 break;
315 case 'h' :
316 opts |= OPT_HITS;
317 break;
318 case 'i' :
319 opts |= OPT_INQUE|OPT_SHOWLIST;
320 break;
321 case 'I' :
322 opts |= OPT_INACTIVE;
323 break;
324 case 'l' :
325 opts |= OPT_SHOWLIST;
326 break;
327 case 'm' :
328 filter = parseipfexpr(optarg, NULL);
329 if (filter == NULL) {
330 fprintf(stderr, "Error parseing '%s'\n",
331 optarg);
332 exit(1);
333 }
334 break;
335 case 'M' :
336 break;
337 case 'N' :
338 break;
339 case 'n' :
340 opts |= OPT_SHOWLINENO;
341 break;
342 case 'o' :
343 opts |= OPT_OUTQUE|OPT_SHOWLIST;
344 break;
345 case 'O' :
346 state_fields = parsefields(statefields, optarg);
347 break;
348 case 'P' :
349 protocol = getproto(optarg);
350 if (protocol == -1) {
351 fprintf(stderr, "%s: Invalid protocol: %s\n",
352 argv[0], optarg);
353 exit(-2);
354 }
355 break;
356 case 'R' :
357 opts |= OPT_NORESOLVE;
358 break;
359 case 's' :
360 opts |= OPT_IPSTATES;
361 break;
362 case 'S' :
363 parse_ipportstr(optarg, &saddr, &sport);
364 break;
365 case 't' :
366 #ifdef STATETOP
367 opts |= OPT_STATETOP;
368 break;
369 #else
370 fprintf(stderr,
371 "%s: state top facility not compiled in\n",
372 argv[0]);
373 exit(-2);
374 #endif
375 case 'T' :
376 if (!sscanf(optarg, "%d", &refreshtime) ||
377 (refreshtime <= 0)) {
378 fprintf(stderr,
379 "%s: Invalid refreshtime < 1 : %s\n",
380 argv[0], optarg);
381 exit(-2);
382 }
383 break;
384 case 'v' :
385 opts |= OPT_VERBOSE;
386 break;
387 default :
388 usage(argv[0]);
389 break;
390 }
391 }
392 #ifdef USE_INET6
393 if ((use_inet4 || use_inet6) &&
394 !(opts & (OPT_INQUE | OPT_OUTQUE | OPT_STATETOP))) {
395 #ifdef STATETOP
396 FPRINTF(stderr, "No -i, -o, or -t given with -4 or -6\n");
397 #else
398 FPRINTF(stderr, "No -i or -o given with -4 or -6\n");
399 #endif
400 exit(-2);
401 }
402 if (use_inet4 == 0 && use_inet6 == 0)
403 use_inet4 = use_inet6 = 1;
404 #endif
405
406 if (live_kernel == 1) {
407 bzero((char *)&fio, sizeof(fio));
408 bzero((char *)&ipsst, sizeof(ipsst));
409 bzero((char *)&ifrst, sizeof(ifrst));
410
411 ipfstate_live(IPL_NAME, &fiop, &ipsstp, &ifrstp,
412 &frauthstp, &frf);
413 } else {
414 ipfstate_dead(kern, &fiop, &ipsstp, &ifrstp, &frauthstp, &frf);
415 }
416
417 if (opts & OPT_IPSTATES) {
418 showipstates(ipsstp, filter);
419 } else if (opts & OPT_SHOWLIST) {
420 showlist(fiop);
421 if ((opts & OPT_OUTQUE) && (opts & OPT_INQUE)){
422 opts &= ~OPT_OUTQUE;
423 showlist(fiop);
424 }
425 } else if (opts & OPT_FRSTATES)
426 showfrstates(ifrstp, fiop->f_ticks);
427 #ifdef STATETOP
428 else if (opts & OPT_STATETOP)
429 topipstates(saddr, daddr, sport, dport, protocol,
430 #ifdef USE_INET6
431 use_inet6 && use_inet4 ? 0 : use_inet6 && !use_inet4 ? 6 : 4,
432 #else
433 4,
434 #endif
435 #endif
436 refreshtime, topclosed, filter);
437 else if (opts & OPT_AUTHSTATS)
438 showauthstates(frauthstp);
439 else if (opts & OPT_GROUPS)
440 showgroups(fiop);
441 else
442 showstats(fiop, frf);
443
444 return (0);
445 }
446
447
448 /*
449 * Fill in the stats structures from the live kernel, using a combination
450 * of ioctl's and copying directly from kernel memory.
451 */
ipfstate_live(char * device,friostat_t ** fiopp,ips_stat_t ** ipsstpp,ipfrstat_t ** ifrstpp,ipf_authstat_t ** frauthstpp,u_32_t * frfp)452 static void ipfstate_live(char *device, friostat_t **fiopp,
453 ips_stat_t **ipsstpp, ipfrstat_t **ifrstpp,
454 ipf_authstat_t **frauthstpp, u_32_t *frfp)
455 {
456 ipfobj_t ipfo;
457
458 if (checkrev(device) == -1) {
459 fprintf(stderr, "User/kernel version check failed\n");
460 exit(1);
461 }
462
463 if ((opts & OPT_AUTHSTATS) == 0) {
464 bzero((caddr_t)&ipfo, sizeof(ipfo));
465 ipfo.ipfo_rev = IPFILTER_VERSION;
466 ipfo.ipfo_type = IPFOBJ_IPFSTAT;
467 ipfo.ipfo_size = sizeof(friostat_t);
468 ipfo.ipfo_ptr = (void *)*fiopp;
469
470 if (ioctl(ipf_fd, SIOCGETFS, &ipfo) == -1) {
471 ipferror(ipf_fd, "ioctl(ipf:SIOCGETFS)");
472 exit(-1);
473 }
474
475 if (ioctl(ipf_fd, SIOCGETFF, frfp) == -1)
476 ipferror(ipf_fd, "ioctl(SIOCGETFF)");
477 }
478
479 if ((opts & OPT_IPSTATES) != 0) {
480
481 bzero((caddr_t)&ipfo, sizeof(ipfo));
482 ipfo.ipfo_rev = IPFILTER_VERSION;
483 ipfo.ipfo_type = IPFOBJ_STATESTAT;
484 ipfo.ipfo_size = sizeof(ips_stat_t);
485 ipfo.ipfo_ptr = (void *)*ipsstpp;
486
487 if ((ioctl(state_fd, SIOCGETFS, &ipfo) == -1)) {
488 ipferror(state_fd, "ioctl(state:SIOCGETFS)");
489 exit(-1);
490 }
491 if (ioctl(state_fd, SIOCGETLG, &state_logging) == -1) {
492 ipferror(state_fd, "ioctl(state:SIOCGETLG)");
493 exit(-1);
494 }
495 }
496
497 if ((opts & OPT_FRSTATES) != 0) {
498 bzero((caddr_t)&ipfo, sizeof(ipfo));
499 ipfo.ipfo_rev = IPFILTER_VERSION;
500 ipfo.ipfo_type = IPFOBJ_FRAGSTAT;
501 ipfo.ipfo_size = sizeof(ipfrstat_t);
502 ipfo.ipfo_ptr = (void *)*ifrstpp;
503
504 if (ioctl(ipf_fd, SIOCGFRST, &ipfo) == -1) {
505 ipferror(ipf_fd, "ioctl(SIOCGFRST)");
506 exit(-1);
507 }
508 }
509
510 if (opts & OPT_DEBUG)
511 PRINTF("opts %#x name %s\n", opts, device);
512
513 if ((opts & OPT_AUTHSTATS) != 0) {
514 bzero((caddr_t)&ipfo, sizeof(ipfo));
515 ipfo.ipfo_rev = IPFILTER_VERSION;
516 ipfo.ipfo_type = IPFOBJ_AUTHSTAT;
517 ipfo.ipfo_size = sizeof(ipf_authstat_t);
518 ipfo.ipfo_ptr = (void *)*frauthstpp;
519
520 if (ioctl(auth_fd, SIOCATHST, &ipfo) == -1) {
521 ipferror(auth_fd, "ioctl(SIOCATHST)");
522 exit(-1);
523 }
524 }
525 }
526
527
528 /*
529 * Build up the stats structures from data held in the "core" memory.
530 * This is mainly useful when looking at data in crash dumps and ioctl's
531 * just won't work any more.
532 */
ipfstate_dead(char * kernel,friostat_t ** fiopp,ips_stat_t ** ipsstpp,ipfrstat_t ** ifrstpp,ipf_authstat_t ** frauthstpp,u_32_t * frfp)533 static void ipfstate_dead( char *kernel, friostat_t **fiopp,
534 ips_stat_t **ipsstpp, ipfrstat_t **ifrstpp,
535 ipf_authstat_t **frauthstpp, u_32_t *frfp)
536 {
537 static ipf_authstat_t frauthst, *frauthstp;
538 static ipftq_t ipstcptab[IPF_TCP_NSTATES];
539 static ips_stat_t ipsst, *ipsstp;
540 static ipfrstat_t ifrst, *ifrstp;
541 static friostat_t fio, *fiop;
542 int temp;
543
544 void *rules[2][2];
545 struct nlist deadlist[44] = {
546 { "ipf_auth_stats", 0, 0, 0, 0 }, /* 0 */
547 { "fae_list", 0, 0, 0, 0 },
548 { "ipauth", 0, 0, 0, 0 },
549 { "ipf_auth_list", 0, 0, 0, 0 },
550 { "ipf_auth_start", 0, 0, 0, 0 },
551 { "ipf_auth_end", 0, 0, 0, 0 }, /* 5 */
552 { "ipf_auth_next", 0, 0, 0, 0 },
553 { "ipf_auth", 0, 0, 0, 0 },
554 { "ipf_auth_used", 0, 0, 0, 0 },
555 { "ipf_auth_size", 0, 0, 0, 0 },
556 { "ipf_auth_defaultage", 0, 0, 0, 0 }, /* 10 */
557 { "ipf_auth_pkts", 0, 0, 0, 0 },
558 { "ipf_auth_lock", 0, 0, 0, 0 },
559 { "frstats", 0, 0, 0, 0 },
560 { "ips_stats", 0, 0, 0, 0 },
561 { "ips_num", 0, 0, 0, 0 }, /* 15 */
562 { "ips_wild", 0, 0, 0, 0 },
563 { "ips_list", 0, 0, 0, 0 },
564 { "ips_table", 0, 0, 0, 0 },
565 { "ipf_state_max", 0, 0, 0, 0 },
566 { "ipf_state_size", 0, 0, 0, 0 }, /* 20 */
567 { "ipf_state_doflush", 0, 0, 0, 0 },
568 { "ipf_state_lock", 0, 0, 0, 0 },
569 { "ipfr_heads", 0, 0, 0, 0 },
570 { "ipfr_nattab", 0, 0, 0, 0 },
571 { "ipfr_stats", 0, 0, 0, 0 }, /* 25 */
572 { "ipfr_inuse", 0, 0, 0, 0 },
573 { "ipf_ipfrttl", 0, 0, 0, 0 },
574 { "ipf_frag_lock", 0, 0, 0, 0 },
575 { "ipfr_timer_id", 0, 0, 0, 0 },
576 { "ipf_nat_lock", 0, 0, 0, 0 }, /* 30 */
577 { "ipf_rules", 0, 0, 0, 0 },
578 { "ipf_acct", 0, 0, 0, 0 },
579 { "ipl_frouteok", 0, 0, 0, 0 },
580 { "ipf_running", 0, 0, 0, 0 },
581 { "ipf_groups", 0, 0, 0, 0 }, /* 35 */
582 { "ipf_active", 0, 0, 0, 0 },
583 { "ipf_pass", 0, 0, 0, 0 },
584 { "ipf_flags", 0, 0, 0, 0 },
585 { "ipf_state_logging", 0, 0, 0, 0 },
586 { "ips_tqtqb", 0, 0, 0, 0 }, /* 40 */
587 { NULL, 0, 0, 0, 0 }
588 };
589
590
591 frauthstp = &frauthst;
592 ipsstp = &ipsst;
593 ifrstp = &ifrst;
594 fiop = &fio;
595
596 *frfp = 0;
597 *fiopp = fiop;
598 *ipsstpp = ipsstp;
599 *ifrstpp = ifrstp;
600 *frauthstpp = frauthstp;
601
602 bzero((char *)fiop, sizeof(*fiop));
603 bzero((char *)ipsstp, sizeof(*ipsstp));
604 bzero((char *)ifrstp, sizeof(*ifrstp));
605 bzero((char *)frauthstp, sizeof(*frauthstp));
606
607 if (nlist(kernel, deadlist) == -1) {
608 fprintf(stderr, "nlist error\n");
609 return;
610 }
611
612 /*
613 * This is for SIOCGETFF.
614 */
615 kmemcpy((char *)frfp, (u_long)deadlist[40].n_value, sizeof(*frfp));
616
617 /*
618 * f_locks is a combination of the lock variable from each part of
619 * ipfilter (state, auth, nat, fragments).
620 */
621 kmemcpy((char *)fiop, (u_long)deadlist[13].n_value, sizeof(*fiop));
622 kmemcpy((char *)&fiop->f_locks[0], (u_long)deadlist[22].n_value,
623 sizeof(fiop->f_locks[0]));
624 kmemcpy((char *)&fiop->f_locks[0], (u_long)deadlist[30].n_value,
625 sizeof(fiop->f_locks[1]));
626 kmemcpy((char *)&fiop->f_locks[2], (u_long)deadlist[28].n_value,
627 sizeof(fiop->f_locks[2]));
628 kmemcpy((char *)&fiop->f_locks[3], (u_long)deadlist[12].n_value,
629 sizeof(fiop->f_locks[3]));
630
631 /*
632 * Get pointers to each list of rules (active, inactive, in, out)
633 */
634 kmemcpy((char *)&rules, (u_long)deadlist[31].n_value, sizeof(rules));
635 fiop->f_fin[0] = rules[0][0];
636 fiop->f_fin[1] = rules[0][1];
637 fiop->f_fout[0] = rules[1][0];
638 fiop->f_fout[1] = rules[1][1];
639
640 /*
641 * Now get accounting rules pointers.
642 */
643 kmemcpy((char *)&rules, (u_long)deadlist[33].n_value, sizeof(rules));
644 fiop->f_acctin[0] = rules[0][0];
645 fiop->f_acctin[1] = rules[0][1];
646 fiop->f_acctout[0] = rules[1][0];
647 fiop->f_acctout[1] = rules[1][1];
648
649 /*
650 * A collection of "global" variables used inside the kernel which
651 * are all collected in friostat_t via ioctl.
652 */
653 kmemcpy((char *)&fiop->f_froute, (u_long)deadlist[33].n_value,
654 sizeof(fiop->f_froute));
655 kmemcpy((char *)&fiop->f_running, (u_long)deadlist[34].n_value,
656 sizeof(fiop->f_running));
657 kmemcpy((char *)&fiop->f_groups, (u_long)deadlist[35].n_value,
658 sizeof(fiop->f_groups));
659 kmemcpy((char *)&fiop->f_active, (u_long)deadlist[36].n_value,
660 sizeof(fiop->f_active));
661 kmemcpy((char *)&fiop->f_defpass, (u_long)deadlist[37].n_value,
662 sizeof(fiop->f_defpass));
663
664 /*
665 * Build up the state information stats structure.
666 */
667 kmemcpy((char *)ipsstp, (u_long)deadlist[14].n_value, sizeof(*ipsstp));
668 kmemcpy((char *)&temp, (u_long)deadlist[15].n_value, sizeof(temp));
669 kmemcpy((char *)ipstcptab, (u_long)deadlist[40].n_value,
670 sizeof(ipstcptab));
671 ipsstp->iss_active = temp;
672 ipsstp->iss_table = (void *)deadlist[18].n_value;
673 ipsstp->iss_list = (void *)deadlist[17].n_value;
674 ipsstp->iss_tcptab = ipstcptab;
675
676 /*
677 * Build up the authentiation information stats structure.
678 */
679 kmemcpy((char *)frauthstp, (u_long)deadlist[0].n_value,
680 sizeof(*frauthstp));
681 frauthstp->fas_faelist = (void *)deadlist[1].n_value;
682
683 /*
684 * Build up the fragment information stats structure.
685 */
686 kmemcpy((char *)ifrstp, (u_long)deadlist[25].n_value,
687 sizeof(*ifrstp));
688 ifrstp->ifs_table = (void *)deadlist[23].n_value;
689 ifrstp->ifs_nattab = (void *)deadlist[24].n_value;
690 kmemcpy((char *)&ifrstp->ifs_inuse, (u_long)deadlist[26].n_value,
691 sizeof(ifrstp->ifs_inuse));
692
693 /*
694 * Get logging on/off switches
695 */
696 kmemcpy((char *)&state_logging, (u_long)deadlist[41].n_value,
697 sizeof(state_logging));
698 }
699
700
printside(char * side,ipf_statistics_t * frs)701 static void printside(char *side, ipf_statistics_t *frs)
702 {
703 int i;
704
705 PRINTF("%lu\t%s bad packets\n", frs->fr_bad, side);
706 #ifdef USE_INET6
707 PRINTF("%lu\t%s IPv6 packets\n", frs->fr_ipv6, side);
708 #endif
709 PRINTF("%lu\t%s packets blocked\n", frs->fr_block, side);
710 PRINTF("%lu\t%s packets passed\n", frs->fr_pass, side);
711 PRINTF("%lu\t%s packets not matched\n", frs->fr_nom, side);
712 PRINTF("%lu\t%s packets counted\n", frs->fr_acct, side);
713 PRINTF("%lu\t%s packets short\n", frs->fr_short, side);
714 PRINTF("%lu\t%s packets logged and blocked\n", frs->fr_bpkl, side);
715 PRINTF("%lu\t%s packets logged and passed\n", frs->fr_ppkl, side);
716 PRINTF("%lu\t%s fragment state kept\n", frs->fr_nfr, side);
717 PRINTF("%lu\t%s fragment state lost\n", frs->fr_bnfr, side);
718 PRINTF("%lu\t%s packet state kept\n", frs->fr_ads, side);
719 PRINTF("%lu\t%s packet state lost\n", frs->fr_bads, side);
720 PRINTF("%lu\t%s invalid source\n", frs->fr_v4_badsrc, side);
721 PRINTF("%lu\t%s cache hits\n", frs->fr_chit, side);
722 PRINTF("%lu\t%s cache misses\n", frs->fr_cmiss, side);
723 PRINTF("%lu\t%s bad coalesces\n", frs->fr_badcoalesces, side);
724 PRINTF("%lu\t%s pullups succeeded\n", frs->fr_pull[0], side);
725 PRINTF("%lu\t%s pullups failed\n", frs->fr_pull[1], side);
726 PRINTF("%lu\t%s TCP checksum failures\n", frs->fr_tcpbad, side);
727 for (i = 0; i <= FRB_MAX_VALUE; i++)
728 PRINTF("%lu\t%s block reason %s\n",
729 frs->fr_blocked[i], side, blockreasons[i]);
730 }
731
732
733 /*
734 * Display the kernel stats for packets blocked and passed and other
735 * associated running totals which are kept.
736 */
showstats(struct friostat * fp,u_32_t frf)737 static void showstats( struct friostat *fp, u_32_t frf)
738 {
739 printside("input", &fp->f_st[0]);
740 printside("output", &fp->f_st[1]);
741
742 PRINTF("%lu\tpackets logged\n", fp->f_log_ok);
743 PRINTF("%lu\tlog failures\n", fp->f_log_fail);
744 PRINTF("%lu\tred-black no memory\n", fp->f_rb_no_mem);
745 PRINTF("%lu\tred-black node maximum\n", fp->f_rb_node_max);
746 PRINTF("%lu\tICMP replies sent\n", fp->f_st[0].fr_ret);
747 PRINTF("%lu\tTCP RSTs sent\n", fp->f_st[1].fr_ret);
748 PRINTF("%lu\tfastroute successes\n", fp->f_froute[0]);
749 PRINTF("%lu\tfastroute failures\n", fp->f_froute[1]);
750 PRINTF("%u\tIPF Ticks\n", fp->f_ticks);
751
752 PRINTF("%x\tPacket log flags set:\n", frf);
753 if (frf & FF_LOGPASS)
754 PRINTF("\tpackets passed through filter\n");
755 if (frf & FF_LOGBLOCK)
756 PRINTF("\tpackets blocked by filter\n");
757 if (frf & FF_LOGNOMATCH)
758 PRINTF("\tpackets not matched by filter\n");
759 if (!frf)
760 PRINTF("\tnone\n");
761 }
762
763
764 /*
765 * Print out a list of rules from the kernel, starting at the one passed.
766 */
767 static int
printlivelist(struct friostat * fiop,int out,int set,frentry_t * fp,char * group,char * comment)768 printlivelist( struct friostat *fiop, int out, int set, frentry_t *fp,
769 char *group, char *comment)
770 {
771 struct frentry fb;
772 ipfruleiter_t rule;
773 frentry_t zero;
774 frgroup_t *g;
775 ipfobj_t obj;
776 int rules;
777 int num;
778
779 rules = 0;
780
781 rule.iri_inout = out;
782 rule.iri_active = set;
783 rule.iri_rule = &fb;
784 rule.iri_nrules = 1;
785 if (group != NULL)
786 strncpy(rule.iri_group, group, FR_GROUPLEN);
787 else
788 rule.iri_group[0] = '\0';
789
790 bzero((char *)&zero, sizeof(zero));
791
792 bzero((char *)&obj, sizeof(obj));
793 obj.ipfo_rev = IPFILTER_VERSION;
794 obj.ipfo_type = IPFOBJ_IPFITER;
795 obj.ipfo_size = sizeof(rule);
796 obj.ipfo_ptr = &rule;
797
798 while (rule.iri_rule != NULL) {
799 u_long array[1000];
800
801 memset(array, 0xff, sizeof(array));
802 fp = (frentry_t *)array;
803 rule.iri_rule = fp;
804 if (ioctl(ipf_fd, SIOCIPFITER, &obj) == -1) {
805 ipferror(ipf_fd, "ioctl(SIOCIPFITER)");
806 num = IPFGENITER_IPF;
807 (void) ioctl(ipf_fd,SIOCIPFDELTOK, &num);
808 return (rules);
809 }
810 if (bcmp(fp, &zero, sizeof(zero)) == 0)
811 break;
812 if (rule.iri_rule == NULL)
813 break;
814 #ifdef USE_INET6
815 if (use_inet6 != 0 && use_inet4 == 0) {
816 if (fp->fr_family != 0 && fp->fr_family != AF_INET6)
817 continue;
818 } else if (use_inet4 != 0 && use_inet6 == 0) {
819 #endif
820 if (fp->fr_family != 0 && fp->fr_family != AF_INET)
821 continue;
822 #ifdef USE_INET6
823 } else {
824 if (fp->fr_family != 0 &&
825 fp->fr_family != AF_INET && fp->fr_family != AF_INET6)
826 continue;
827 }
828 #endif
829
830 if (fp->fr_data != NULL)
831 fp->fr_data = (char *)fp + fp->fr_size;
832
833 rules++;
834
835 if (opts & (OPT_HITS|OPT_DEBUG))
836 #ifdef USE_QUAD_T
837 PRINTF("%"PRIu64" ", (unsigned long long) fp->fr_hits);
838 #else
839 PRINTF("%lu ", fp->fr_hits);
840 #endif
841 if (opts & (OPT_ACCNT|OPT_DEBUG))
842 #ifdef USE_QUAD_T
843 PRINTF("%"PRIu64" ", (unsigned long long) fp->fr_bytes);
844 #else
845 PRINTF("%lu ", fp->fr_bytes);
846 #endif
847 if (opts & OPT_SHOWLINENO)
848 PRINTF("@%d ", rules);
849
850 if (fp->fr_die != 0)
851 fp->fr_die -= fiop->f_ticks;
852
853 printfr(fp, ioctl);
854 if (opts & OPT_DEBUG) {
855 binprint(fp, fp->fr_size);
856 if (fp->fr_data != NULL && fp->fr_dsize > 0)
857 binprint(fp->fr_data, fp->fr_dsize);
858 }
859 if (fp->fr_grhead != -1) {
860 for (g = grtop; g != NULL; g = g->fg_next) {
861 if (!strncmp(fp->fr_names + fp->fr_grhead,
862 g->fg_name,
863 FR_GROUPLEN))
864 break;
865 }
866 if (g == NULL) {
867 g = calloc(1, sizeof(*g));
868
869 if (g != NULL) {
870 strncpy(g->fg_name,
871 fp->fr_names + fp->fr_grhead,
872 FR_GROUPLEN);
873 if (grtop == NULL) {
874 grtop = g;
875 grtail = g;
876 } else {
877 grtail->fg_next = g;
878 grtail = g;
879 }
880 }
881 }
882 }
883 if (fp->fr_type == FR_T_CALLFUNC) {
884 rules += printlivelist(fiop, out, set, fp->fr_data,
885 group, "# callfunc: ");
886 }
887 }
888
889 num = IPFGENITER_IPF;
890 (void) ioctl(ipf_fd,SIOCIPFDELTOK, &num);
891
892 return (rules);
893 }
894
895
printdeadlist(friostat_t * fiop,int out,int set,frentry_t * fp,char * group,char * comment)896 static void printdeadlist(friostat_t *fiop, int out, int set, frentry_t *fp,
897 char *group, char *comment)
898 {
899 frgroup_t *grtop, *grtail, *g;
900 struct frentry fb;
901 char *data;
902 u_32_t type;
903 int n;
904
905 fb.fr_next = fp;
906 n = 0;
907 grtop = NULL;
908 grtail = NULL;
909
910 for (n = 1; fp; fp = fb.fr_next, n++) {
911 if (kmemcpy((char *)&fb, (u_long)fb.fr_next,
912 fb.fr_size) == -1) {
913 perror("kmemcpy");
914 return;
915 }
916 fp = &fb;
917 #ifdef USE_INET6
918 if (use_inet6 != 0 && use_inet4 == 0) {
919 if (fp->fr_family != 0 && fp->fr_family != AF_INET6)
920 continue;
921 } else if (use_inet4 != 0 && use_inet6 == 0) {
922 #endif
923 if (fp->fr_family != 0 && fp->fr_family != AF_INET)
924 continue;
925 #ifdef USE_INET6
926 } else {
927 if (fp->fr_family != 0 &&
928 fp->fr_family != AF_INET && fp->fr_family != AF_INET6)
929 continue;
930 }
931 #endif
932
933 data = NULL;
934 type = fb.fr_type & ~FR_T_BUILTIN;
935 if (type == FR_T_IPF || type == FR_T_BPFOPC) {
936 if (fb.fr_dsize) {
937 data = malloc(fb.fr_dsize);
938
939 if (kmemcpy(data, (u_long)fb.fr_data,
940 fb.fr_dsize) == -1) {
941 perror("kmemcpy");
942 return;
943 }
944 fb.fr_data = data;
945 }
946 }
947
948 if (opts & OPT_HITS)
949 #ifdef USE_QUAD_T
950 PRINTF("%"PRIu64" ", (unsigned long long) fb.fr_hits);
951 #else
952 PRINTF("%lu ", fb.fr_hits);
953 #endif
954 if (opts & OPT_ACCNT)
955 #ifdef USE_QUAD_T
956 PRINTF("%"PRIu64" ", (unsigned long long) fb.fr_bytes);
957 #else
958 PRINTF("%lu ", fb.fr_bytes);
959 #endif
960 if (opts & OPT_SHOWLINENO)
961 PRINTF("@%d ", n);
962
963 printfr(fp, ioctl);
964 if (opts & OPT_DEBUG) {
965 binprint(fp, fp->fr_size);
966 if (fb.fr_data != NULL && fb.fr_dsize > 0)
967 binprint(fb.fr_data, fb.fr_dsize);
968 }
969 if (data != NULL)
970 free(data);
971 if (fb.fr_grhead != -1) {
972 g = calloc(1, sizeof(*g));
973
974 if (g != NULL) {
975 strncpy(g->fg_name, fb.fr_names + fb.fr_grhead,
976 FR_GROUPLEN);
977 if (grtop == NULL) {
978 grtop = g;
979 grtail = g;
980 } else {
981 grtail->fg_next = g;
982 grtail = g;
983 }
984 }
985 }
986 if (type == FR_T_CALLFUNC) {
987 printdeadlist(fiop, out, set, fb.fr_data, group,
988 "# callfunc: ");
989 }
990 }
991
992 while ((g = grtop) != NULL) {
993 printdeadlist(fiop, out, set, NULL, g->fg_name, comment);
994 grtop = g->fg_next;
995 free(g);
996 }
997 }
998
999 /*
1000 * print out all of the asked for rule sets, using the stats struct as
1001 * the base from which to get the pointers.
1002 */
showlist(struct friostat * fiop)1003 static void showlist(struct friostat *fiop)
1004 {
1005 struct frentry *fp = NULL;
1006 int i, set;
1007
1008 set = fiop->f_active;
1009 if (opts & OPT_INACTIVE)
1010 set = 1 - set;
1011 if (opts & OPT_ACCNT) {
1012 if (opts & OPT_OUTQUE) {
1013 i = F_ACOUT;
1014 fp = (struct frentry *)fiop->f_acctout[set];
1015 } else if (opts & OPT_INQUE) {
1016 i = F_ACIN;
1017 fp = (struct frentry *)fiop->f_acctin[set];
1018 } else {
1019 FPRINTF(stderr, "No -i or -o given with -a\n");
1020 return;
1021 }
1022 } else {
1023 if (opts & OPT_OUTQUE) {
1024 i = F_OUT;
1025 fp = (struct frentry *)fiop->f_fout[set];
1026 } else if (opts & OPT_INQUE) {
1027 i = F_IN;
1028 fp = (struct frentry *)fiop->f_fin[set];
1029 } else
1030 return;
1031 }
1032 if (opts & OPT_DEBUG)
1033 FPRINTF(stderr, "showlist:opts %#x i %d\n", opts, i);
1034
1035 if (opts & OPT_DEBUG)
1036 PRINTF("fp %p set %d\n", fp, set);
1037
1038 if (live_kernel == 1) {
1039 int printed;
1040
1041 printed = printlivelist(fiop, i, set, fp, NULL, NULL);
1042 if (printed == 0) {
1043 FPRINTF(stderr, "# empty list for %s%s\n",
1044 (opts & OPT_INACTIVE) ? "inactive " : "",
1045 filters[i]);
1046 }
1047 } else {
1048 if (!fp) {
1049 FPRINTF(stderr, "# empty list for %s%s\n",
1050 (opts & OPT_INACTIVE) ? "inactive " : "",
1051 filters[i]);
1052 } else {
1053 printdeadlist(fiop, i, set, fp, NULL, NULL);
1054 }
1055 }
1056 }
1057
1058
1059 /*
1060 * Display ipfilter stateful filtering information
1061 */
showipstates(ips_stat_t * ipsp,int * filter)1062 static void showipstates(ips_stat_t *ipsp, int *filter)
1063 {
1064 ipstate_t *is;
1065 int i;
1066
1067 /*
1068 * If a list of states hasn't been asked for, only print out stats
1069 */
1070 if (!(opts & OPT_SHOWLIST)) {
1071 showstatestats(ipsp);
1072 return;
1073 }
1074
1075 if ((state_fields != NULL) && (nohdrfields == 0)) {
1076 for (i = 0; state_fields[i].w_value != 0; i++) {
1077 printfieldhdr(statefields, state_fields + i);
1078 if (state_fields[i + 1].w_value != 0)
1079 printf("\t");
1080 }
1081 printf("\n");
1082 }
1083
1084 /*
1085 * Print out all the state information currently held in the kernel.
1086 */
1087 for (is = ipsp->iss_list; is != NULL; ) {
1088 ipstate_t ips;
1089
1090 is = fetchstate(is, &ips);
1091
1092 if (is == NULL)
1093 break;
1094
1095 is = ips.is_next;
1096 if ((filter != NULL) &&
1097 (state_matcharray(&ips, filter) == 0)) {
1098 continue;
1099 }
1100 if (state_fields != NULL) {
1101 for (i = 0; state_fields[i].w_value != 0; i++) {
1102 printstatefield(&ips, state_fields[i].w_value);
1103 if (state_fields[i + 1].w_value != 0)
1104 printf("\t");
1105 }
1106 printf("\n");
1107 } else {
1108 printstate(&ips, opts, ipsp->iss_ticks);
1109 }
1110 }
1111 }
1112
1113
showstatestats(ips_stat_t * ipsp)1114 static void showstatestats(ips_stat_t *ipsp)
1115 {
1116 int minlen, maxlen, totallen;
1117 ipftable_t table;
1118 u_int *buckets;
1119 ipfobj_t obj;
1120 int i, sz;
1121
1122 /*
1123 * If a list of states hasn't been asked for, only print out stats
1124 */
1125
1126 sz = sizeof(*buckets) * ipsp->iss_state_size;
1127 buckets = (u_int *)malloc(sz);
1128
1129 obj.ipfo_rev = IPFILTER_VERSION;
1130 obj.ipfo_type = IPFOBJ_GTABLE;
1131 obj.ipfo_size = sizeof(table);
1132 obj.ipfo_ptr = &table;
1133
1134 table.ita_type = IPFTABLE_BUCKETS;
1135 table.ita_table = buckets;
1136
1137 if (live_kernel == 1) {
1138 if (ioctl(state_fd, SIOCGTABL, &obj) != 0) {
1139 free(buckets);
1140 return;
1141 }
1142 } else {
1143 if (kmemcpy((char *)buckets,
1144 (u_long)ipsp->iss_bucketlen, sz)) {
1145 free(buckets);
1146 return;
1147 }
1148 }
1149
1150 PRINTF("%u\tactive state table entries\n",ipsp->iss_active);
1151 PRINTF("%lu\tadd bad\n", ipsp->iss_add_bad);
1152 PRINTF("%lu\tadd duplicate\n", ipsp->iss_add_dup);
1153 PRINTF("%lu\tadd locked\n", ipsp->iss_add_locked);
1154 PRINTF("%lu\tadd oow\n", ipsp->iss_add_oow);
1155 PRINTF("%lu\tbucket full\n", ipsp->iss_bucket_full);
1156 PRINTF("%lu\tcheck bad\n", ipsp->iss_check_bad);
1157 PRINTF("%lu\tcheck miss\n", ipsp->iss_check_miss);
1158 PRINTF("%lu\tcheck nattag\n", ipsp->iss_check_nattag);
1159 PRINTF("%lu\tclone nomem\n", ipsp->iss_clone_nomem);
1160 PRINTF("%lu\tcheck notag\n", ipsp->iss_check_notag);
1161 PRINTF("%lu\tcheck success\n", ipsp->iss_hits);
1162 PRINTF("%lu\tcloned\n", ipsp->iss_cloned);
1163 PRINTF("%lu\texpired\n", ipsp->iss_expire);
1164 PRINTF("%lu\tflush all\n", ipsp->iss_flush_all);
1165 PRINTF("%lu\tflush closing\n", ipsp->iss_flush_closing);
1166 PRINTF("%lu\tflush queue\n", ipsp->iss_flush_queue);
1167 PRINTF("%lu\tflush state\n", ipsp->iss_flush_state);
1168 PRINTF("%lu\tflush timeout\n", ipsp->iss_flush_timeout);
1169 PRINTF("%u\thash buckets in use\n", ipsp->iss_inuse);
1170 PRINTF("%lu\tICMP bad\n", ipsp->iss_icmp_bad);
1171 PRINTF("%lu\tICMP banned\n", ipsp->iss_icmp_banned);
1172 PRINTF("%lu\tICMP errors\n", ipsp->iss_icmp_icmperr);
1173 PRINTF("%lu\tICMP head block\n", ipsp->iss_icmp_headblock);
1174 PRINTF("%lu\tICMP hits\n", ipsp->iss_icmp_hits);
1175 PRINTF("%lu\tICMP not query\n", ipsp->iss_icmp_notquery);
1176 PRINTF("%lu\tICMP short\n", ipsp->iss_icmp_short);
1177 PRINTF("%lu\tICMP too many\n", ipsp->iss_icmp_toomany);
1178 PRINTF("%lu\tICMPv6 errors\n", ipsp->iss_icmp6_icmperr);
1179 PRINTF("%lu\tICMPv6 miss\n", ipsp->iss_icmp6_miss);
1180 PRINTF("%lu\tICMPv6 not info\n", ipsp->iss_icmp6_notinfo);
1181 PRINTF("%lu\tICMPv6 not query\n", ipsp->iss_icmp6_notquery);
1182 PRINTF("%lu\tlog fail\n", ipsp->iss_log_fail);
1183 PRINTF("%lu\tlog ok\n", ipsp->iss_log_ok);
1184 PRINTF("%lu\tlookup interface mismatch\n", ipsp->iss_lookup_badifp);
1185 PRINTF("%lu\tlookup mask mismatch\n", ipsp->iss_miss_mask);
1186 PRINTF("%lu\tlookup port mismatch\n", ipsp->iss_lookup_badport);
1187 PRINTF("%lu\tlookup miss\n", ipsp->iss_lookup_miss);
1188 PRINTF("%lu\tmaximum rule references\n", ipsp->iss_max_ref);
1189 PRINTF("%lu\tmaximum hosts per rule\n", ipsp->iss_max_track);
1190 PRINTF("%lu\tno memory\n", ipsp->iss_nomem);
1191 PRINTF("%lu\tout of window\n", ipsp->iss_oow);
1192 PRINTF("%lu\torphans\n", ipsp->iss_orphan);
1193 PRINTF("%lu\tscan block\n", ipsp->iss_scan_block);
1194 PRINTF("%lu\tstate table maximum reached\n", ipsp->iss_max);
1195 PRINTF("%lu\tTCP closing\n", ipsp->iss_tcp_closing);
1196 PRINTF("%lu\tTCP OOW\n", ipsp->iss_tcp_oow);
1197 PRINTF("%lu\tTCP RST add\n", ipsp->iss_tcp_rstadd);
1198 PRINTF("%lu\tTCP too small\n", ipsp->iss_tcp_toosmall);
1199 PRINTF("%lu\tTCP bad options\n", ipsp->iss_tcp_badopt);
1200 PRINTF("%lu\tTCP removed\n", ipsp->iss_fin);
1201 PRINTF("%lu\tTCP FSM\n", ipsp->iss_tcp_fsm);
1202 PRINTF("%lu\tTCP strict\n", ipsp->iss_tcp_strict);
1203 PRINTF("%lu\tTCP wild\n", ipsp->iss_wild);
1204 PRINTF("%lu\tMicrosoft Windows SACK\n", ipsp->iss_winsack);
1205
1206 PRINTF("State logging %sabled\n", state_logging ? "en" : "dis");
1207
1208 PRINTF("IP states added:\n");
1209 for (i = 0; i < 256; i++) {
1210 if (ipsp->iss_proto[i] != 0) {
1211 struct protoent *proto;
1212
1213 proto = getprotobynumber(i);
1214 PRINTF("%lu", ipsp->iss_proto[i]);
1215 if (proto != NULL)
1216 PRINTF("\t%s\n", proto->p_name);
1217 else
1218 PRINTF("\t%d\n", i);
1219 }
1220 }
1221
1222 PRINTF("\nState table bucket statistics:\n");
1223 PRINTF("%u\tin use\n", ipsp->iss_inuse);
1224
1225 minlen = ipsp->iss_max;
1226 totallen = 0;
1227 maxlen = 0;
1228
1229 for (i = 0; i < ipsp->iss_state_size; i++) {
1230 if (buckets[i] > maxlen)
1231 maxlen = buckets[i];
1232 if (buckets[i] < minlen)
1233 minlen = buckets[i];
1234 totallen += buckets[i];
1235 }
1236
1237 PRINTF("%d\thash efficiency\n",
1238 totallen ? ipsp->iss_inuse * 100 / totallen : 0);
1239 PRINTF("%2.2f%%\tbucket usage\n%u\tminimal length\n",
1240 ((float)ipsp->iss_inuse / ipsp->iss_state_size) * 100.0,
1241 minlen);
1242 PRINTF("%u\tmaximal length\n%.3f\taverage length\n",
1243 maxlen,
1244 ipsp->iss_inuse ? (float) totallen/ ipsp->iss_inuse :
1245 0.0);
1246
1247 #define ENTRIES_PER_LINE 5
1248
1249 if (opts & OPT_VERBOSE) {
1250 PRINTF("\nCurrent bucket sizes :\n");
1251 for (i = 0; i < ipsp->iss_state_size; i++) {
1252 if ((i % ENTRIES_PER_LINE) == 0)
1253 PRINTF("\t");
1254 PRINTF("%4d -> %4u", i, buckets[i]);
1255 if ((i % ENTRIES_PER_LINE) ==
1256 (ENTRIES_PER_LINE - 1))
1257 PRINTF("\n");
1258 else
1259 PRINTF(" ");
1260 }
1261 PRINTF("\n");
1262 }
1263 PRINTF("\n");
1264
1265 free(buckets);
1266
1267 if (live_kernel == 1) {
1268 showtqtable_live(state_fd);
1269 } else {
1270 printtqtable(ipsp->iss_tcptab);
1271 }
1272 }
1273
1274
1275 #ifdef STATETOP
1276 static int handle_resize = 0, handle_break = 0;
1277
topipstates(i6addr_t saddr,i6addr_t daddr,int sport,int dport,int protocol,int ver,int refreshtime,int topclosed,int * filter)1278 static void topipstates(i6addr_t saddr, i6addr_t daddr, int sport, int dport,
1279 int protocol, int ver, int refreshtime, int topclosed, int *filter)
1280 {
1281 char str1[STSTRSIZE], str2[STSTRSIZE], str3[STSTRSIZE], str4[STSTRSIZE];
1282 int maxtsentries = 0, reverse = 0, sorting = STSORT_DEFAULT;
1283 int i, j, winy, tsentry, maxx, maxy, redraw = 0, ret = 0;
1284 int len, srclen, dstlen, forward = 1, c = 0;
1285 ips_stat_t ipsst, *ipsstp = &ipsst;
1286 int token_type = IPFGENITER_STATE;
1287 statetop_t *tstable = NULL, *tp;
1288 const char *errstr = "";
1289 ipstate_t ips;
1290 ipfobj_t ipfo;
1291 struct timeval selecttimeout;
1292 char hostnm[HOSTNMLEN];
1293 struct protoent *proto;
1294 fd_set readfd;
1295 time_t t;
1296
1297 /* install signal handlers */
1298 signal(SIGINT, sig_break);
1299 signal(SIGQUIT, sig_break);
1300 signal(SIGTERM, sig_break);
1301 signal(SIGWINCH, sig_resize);
1302
1303 /* init ncurses stuff */
1304 initscr();
1305 cbreak();
1306 noecho();
1307 curs_set(0);
1308 timeout(0);
1309 getmaxyx(stdscr, maxy, maxx);
1310
1311 /* init hostname */
1312 gethostname(hostnm, sizeof(hostnm) - 1);
1313 hostnm[sizeof(hostnm) - 1] = '\0';
1314
1315 /* init ipfobj_t stuff */
1316 bzero((caddr_t)&ipfo, sizeof(ipfo));
1317 ipfo.ipfo_rev = IPFILTER_VERSION;
1318 ipfo.ipfo_type = IPFOBJ_STATESTAT;
1319 ipfo.ipfo_size = sizeof(*ipsstp);
1320 ipfo.ipfo_ptr = (void *)ipsstp;
1321
1322 /* repeat until user aborts */
1323 while ( 1 ) {
1324
1325 /* get state table */
1326 bzero((char *)&ipsst, sizeof(ipsst));
1327 if ((ioctl(state_fd, SIOCGETFS, &ipfo) == -1)) {
1328 errstr = "ioctl(SIOCGETFS)";
1329 ret = -1;
1330 goto out;
1331 }
1332
1333 /* clear the history */
1334 tsentry = -1;
1335
1336 /* reset max str len */
1337 srclen = dstlen = 0;
1338
1339 /* read the state table and store in tstable */
1340 for (; ipsstp->iss_list; ipsstp->iss_list = ips.is_next) {
1341
1342 ipsstp->iss_list = fetchstate(ipsstp->iss_list, &ips);
1343 if (ipsstp->iss_list == NULL)
1344 break;
1345
1346 if (ver != 0 && ips.is_v != ver)
1347 continue;
1348
1349 if ((filter != NULL) &&
1350 (state_matcharray(&ips, filter) == 0))
1351 continue;
1352
1353 /* check v4 src/dest addresses */
1354 if (ips.is_v == 4) {
1355 if ((saddr.in4.s_addr != INADDR_ANY &&
1356 saddr.in4.s_addr != ips.is_saddr) ||
1357 (daddr.in4.s_addr != INADDR_ANY &&
1358 daddr.in4.s_addr != ips.is_daddr))
1359 continue;
1360 }
1361 #ifdef USE_INET6
1362 /* check v6 src/dest addresses */
1363 if (ips.is_v == 6) {
1364 if ((IP6_NEQ(&saddr, &in6addr_any) &&
1365 IP6_NEQ(&saddr, &ips.is_src)) ||
1366 (IP6_NEQ(&daddr, &in6addr_any) &&
1367 IP6_NEQ(&daddr, &ips.is_dst)))
1368 continue;
1369 }
1370 #endif
1371 /* check protocol */
1372 if (protocol > 0 && protocol != ips.is_p)
1373 continue;
1374
1375 /* check ports if protocol is TCP or UDP */
1376 if (((ips.is_p == IPPROTO_TCP) ||
1377 (ips.is_p == IPPROTO_UDP)) &&
1378 (((sport > 0) && (htons(sport) != ips.is_sport)) ||
1379 ((dport > 0) && (htons(dport) != ips.is_dport))))
1380 continue;
1381
1382 /* show closed TCP sessions ? */
1383 if ((topclosed == 0) && (ips.is_p == IPPROTO_TCP) &&
1384 (ips.is_state[0] >= IPF_TCPS_LAST_ACK) &&
1385 (ips.is_state[1] >= IPF_TCPS_LAST_ACK))
1386 continue;
1387
1388 /*
1389 * if necessary make room for this state
1390 * entry
1391 */
1392 tsentry++;
1393 if (!maxtsentries || tsentry == maxtsentries) {
1394 maxtsentries += STGROWSIZE;
1395 tstable = reallocarray(tstable, maxtsentries,
1396 sizeof(statetop_t));
1397 if (tstable == NULL) {
1398 perror("realloc");
1399 exit(-1);
1400 }
1401 }
1402
1403 /* get max src/dest address string length */
1404 len = strlen(getip(ips.is_v, &ips.is_src));
1405 if (srclen < len)
1406 srclen = len;
1407 len = strlen(getip(ips.is_v, &ips.is_dst));
1408 if (dstlen < len)
1409 dstlen = len;
1410
1411 /* fill structure */
1412 tp = tstable + tsentry;
1413 tp->st_src = ips.is_src;
1414 tp->st_dst = ips.is_dst;
1415 tp->st_p = ips.is_p;
1416 tp->st_v = ips.is_v;
1417 tp->st_state[0] = ips.is_state[0];
1418 tp->st_state[1] = ips.is_state[1];
1419 if (forward) {
1420 tp->st_pkts = ips.is_pkts[0]+ips.is_pkts[1];
1421 tp->st_bytes = ips.is_bytes[0]+ips.is_bytes[1];
1422 } else {
1423 tp->st_pkts = ips.is_pkts[2]+ips.is_pkts[3];
1424 tp->st_bytes = ips.is_bytes[2]+ips.is_bytes[3];
1425 }
1426 tp->st_age = ips.is_die - ipsstp->iss_ticks;
1427 if ((ips.is_p == IPPROTO_TCP) ||
1428 (ips.is_p == IPPROTO_UDP)) {
1429 tp->st_sport = ips.is_sport;
1430 tp->st_dport = ips.is_dport;
1431 }
1432 }
1433
1434 (void) ioctl(state_fd, SIOCIPFDELTOK, &token_type);
1435
1436 /* sort the array */
1437 if (tsentry != -1) {
1438 switch (sorting)
1439 {
1440 case STSORT_PR:
1441 qsort(tstable, tsentry + 1,
1442 sizeof(statetop_t), sort_p);
1443 break;
1444 case STSORT_PKTS:
1445 qsort(tstable, tsentry + 1,
1446 sizeof(statetop_t), sort_pkts);
1447 break;
1448 case STSORT_BYTES:
1449 qsort(tstable, tsentry + 1,
1450 sizeof(statetop_t), sort_bytes);
1451 break;
1452 case STSORT_TTL:
1453 qsort(tstable, tsentry + 1,
1454 sizeof(statetop_t), sort_ttl);
1455 break;
1456 case STSORT_SRCIP:
1457 qsort(tstable, tsentry + 1,
1458 sizeof(statetop_t), sort_srcip);
1459 break;
1460 case STSORT_SRCPT:
1461 qsort(tstable, tsentry +1,
1462 sizeof(statetop_t), sort_srcpt);
1463 break;
1464 case STSORT_DSTIP:
1465 qsort(tstable, tsentry + 1,
1466 sizeof(statetop_t), sort_dstip);
1467 break;
1468 case STSORT_DSTPT:
1469 qsort(tstable, tsentry + 1,
1470 sizeof(statetop_t), sort_dstpt);
1471 break;
1472 default:
1473 break;
1474 }
1475 }
1476
1477 /* handle window resizes */
1478 if (handle_resize) {
1479 endwin();
1480 initscr();
1481 cbreak();
1482 noecho();
1483 curs_set(0);
1484 timeout(0);
1485 getmaxyx(stdscr, maxy, maxx);
1486 redraw = 1;
1487 handle_resize = 0;
1488 }
1489
1490 /* stop program? */
1491 if (handle_break)
1492 break;
1493
1494 /* print title */
1495 erase();
1496 attron(A_BOLD);
1497 winy = 0;
1498 move(winy,0);
1499 snprintf(str1, sizeof(str1), "%s - %s - state top", hostnm, IPL_VERSION);
1500 for (j = 0 ; j < (maxx - 8 - strlen(str1)) / 2; j++)
1501 printw(" ");
1502 printw("%s", str1);
1503 attroff(A_BOLD);
1504
1505 /* just for fun add a clock */
1506 move(winy, maxx - 8);
1507 t = time(NULL);
1508 strftime(str1, 80, "%T", localtime(&t));
1509 printw("%s\n", str1);
1510
1511 /*
1512 * print the display filters, this is placed in the loop,
1513 * because someday I might add code for changing these
1514 * while the programming is running :-)
1515 */
1516 if (sport >= 0)
1517 snprintf(str1, sizeof(str1), "%s,%d", getip(ver, &saddr), sport);
1518 else
1519 snprintf(str1, sizeof(str1), "%s", getip(ver, &saddr));
1520
1521 if (dport >= 0)
1522 snprintf(str2, sizeof(str2), "%s,%d", getip(ver, &daddr), dport);
1523 else
1524 snprintf(str2, sizeof(str2), "%s", getip(ver, &daddr));
1525
1526 if (protocol < 0)
1527 strcpy(str3, "any");
1528 else if ((proto = getprotobynumber(protocol)) != NULL)
1529 snprintf(str3, sizeof(str3), "%s", proto->p_name);
1530 else
1531 snprintf(str3, sizeof(str3), "%d", protocol);
1532
1533 switch (sorting)
1534 {
1535 case STSORT_PR:
1536 snprintf(str4, sizeof(str4), "proto");
1537 break;
1538 case STSORT_PKTS:
1539 snprintf(str4, sizeof(str4), "# pkts");
1540 break;
1541 case STSORT_BYTES:
1542 snprintf(str4, sizeof(str4), "# bytes");
1543 break;
1544 case STSORT_TTL:
1545 snprintf(str4, sizeof(str4), "ttl");
1546 break;
1547 case STSORT_SRCIP:
1548 snprintf(str4, sizeof(str4), "src ip");
1549 break;
1550 case STSORT_SRCPT:
1551 snprintf(str4, sizeof(str4), "src port");
1552 break;
1553 case STSORT_DSTIP:
1554 snprintf(str4, sizeof(str4), "dest ip");
1555 break;
1556 case STSORT_DSTPT:
1557 snprintf(str4, sizeof(str4), "dest port");
1558 break;
1559 default:
1560 snprintf(str4, sizeof(str4), "unknown");
1561 break;
1562 }
1563
1564 if (reverse)
1565 strcat(str4, " (reverse)");
1566
1567 winy += 2;
1568 move(winy,0);
1569 printw("Src: %s, Dest: %s, Proto: %s, Sorted by: %s\n\n",
1570 str1, str2, str3, str4);
1571
1572 /*
1573 * For an IPv4 IP address we need at most 15 characters,
1574 * 4 tuples of 3 digits, separated by 3 dots. Enforce this
1575 * length, so the columns do not change positions based
1576 * on the size of the IP address. This length makes the
1577 * output fit in a 80 column terminal.
1578 * We are lacking a good solution for IPv6 addresses (that
1579 * can be longer that 15 characters), so we do not enforce
1580 * a maximum on the IP field size.
1581 */
1582 if (srclen < 15)
1583 srclen = 15;
1584 if (dstlen < 15)
1585 dstlen = 15;
1586
1587 /* print column description */
1588 winy += 2;
1589 move(winy,0);
1590 attron(A_BOLD);
1591 printw("%-*s %-*s %3s %4s %7s %9s %9s\n",
1592 srclen + 6, "Source IP", dstlen + 6, "Destination IP",
1593 "ST", "PR", "#pkts", "#bytes", "ttl");
1594 attroff(A_BOLD);
1595
1596 /* print all the entries */
1597 tp = tstable;
1598 if (reverse)
1599 tp += tsentry;
1600
1601 if (tsentry > maxy - 6)
1602 tsentry = maxy - 6;
1603 for (i = 0; i <= tsentry; i++) {
1604 /* print src/dest and port */
1605 if ((tp->st_p == IPPROTO_TCP) ||
1606 (tp->st_p == IPPROTO_UDP)) {
1607 snprintf(str1, sizeof(str1), "%s,%hu",
1608 getip(tp->st_v, &tp->st_src),
1609 ntohs(tp->st_sport));
1610 snprintf(str2, sizeof(str2), "%s,%hu",
1611 getip(tp->st_v, &tp->st_dst),
1612 ntohs(tp->st_dport));
1613 } else {
1614 snprintf(str1, sizeof(str1), "%s", getip(tp->st_v,
1615 &tp->st_src));
1616 snprintf(str2, sizeof(str2), "%s", getip(tp->st_v,
1617 &tp->st_dst));
1618 }
1619 winy++;
1620 move(winy, 0);
1621 printw("%-*s %-*s", srclen + 6, str1, dstlen + 6, str2);
1622
1623 /* print state */
1624 snprintf(str1, sizeof(str1), "%X/%X", tp->st_state[0],
1625 tp->st_state[1]);
1626 printw(" %3s", str1);
1627
1628 /* print protocol */
1629 proto = getprotobynumber(tp->st_p);
1630 if (proto) {
1631 strncpy(str1, proto->p_name, 4);
1632 str1[4] = '\0';
1633 } else {
1634 snprintf(str1, sizeof(str1), "%d", tp->st_p);
1635 }
1636 /* just print icmp for IPv6-ICMP */
1637 if (tp->st_p == IPPROTO_ICMPV6)
1638 strcpy(str1, "icmp");
1639 printw(" %4s", str1);
1640
1641 /* print #pkt/#bytes */
1642 #ifdef USE_QUAD_T
1643 printw(" %7qu %9qu", (unsigned long long) tp->st_pkts,
1644 (unsigned long long) tp->st_bytes);
1645 #else
1646 printw(" %7lu %9lu", tp->st_pkts, tp->st_bytes);
1647 #endif
1648 printw(" %9s", ttl_to_string(tp->st_age));
1649
1650 if (reverse)
1651 tp--;
1652 else
1653 tp++;
1654 }
1655
1656 /* screen data structure is filled, now update the screen */
1657 if (redraw)
1658 clearok(stdscr,1);
1659
1660 if (refresh() == ERR)
1661 break;
1662 if (redraw) {
1663 clearok(stdscr,0);
1664 redraw = 0;
1665 }
1666
1667 /* wait for key press or a 1 second time out period */
1668 selecttimeout.tv_sec = refreshtime;
1669 selecttimeout.tv_usec = 0;
1670 FD_ZERO(&readfd);
1671 FD_SET(0, &readfd);
1672 select(1, &readfd, NULL, NULL, &selecttimeout);
1673
1674 /* if key pressed, read all waiting keys */
1675 if (FD_ISSET(0, &readfd)) {
1676 c = wgetch(stdscr);
1677 if (c == ERR)
1678 continue;
1679
1680 if (ISALPHA(c) && ISUPPER(c))
1681 c = TOLOWER(c);
1682 if (c == 'l') {
1683 redraw = 1;
1684 } else if (c == 'q') {
1685 break;
1686 } else if (c == 'r') {
1687 reverse = !reverse;
1688 } else if (c == 'b') {
1689 forward = 0;
1690 } else if (c == 'f') {
1691 forward = 1;
1692 } else if (c == 's') {
1693 if (++sorting > STSORT_MAX)
1694 sorting = 0;
1695 }
1696 }
1697 } /* while */
1698
1699 out:
1700 printw("\n");
1701 curs_set(1);
1702 /* nocbreak(); XXX - endwin() should make this redundant */
1703 endwin();
1704
1705 free(tstable);
1706 if (ret != 0)
1707 perror(errstr);
1708 }
1709 #endif
1710
1711
1712 /*
1713 * Show fragment cache information that's held in the kernel.
1714 */
showfrstates(ipfrstat_t * ifsp,u_long ticks)1715 static void showfrstates(ipfrstat_t *ifsp, u_long ticks)
1716 {
1717 struct ipfr *ipfrtab[IPFT_SIZE], ifr;
1718 int i;
1719
1720 /*
1721 * print out the numeric statistics
1722 */
1723 PRINTF("IP fragment states:\n%lu\tnew\n%lu\texpired\n%lu\thits\n",
1724 ifsp->ifs_new, ifsp->ifs_expire, ifsp->ifs_hits);
1725 PRINTF("%lu\tretrans\n%lu\ttoo short\n",
1726 ifsp->ifs_retrans0, ifsp->ifs_short);
1727 PRINTF("%lu\tno memory\n%lu\talready exist\n",
1728 ifsp->ifs_nomem, ifsp->ifs_exists);
1729 PRINTF("%lu\tinuse\n", ifsp->ifs_inuse);
1730 PRINTF("\n");
1731
1732 if (live_kernel == 0) {
1733 if (kmemcpy((char *)ipfrtab, (u_long)ifsp->ifs_table,
1734 sizeof(ipfrtab)))
1735 return;
1736 }
1737
1738 /*
1739 * Print out the contents (if any) of the fragment cache table.
1740 */
1741 if (live_kernel == 1) {
1742 do {
1743 if (fetchfrag(ipf_fd, IPFGENITER_FRAG, &ifr) != 0)
1744 break;
1745 if (ifr.ipfr_ifp == NULL)
1746 break;
1747 ifr.ipfr_ttl -= ticks;
1748 printfraginfo("", &ifr);
1749 } while (ifr.ipfr_next != NULL);
1750 } else {
1751 for (i = 0; i < IPFT_SIZE; i++)
1752 while (ipfrtab[i] != NULL) {
1753 if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i],
1754 sizeof(ifr)) == -1)
1755 break;
1756 printfraginfo("", &ifr);
1757 ipfrtab[i] = ifr.ipfr_next;
1758 }
1759 }
1760 /*
1761 * Print out the contents (if any) of the NAT fragment cache table.
1762 */
1763
1764 if (live_kernel == 0) {
1765 if (kmemcpy((char *)ipfrtab, (u_long)ifsp->ifs_nattab,
1766 sizeof(ipfrtab)))
1767 return;
1768 }
1769
1770 if (live_kernel == 1) {
1771 do {
1772 if (fetchfrag(nat_fd, IPFGENITER_NATFRAG, &ifr) != 0)
1773 break;
1774 if (ifr.ipfr_ifp == NULL)
1775 break;
1776 ifr.ipfr_ttl -= ticks;
1777 printfraginfo("NAT: ", &ifr);
1778 } while (ifr.ipfr_next != NULL);
1779 } else {
1780 for (i = 0; i < IPFT_SIZE; i++)
1781 while (ipfrtab[i] != NULL) {
1782 if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i],
1783 sizeof(ifr)) == -1)
1784 break;
1785 printfraginfo("NAT: ", &ifr);
1786 ipfrtab[i] = ifr.ipfr_next;
1787 }
1788 }
1789 }
1790
1791
1792 /*
1793 * Show stats on how auth within IPFilter has been used
1794 */
showauthstates(ipf_authstat_t * asp)1795 static void showauthstates(ipf_authstat_t *asp)
1796 {
1797 frauthent_t *frap, fra;
1798 ipfgeniter_t auth;
1799 ipfobj_t obj;
1800
1801 obj.ipfo_rev = IPFILTER_VERSION;
1802 obj.ipfo_type = IPFOBJ_GENITER;
1803 obj.ipfo_size = sizeof(auth);
1804 obj.ipfo_ptr = &auth;
1805
1806 auth.igi_type = IPFGENITER_AUTH;
1807 auth.igi_nitems = 1;
1808 auth.igi_data = &fra;
1809
1810 #ifdef USE_QUAD_T
1811 printf("Authorisation hits: %"PRIu64"\tmisses %"PRIu64"\n",
1812 (unsigned long long) asp->fas_hits,
1813 (unsigned long long) asp->fas_miss);
1814 #else
1815 printf("Authorisation hits: %ld\tmisses %ld\n", asp->fas_hits,
1816 asp->fas_miss);
1817 #endif
1818 printf("nospace %ld\nadded %ld\nsendfail %ld\nsendok %ld\n",
1819 asp->fas_nospace, asp->fas_added, asp->fas_sendfail,
1820 asp->fas_sendok);
1821 printf("queok %ld\nquefail %ld\nexpire %ld\n",
1822 asp->fas_queok, asp->fas_quefail, asp->fas_expire);
1823
1824 frap = asp->fas_faelist;
1825 while (frap) {
1826 if (live_kernel == 1) {
1827 if (ioctl(auth_fd, SIOCGENITER, &obj))
1828 break;
1829 } else {
1830 if (kmemcpy((char *)&fra, (u_long)frap,
1831 sizeof(fra)) == -1)
1832 break;
1833 }
1834 printf("age %ld\t", fra.fae_age);
1835 printfr(&fra.fae_fr, ioctl);
1836 frap = fra.fae_next;
1837 }
1838 }
1839
1840
1841 /*
1842 * Display groups used for each of filter rules, accounting rules and
1843 * authentication, separately.
1844 */
showgroups(struct friostat * fiop)1845 static void showgroups(struct friostat *fiop)
1846 {
1847 static char *gnames[3] = { "Filter", "Accounting", "Authentication" };
1848 static int gnums[3] = { IPL_LOGIPF, IPL_LOGCOUNT, IPL_LOGAUTH };
1849 frgroup_t *fp, grp;
1850 int on, off, i;
1851
1852 on = fiop->f_active;
1853 off = 1 - on;
1854
1855 for (i = 0; i < 3; i++) {
1856 printf("%s groups (active):\n", gnames[i]);
1857 for (fp = fiop->f_groups[gnums[i]][on]; fp != NULL;
1858 fp = grp.fg_next)
1859 if (kmemcpy((char *)&grp, (u_long)fp, sizeof(grp)))
1860 break;
1861 else
1862 printf("%s\n", grp.fg_name);
1863 printf("%s groups (inactive):\n", gnames[i]);
1864 for (fp = fiop->f_groups[gnums[i]][off]; fp != NULL;
1865 fp = grp.fg_next)
1866 if (kmemcpy((char *)&grp, (u_long)fp, sizeof(grp)))
1867 break;
1868 else
1869 printf("%s\n", grp.fg_name);
1870 }
1871 }
1872
1873
parse_ipportstr(const char * argument,i6addr_t * ip,int * port)1874 static void parse_ipportstr(const char *argument, i6addr_t *ip, int *port)
1875 {
1876 char *s, *comma;
1877 int ok = 0;
1878
1879 /* make working copy of argument, Theoretically you must be able
1880 * to write to optarg, but that seems very ugly to me....
1881 */
1882 s = strdup(argument);
1883 if (s == NULL)
1884 return;
1885
1886 /* get port */
1887 if ((comma = strchr(s, ',')) != NULL) {
1888 if (!strcasecmp(comma + 1, "any")) {
1889 *port = -1;
1890 } else if (!sscanf(comma + 1, "%d", port) ||
1891 (*port < 0) || (*port > 65535)) {
1892 fprintf(stderr, "Invalid port specification in %s\n",
1893 argument);
1894 free(s);
1895 exit(-2);
1896 }
1897 *comma = '\0';
1898 }
1899
1900
1901 /* get ip address */
1902 if (!strcasecmp(s, "any")) {
1903 ip->in4.s_addr = INADDR_ANY;
1904 ok = 1;
1905 #ifdef USE_INET6
1906 ip->in6 = in6addr_any;
1907 } else if (use_inet6 && !use_inet4 && inet_pton(AF_INET6, s, &ip->in6)) {
1908 ok = 1;
1909 #endif
1910 } else if (inet_aton(s, &ip->in4))
1911 ok = 1;
1912
1913 if (ok == 0) {
1914 fprintf(stderr, "Invalid IP address: %s\n", s);
1915 free(s);
1916 exit(-2);
1917 }
1918
1919 /* free allocated memory */
1920 free(s);
1921 }
1922
1923
1924 #ifdef STATETOP
sig_resize(int s)1925 static void sig_resize(int s)
1926 {
1927 handle_resize = 1;
1928 }
1929
sig_break(int s)1930 static void sig_break(int s)
1931 {
1932 handle_break = 1;
1933 }
1934
getip(int v,i6addr_t * addr)1935 static char *getip(int v, i6addr_t *addr)
1936 {
1937 #ifdef USE_INET6
1938 static char hostbuf[MAXHOSTNAMELEN+1];
1939 #endif
1940
1941 if (v == 0)
1942 return ("any");
1943
1944 if (v == 4)
1945 return (inet_ntoa(addr->in4));
1946
1947 #ifdef USE_INET6
1948 (void) inet_ntop(AF_INET6, &addr->in6, hostbuf, sizeof(hostbuf) - 1);
1949 hostbuf[MAXHOSTNAMELEN] = '\0';
1950 return (hostbuf);
1951 #else
1952 return ("IPv6");
1953 #endif
1954 }
1955
1956
ttl_to_string(long int ttl)1957 static char *ttl_to_string(long int ttl)
1958 {
1959 static char ttlbuf[STSTRSIZE];
1960 int hours, minutes, seconds;
1961
1962 /* ttl is in half seconds */
1963 ttl /= 2;
1964
1965 hours = ttl / 3600;
1966 ttl = ttl % 3600;
1967 minutes = ttl / 60;
1968 seconds = ttl % 60;
1969
1970 if (hours > 0)
1971 snprintf(ttlbuf, sizeof(ttlbuf), "%2d:%02d:%02d", hours, minutes, seconds);
1972 else
1973 snprintf(ttlbuf, sizeof(ttlbuf), "%2d:%02d", minutes, seconds);
1974 return (ttlbuf);
1975 }
1976
1977
sort_pkts(const void * a,const void * b)1978 static int sort_pkts(const void *a, const void *b)
1979 {
1980
1981 register const statetop_t *ap = a;
1982 register const statetop_t *bp = b;
1983
1984 if (ap->st_pkts == bp->st_pkts)
1985 return (0);
1986 else if (ap->st_pkts < bp->st_pkts)
1987 return (1);
1988 return (-1);
1989 }
1990
1991
sort_bytes(const void * a,const void * b)1992 static int sort_bytes(const void *a, const void *b)
1993 {
1994 register const statetop_t *ap = a;
1995 register const statetop_t *bp = b;
1996
1997 if (ap->st_bytes == bp->st_bytes)
1998 return (0);
1999 else if (ap->st_bytes < bp->st_bytes)
2000 return (1);
2001 return (-1);
2002 }
2003
2004
sort_p(const void * a,const void * b)2005 static int sort_p(const void *a, const void *b)
2006 {
2007 register const statetop_t *ap = a;
2008 register const statetop_t *bp = b;
2009
2010 if (ap->st_p == bp->st_p)
2011 return (0);
2012 else if (ap->st_p < bp->st_p)
2013 return (1);
2014 return (-1);
2015 }
2016
2017
sort_ttl(const void * a,const void * b)2018 static int sort_ttl(const void *a, const void *b)
2019 {
2020 register const statetop_t *ap = a;
2021 register const statetop_t *bp = b;
2022
2023 if (ap->st_age == bp->st_age)
2024 return (0);
2025 else if (ap->st_age < bp->st_age)
2026 return (1);
2027 return (-1);
2028 }
2029
sort_srcip(const void * a,const void * b)2030 static int sort_srcip(const void *a, const void *b)
2031 {
2032 register const statetop_t *ap = a;
2033 register const statetop_t *bp = b;
2034
2035 #ifdef USE_INET6
2036 if (use_inet6 && !use_inet4) {
2037 if (IP6_EQ(&ap->st_src, &bp->st_src))
2038 return (0);
2039 else if (IP6_GT(&ap->st_src, &bp->st_src))
2040 return (1);
2041 } else
2042 #endif
2043 {
2044 if (ntohl(ap->st_src.in4.s_addr) ==
2045 ntohl(bp->st_src.in4.s_addr))
2046 return (0);
2047 else if (ntohl(ap->st_src.in4.s_addr) >
2048 ntohl(bp->st_src.in4.s_addr))
2049 return (1);
2050 }
2051 return (-1);
2052 }
2053
sort_srcpt(const void * a,const void * b)2054 static int sort_srcpt(const void *a, const void *b)
2055 {
2056 register const statetop_t *ap = a;
2057 register const statetop_t *bp = b;
2058
2059 if (htons(ap->st_sport) == htons(bp->st_sport))
2060 return (0);
2061 else if (htons(ap->st_sport) > htons(bp->st_sport))
2062 return (1);
2063 return (-1);
2064 }
2065
sort_dstip(const void * a,const void * b)2066 static int sort_dstip(const void *a, const void *b)
2067 {
2068 register const statetop_t *ap = a;
2069 register const statetop_t *bp = b;
2070
2071 #ifdef USE_INET6
2072 if (use_inet6 && !use_inet4) {
2073 if (IP6_EQ(&ap->st_dst, &bp->st_dst))
2074 return (0);
2075 else if (IP6_GT(&ap->st_dst, &bp->st_dst))
2076 return (1);
2077 } else
2078 #endif
2079 {
2080 if (ntohl(ap->st_dst.in4.s_addr) ==
2081 ntohl(bp->st_dst.in4.s_addr))
2082 return (0);
2083 else if (ntohl(ap->st_dst.in4.s_addr) >
2084 ntohl(bp->st_dst.in4.s_addr))
2085 return (1);
2086 }
2087 return (-1);
2088 }
2089
sort_dstpt(const void * a,const void * b)2090 static int sort_dstpt(const void *a, const void *b)
2091 {
2092 register const statetop_t *ap = a;
2093 register const statetop_t *bp = b;
2094
2095 if (htons(ap->st_dport) == htons(bp->st_dport))
2096 return (0);
2097 else if (htons(ap->st_dport) > htons(bp->st_dport))
2098 return (1);
2099 return (-1);
2100 }
2101
2102 #endif
2103
2104
fetchstate(ipstate_t * src,ipstate_t * dst)2105 ipstate_t *fetchstate(ipstate_t *src, ipstate_t *dst)
2106 {
2107
2108 if (live_kernel == 1) {
2109 ipfgeniter_t state;
2110 ipfobj_t obj;
2111
2112 obj.ipfo_rev = IPFILTER_VERSION;
2113 obj.ipfo_type = IPFOBJ_GENITER;
2114 obj.ipfo_size = sizeof(state);
2115 obj.ipfo_ptr = &state;
2116
2117 state.igi_type = IPFGENITER_STATE;
2118 state.igi_nitems = 1;
2119 state.igi_data = dst;
2120
2121 if (ioctl(state_fd, SIOCGENITER, &obj) != 0)
2122 return (NULL);
2123 if (dst->is_next == NULL) {
2124 int n = IPFGENITER_STATE;
2125 (void) ioctl(ipf_fd,SIOCIPFDELTOK, &n);
2126 }
2127 } else {
2128 if (kmemcpy((char *)dst, (u_long)src, sizeof(*dst)))
2129 return (NULL);
2130 }
2131 return (dst);
2132 }
2133
2134
fetchfrag(int fd,int type,ipfr_t * frp)2135 static int fetchfrag( int fd, int type, ipfr_t *frp)
2136 {
2137 ipfgeniter_t frag;
2138 ipfobj_t obj;
2139
2140 obj.ipfo_rev = IPFILTER_VERSION;
2141 obj.ipfo_type = IPFOBJ_GENITER;
2142 obj.ipfo_size = sizeof(frag);
2143 obj.ipfo_ptr = &frag;
2144
2145 frag.igi_type = type;
2146 frag.igi_nitems = 1;
2147 frag.igi_data = frp;
2148
2149 if (ioctl(fd, SIOCGENITER, &obj))
2150 return (EFAULT);
2151 return (0);
2152 }
2153
2154
state_matcharray(ipstate_t * stp,int * array)2155 static int state_matcharray(ipstate_t *stp, int *array)
2156 {
2157 int i, n, *x, rv, p;
2158 ipfexp_t *e;
2159
2160 rv = 0;
2161
2162 for (n = array[0], x = array + 1; n > 0; x += e->ipfe_size) {
2163 e = (ipfexp_t *)x;
2164 if (e->ipfe_cmd == IPF_EXP_END)
2165 break;
2166 n -= e->ipfe_size;
2167
2168 rv = 0;
2169 /*
2170 * The upper 16 bits currently store the protocol value.
2171 * This is currently used with TCP and UDP port compares and
2172 * allows "tcp.port = 80" without requiring an explicit
2173 " "ip.pr = tcp" first.
2174 */
2175 p = e->ipfe_cmd >> 16;
2176 if ((p != 0) && (p != stp->is_p))
2177 break;
2178
2179 switch (e->ipfe_cmd)
2180 {
2181 case IPF_EXP_IP_PR :
2182 for (i = 0; !rv && i < e->ipfe_narg; i++) {
2183 rv |= (stp->is_p == e->ipfe_arg0[i]);
2184 }
2185 break;
2186
2187 case IPF_EXP_IP_SRCADDR :
2188 if (stp->is_v != 4)
2189 break;
2190 for (i = 0; !rv && i < e->ipfe_narg; i++) {
2191 rv |= ((stp->is_saddr &
2192 e->ipfe_arg0[i * 2 + 1]) ==
2193 e->ipfe_arg0[i * 2]);
2194 }
2195 break;
2196
2197 case IPF_EXP_IP_DSTADDR :
2198 if (stp->is_v != 4)
2199 break;
2200 for (i = 0; !rv && i < e->ipfe_narg; i++) {
2201 rv |= ((stp->is_daddr &
2202 e->ipfe_arg0[i * 2 + 1]) ==
2203 e->ipfe_arg0[i * 2]);
2204 }
2205 break;
2206
2207 case IPF_EXP_IP_ADDR :
2208 if (stp->is_v != 4)
2209 break;
2210 for (i = 0; !rv && i < e->ipfe_narg; i++) {
2211 rv |= ((stp->is_saddr &
2212 e->ipfe_arg0[i * 2 + 1]) ==
2213 e->ipfe_arg0[i * 2]) ||
2214 ((stp->is_daddr &
2215 e->ipfe_arg0[i * 2 + 1]) ==
2216 e->ipfe_arg0[i * 2]);
2217 }
2218 break;
2219
2220 #ifdef USE_INET6
2221 case IPF_EXP_IP6_SRCADDR :
2222 if (stp->is_v != 6)
2223 break;
2224 for (i = 0; !rv && i < e->ipfe_narg; i++) {
2225 rv |= IP6_MASKEQ(&stp->is_src,
2226 &e->ipfe_arg0[i * 8 + 4],
2227 &e->ipfe_arg0[i * 8]);
2228 }
2229 break;
2230
2231 case IPF_EXP_IP6_DSTADDR :
2232 if (stp->is_v != 6)
2233 break;
2234 for (i = 0; !rv && i < e->ipfe_narg; i++) {
2235 rv |= IP6_MASKEQ(&stp->is_dst,
2236 &e->ipfe_arg0[i * 8 + 4],
2237 &e->ipfe_arg0[i * 8]);
2238 }
2239 break;
2240
2241 case IPF_EXP_IP6_ADDR :
2242 if (stp->is_v != 6)
2243 break;
2244 for (i = 0; !rv && i < e->ipfe_narg; i++) {
2245 rv |= IP6_MASKEQ(&stp->is_src,
2246 &e->ipfe_arg0[i * 8 + 4],
2247 &e->ipfe_arg0[i * 8]) ||
2248 IP6_MASKEQ(&stp->is_dst,
2249 &e->ipfe_arg0[i * 8 + 4],
2250 &e->ipfe_arg0[i * 8]);
2251 }
2252 break;
2253 #endif
2254
2255 case IPF_EXP_UDP_PORT :
2256 case IPF_EXP_TCP_PORT :
2257 for (i = 0; !rv && i < e->ipfe_narg; i++) {
2258 rv |= (stp->is_sport == e->ipfe_arg0[i]) ||
2259 (stp->is_dport == e->ipfe_arg0[i]);
2260 }
2261 break;
2262
2263 case IPF_EXP_UDP_SPORT :
2264 case IPF_EXP_TCP_SPORT :
2265 for (i = 0; !rv && i < e->ipfe_narg; i++) {
2266 rv |= (stp->is_sport == e->ipfe_arg0[i]);
2267 }
2268 break;
2269
2270 case IPF_EXP_UDP_DPORT :
2271 case IPF_EXP_TCP_DPORT :
2272 for (i = 0; !rv && i < e->ipfe_narg; i++) {
2273 rv |= (stp->is_dport == e->ipfe_arg0[i]);
2274 }
2275 break;
2276
2277 case IPF_EXP_IDLE_GT :
2278 for (i = 0; !rv && i < e->ipfe_narg; i++) {
2279 rv |= (stp->is_die < e->ipfe_arg0[i]);
2280 }
2281 break;
2282
2283 case IPF_EXP_TCP_STATE :
2284 for (i = 0; !rv && i < e->ipfe_narg; i++) {
2285 rv |= (stp->is_state[0] == e->ipfe_arg0[i]) ||
2286 (stp->is_state[1] == e->ipfe_arg0[i]);
2287 }
2288 break;
2289 }
2290 rv ^= e->ipfe_not;
2291
2292 if (rv == 0)
2293 break;
2294 }
2295
2296 return (rv);
2297 }
2298
2299
showtqtable_live(int fd)2300 static void showtqtable_live(int fd)
2301 {
2302 ipftq_t table[IPF_TCP_NSTATES];
2303 ipfobj_t obj;
2304
2305 bzero((char *)&obj, sizeof(obj));
2306 obj.ipfo_rev = IPFILTER_VERSION;
2307 obj.ipfo_size = sizeof(table);
2308 obj.ipfo_ptr = (void *)table;
2309 obj.ipfo_type = IPFOBJ_STATETQTAB;
2310
2311 if (ioctl(fd, SIOCGTQTAB, &obj) == 0) {
2312 printtqtable(table);
2313 }
2314 }
2315