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