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