]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/ipfilter/fils.c
This commit was generated by cvs2svn to compensate for changes in r52287,
[FreeBSD/FreeBSD.git] / contrib / ipfilter / fils.c
1 /*
2  * Copyright (C) 1993-1997 by Darren Reed.
3  *
4  * Redistribution and use in source and binary forms are permitted
5  * provided that this notice is preserved and due credit is given
6  * to the original author and the contributors.
7  */
8
9 #include <stdio.h>
10 #include <string.h>
11 #if !defined(__SVR4) && !defined(__svr4__)
12 #include <strings.h>
13 #endif
14 #include <sys/types.h>
15 #include <sys/time.h>
16 #include <sys/param.h>
17 #include <sys/file.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20 #include <fcntl.h>
21 #include <stddef.h>
22 #include <nlist.h>
23 #include <sys/socket.h>
24 #include <sys/ioctl.h>
25 #include <netinet/in.h>
26 #include <arpa/inet.h>
27 #include <netinet/in_systm.h>
28 #include <netinet/ip.h>
29 #include <net/if.h>
30 #include <netdb.h>
31 #include <arpa/nameser.h>
32 #include <resolv.h>
33 #include <netinet/tcp.h>
34 #include "netinet/ip_compat.h"
35 #include "netinet/ip_fil.h"
36 #include "ipf.h"
37 #include "netinet/ip_proxy.h"
38 #include "netinet/ip_nat.h"
39 #include "netinet/ip_frag.h"
40 #include "netinet/ip_state.h"
41 #include "netinet/ip_auth.h"
42 #include "kmem.h"
43 #if defined(__NetBSD__) || (__OpenBSD__)
44 #include <paths.h>
45 #endif
46
47 #if !defined(lint)
48 static const char sccsid[] = "@(#)fils.c        1.21 4/20/96 (C) 1993-1996 Darren Reed";
49 static const char rcsid[] = "@(#)$Id: fils.c,v 2.0.2.25.2.2 1997/11/20 12:41:04 darrenr Exp $";
50 #endif
51 #ifdef  _PATH_UNIX
52 #define VMUNIX  _PATH_UNIX
53 #else
54 #define VMUNIX  "/vmunix"
55 #endif
56
57 extern  char    *optarg;
58
59 #define PRINTF  (void)printf
60 #define FPRINTF (void)fprintf
61 #define F_IN    0
62 #define F_OUT   1
63 #define F_AC    2
64 static  char    *filters[4] = { "ipfilter(in)", "ipfilter(out)",
65                                 "ipacct(in)", "ipacct(out)" };
66
67 int     opts = 0;
68
69 extern  int     main __P((int, char *[]));
70 static  void    showstats __P((int, friostat_t *));
71 static  void    showfrstates __P((int, ipfrstat_t *));
72 static  void    showlist __P((friostat_t *));
73 static  void    showipstates __P((int, ips_stat_t *));
74 static  void    showauthstates __P((int, fr_authstat_t *));
75 static  void    Usage __P((char *));
76 static  void    printlist __P((frentry_t *));
77
78
79 static void Usage(name)
80 char *name;
81 {
82         fprintf(stderr, "Usage: %s [-aAfhIinosv] [-d <device>]\n", name);
83         exit(1);
84 }
85
86
87 int main(argc,argv)
88 int argc;
89 char *argv[];
90 {
91         fr_authstat_t   frauthst;
92         friostat_t fio;
93         ips_stat_t ipsst;
94         ipfrstat_t ifrst;
95         char    *name = NULL, *device = IPL_NAME;
96         int     c, fd;
97
98         if (openkmem() == -1)
99                 exit(-1);
100
101         (void)setuid(getuid());
102         (void)setgid(getgid());
103
104         while ((c = getopt(argc, argv, "aAfhIinosvd:")) != -1)
105         {
106                 switch (c)
107                 {
108                 case 'a' :
109                         opts |= OPT_ACCNT|OPT_SHOWLIST;
110                         break;
111                 case 'A' :
112                         opts |= OPT_AUTHSTATS;
113                         break;
114                 case 'd' :
115                         device = optarg;
116                         break;
117                 case 'f' :
118                         opts |= OPT_FRSTATES;
119                         break;
120                 case 'h' :
121                         opts |= OPT_HITS;
122                         break;
123                 case 'i' :
124                         opts |= OPT_INQUE|OPT_SHOWLIST;
125                         break;
126                 case 'I' :
127                         opts |= OPT_INACTIVE;
128                         break;
129                 case 'n' :
130                         opts |= OPT_SHOWLINENO;
131                         break;
132                 case 'o' :
133                         opts |= OPT_OUTQUE|OPT_SHOWLIST;
134                         break;
135                 case 's' :
136                         opts |= OPT_IPSTATES;
137                         break;
138                 case 'v' :
139                         opts |= OPT_VERBOSE;
140                         break;
141                 default :
142                         Usage(argv[0]);
143                         break;
144                 }
145         }
146
147         if ((fd = open(device, O_RDONLY)) < 0) {
148                 perror("open");
149                 exit(-1);
150         }
151
152         bzero((char *)&fio, sizeof(fio));
153         bzero((char *)&ipsst, sizeof(ipsst));
154         bzero((char *)&ifrst, sizeof(ifrst));
155
156         if (ioctl(fd, SIOCGETFS, &fio) == -1) {
157                 perror("ioctl(SIOCGETFS)");
158                 exit(-1);
159         }
160         if ((opts & OPT_IPSTATES)) {
161                 int     sfd = open(IPL_STATE, O_RDONLY);
162
163                 if (sfd == -1) {
164                         perror("open");
165                         exit(-1);
166                 }
167                 if ((ioctl(sfd, SIOCGIPST, &ipsst) == -1)) {
168                         perror("ioctl(SIOCGIPST)");
169                         exit(-1);
170                 }
171                 close(sfd);
172         }
173         if ((opts & OPT_FRSTATES) && (ioctl(fd, SIOCGFRST, &ifrst) == -1)) {
174                 perror("ioctl(SIOCGFRST)");
175                 exit(-1);
176         }
177
178         if (opts & OPT_VERBOSE)
179                 PRINTF("opts %#x name %s\n", opts, name ? name : "<>");
180
181         if ((opts & OPT_AUTHSTATS) &&
182             (ioctl(fd, SIOCATHST, &frauthst) == -1)) {
183                 perror("ioctl(SIOCATHST)");
184                 exit(-1);
185         }
186
187         if (opts & OPT_SHOWLIST) {
188                 showlist(&fio);
189                 if ((opts & OPT_OUTQUE) && (opts & OPT_INQUE)){
190                         opts &= ~OPT_OUTQUE;
191                         showlist(&fio);
192                 }
193         } else {
194                 if (opts & OPT_IPSTATES)
195                         showipstates(fd, &ipsst);
196                 else if (opts & OPT_FRSTATES)
197                         showfrstates(fd, &ifrst);
198                 else if (opts & OPT_AUTHSTATS)
199                         showauthstates(fd, &frauthst);
200                 else
201                         showstats(fd, &fio);
202         }
203         return 0;
204 }
205
206
207 /*
208  * read the kernel stats for packets blocked and passed
209  */
210 static  void    showstats(fd, fp)
211 int     fd;
212 struct  friostat        *fp;
213 {
214         int     frf = 0;
215
216         if (ioctl(fd, SIOCGETFF, &frf) == -1)
217                 perror("ioctl(SIOCGETFF)");
218
219 #if SOLARIS
220         PRINTF("dropped packets:\tin %lu\tout %lu\n",
221                         fp->f_st[0].fr_drop, fp->f_st[1].fr_drop);
222         PRINTF("non-ip packets:\t\tin %lu\tout %lu\n",
223                         fp->f_st[0].fr_notip, fp->f_st[1].fr_notip);
224         PRINTF("   bad packets:\t\tin %lu\tout %lu\n",
225                         fp->f_st[0].fr_bad, fp->f_st[1].fr_bad);
226 #endif
227         PRINTF(" input packets:\t\tblocked %lu passed %lu nomatch %lu",
228                         fp->f_st[0].fr_block, fp->f_st[0].fr_pass,
229                         fp->f_st[0].fr_nom);
230         PRINTF(" counted %lu\n", fp->f_st[0].fr_acct);
231         PRINTF("output packets:\t\tblocked %lu passed %lu nomatch %lu",
232                         fp->f_st[1].fr_block, fp->f_st[1].fr_pass,
233                         fp->f_st[1].fr_nom);
234         PRINTF(" counted %lu\n", fp->f_st[0].fr_acct);
235         PRINTF(" input packets logged:\tblocked %lu passed %lu\n",
236                         fp->f_st[0].fr_bpkl, fp->f_st[0].fr_ppkl);
237         PRINTF("output packets logged:\tblocked %lu passed %lu\n",
238                         fp->f_st[1].fr_bpkl, fp->f_st[1].fr_ppkl);
239         PRINTF(" packets logged:\tinput %lu output %lu\n",
240                         fp->f_st[0].fr_pkl, fp->f_st[1].fr_pkl);
241         PRINTF(" log failures:\t\tinput %lu output %lu\n",
242                         fp->f_st[0].fr_skip, fp->f_st[1].fr_skip);
243         PRINTF("fragment state(in):\tkept %lu\tlost %lu\n",
244                         fp->f_st[0].fr_nfr, fp->f_st[0].fr_bnfr);
245         PRINTF("fragment state(out):\tkept %lu\tlost %lu\n",
246                         fp->f_st[1].fr_nfr, fp->f_st[1].fr_bnfr);
247         PRINTF("packet state(in):\tkept %lu\tlost %lu\n",
248                         fp->f_st[0].fr_ads, fp->f_st[0].fr_bads);
249         PRINTF("packet state(out):\tkept %lu\tlost %lu\n",
250                         fp->f_st[1].fr_ads, fp->f_st[1].fr_bads);
251         PRINTF("ICMP replies:\t%lu\tTCP RSTs sent:\t%lu\n",
252                         fp->f_st[0].fr_ret, fp->f_st[1].fr_ret);
253         PRINTF("Result cache hits(in):\t%lu\t(out):\t%lu\n",
254                         fp->f_st[0].fr_chit, fp->f_st[1].fr_chit);
255         PRINTF("IN Pullups succeeded:\t%lu\tfailed:\t%lu\n",
256                         fp->f_st[0].fr_pull[0], fp->f_st[0].fr_pull[1]);
257         PRINTF("OUT Pullups succeeded:\t%lu\tfailed:\t%lu\n",
258                         fp->f_st[1].fr_pull[0], fp->f_st[1].fr_pull[1]);
259         PRINTF("Fastroute successes:\t%lu\tfailures:\t%lu\n",
260                         fp->f_froute[0], fp->f_froute[1]);
261         PRINTF("TCP cksum fails(in):\t%lu\t(out):\t%lu\n",
262                         fp->f_st[0].fr_tcpbad, fp->f_st[1].fr_tcpbad);
263
264         PRINTF("Packet log flags set: (%#x)\n", frf);
265         if (frf & FF_LOGPASS)
266                 PRINTF("\tpackets passed through filter\n");
267         if (frf & FF_LOGBLOCK)
268                 PRINTF("\tpackets blocked by filter\n");
269         if (frf & FF_LOGNOMATCH)
270                 PRINTF("\tpackets not matched by filter\n");
271         if (!frf)
272                 PRINTF("\tnone\n");
273 }
274
275
276 static void printlist(fp)
277 frentry_t *fp;
278 {
279         struct  frentry fb;
280         int     n;
281
282         for (n = 1; fp; n++) {
283                 if (kmemcpy((char *)&fb, (u_long)fp, sizeof(fb)) == -1) {
284                         perror("kmemcpy");
285                         return;
286                 }
287                 fp = &fb;
288                 if (opts & OPT_OUTQUE)
289                         fp->fr_flags |= FR_OUTQUE;
290                 if (opts & (OPT_HITS|OPT_VERBOSE))
291 #ifdef  USE_QUAD_T
292                         PRINTF("%qd ", fp->fr_hits);
293 #else
294                         PRINTF("%ld ", fp->fr_hits);
295 #endif
296                 if (opts & (OPT_ACCNT|OPT_VERBOSE))
297 #ifdef  USE_QUAD_T
298                         PRINTF("%qd ", fp->fr_bytes);
299 #else
300                         PRINTF("%ld ", fp->fr_bytes);
301 #endif
302                 if (opts & OPT_SHOWLINENO)
303                         PRINTF("@%d ", n);
304                 printfr(fp);
305                 if (opts & OPT_VERBOSE)
306                         binprint(fp);
307                 if (fp->fr_grp)
308                         printlist(fp->fr_grp);
309                 fp = fp->fr_next;
310         }
311 }
312
313 /*
314  * print out filter rule list
315  */
316 static  void    showlist(fiop)
317 struct  friostat        *fiop;
318 {
319         struct  frentry *fp = NULL;
320         int     i, set;
321
322         set = fiop->f_active;
323         if (opts & OPT_INACTIVE)
324                 set = 1 - set;
325         if (opts & OPT_ACCNT) {
326                 i = F_AC;
327                 if (opts & OPT_OUTQUE) {
328                         fp = (struct frentry *)fiop->f_acctout[set];
329                         i++;
330                 } else if (opts & OPT_INQUE)
331                         fp = (struct frentry *)fiop->f_acctin[set];
332                 else {
333                         FPRINTF(stderr, "No -i or -o given with -a\n");
334                         return;
335                 }
336         } else if (opts & OPT_OUTQUE) {
337                 i = F_OUT;
338                 fp = (struct frentry *)fiop->f_fout[set];
339         } else if (opts & OPT_INQUE) {
340                 i = F_IN;
341                 fp = (struct frentry *)fiop->f_fin[set];
342         } else
343                 return;
344         if (opts & OPT_VERBOSE)
345                 FPRINTF(stderr, "showlist:opts %#x i %d\n", opts, i);
346
347         if (opts & OPT_VERBOSE)
348                 PRINTF("fp %p set %d\n", fp, set);
349         if (!fp) {
350                 FPRINTF(stderr, "empty list for %s%s\n",
351                         (opts & OPT_INACTIVE) ? "inactive " : "", filters[i]);
352                 return;
353         }
354         printlist(fp);
355 }
356
357
358 static void showipstates(fd, ipsp)
359 int fd;
360 ips_stat_t *ipsp;
361 {
362         ipstate_t *istab[IPSTATE_SIZE], ips;
363         int i;
364
365         PRINTF("IP states added:\n\t%lu TCP\n\t%lu UDP\n\t%lu ICMP\n",
366                 ipsp->iss_tcp, ipsp->iss_udp, ipsp->iss_icmp);
367         PRINTF("\t%lu hits\n\t%lu misses\n", ipsp->iss_hits, ipsp->iss_miss);
368         PRINTF("\t%lu maximum\n\t%lu no memory\n",
369                 ipsp->iss_max, ipsp->iss_nomem);
370         PRINTF("\t%lu active\n\t%lu expired\n\t%lu closed\n",
371                 ipsp->iss_active, ipsp->iss_expire, ipsp->iss_fin);
372         if (kmemcpy((char *)istab, (u_long)ipsp->iss_table, sizeof(istab)))
373                 return;
374         for (i = 0; i < IPSTATE_SIZE; i++)
375                 while (istab[i]) {
376                         if (kmemcpy((char *)&ips, (u_long)istab[i],
377                                     sizeof(ips)) == -1)
378                                 break;
379                         PRINTF("%s -> ", inet_ntoa(ips.is_src));
380                         PRINTF("%s ttl %ld pass %d pr %d state %d/%d\n",
381                                 inet_ntoa(ips.is_dst), ips.is_age,
382                                 ips.is_pass, ips.is_p, ips.is_state[0],
383                                 ips.is_state[1]);
384 #ifdef  USE_QUAD_T
385                         PRINTF("\tpkts %qd bytes %qd",
386                                 ips.is_pkts, ips.is_bytes);
387 #else
388                         PRINTF("\tpkts %ld bytes %ld",
389                                 ips.is_pkts, ips.is_bytes);
390 #endif
391                         if (ips.is_p == IPPROTO_TCP)
392                                 PRINTF("\t%hu -> %hu %lu:%lu %hu:%hu\n",
393                                         ntohs(ips.is_sport),
394                                         ntohs(ips.is_dport),
395                                         ips.is_seq, ips.is_ack,
396                                         ips.is_swin, ips.is_dwin);
397                         else if (ips.is_p == IPPROTO_UDP)
398                                 PRINTF(" %hu -> %hu\n", ntohs(ips.is_sport),
399                                         ntohs(ips.is_dport));
400                         else if (ips.is_p == IPPROTO_ICMP)
401                                 PRINTF(" %hu %hu %d\n", ips.is_icmp.ics_id,
402                                         ips.is_icmp.ics_seq,
403                                         ips.is_icmp.ics_type);
404
405                         /* phil@ultimate.com ... */
406                         PRINTF("\t");
407                         /* from "printfr()" */
408                         if (ips.is_pass & FR_PASS) {
409                                 PRINTF("pass");
410                         } else if (ips.is_pass & FR_BLOCK) {
411                                 PRINTF("block");
412                                 if (ips.is_pass & FR_RETICMP)
413                                         PRINTF(" return-icmp");
414                                 if (ips.is_pass & FR_RETRST)
415                                         PRINTF(" return-rst");
416                         } else if ((ips.is_pass & FR_LOGMASK) == FR_LOG) {
417                                         PRINTF("log");
418                                 if (ips.is_pass & FR_LOGBODY)
419                                         PRINTF(" body");
420                                 if (ips.is_pass & FR_LOGFIRST)
421                                         PRINTF(" first");
422                         } else if (ips.is_pass & FR_ACCOUNT)
423                                 PRINTF("count");
424
425                         if (ips.is_pass & FR_OUTQUE)
426                                 PRINTF(" out");
427                         else
428                                 PRINTF(" in");
429
430                         if ((ips.is_pass & (FR_LOGB|FR_LOGP)) != 0) {
431                                 PRINTF(" log");
432                                 if (ips.is_pass & FR_LOGBODY)
433                                         PRINTF(" body");
434                                 if (ips.is_pass & FR_LOGFIRST)
435                                         PRINTF(" first");
436                                 if (ips.is_pass & FR_LOGORBLOCK)
437                                         PRINTF(" or-block");
438                         }
439                         if (ips.is_pass & FR_QUICK)
440                                 PRINTF(" quick");
441                         if (ips.is_pass & FR_KEEPFRAG)
442                                 PRINTF(" keep frags");
443                         /* a given; no? */
444                         if (ips.is_pass & FR_KEEPSTATE)
445                                 PRINTF(" keep state");
446                         PRINTF("\n");
447                         /* ... phil@ultimate.com */
448
449                         istab[i] = ips.is_next;
450                 }
451 }
452
453
454 static void showfrstates(fd, ifsp)
455 int fd;
456 ipfrstat_t *ifsp;
457 {
458         struct ipfr *ipfrtab[IPFT_SIZE], ifr;
459         int i;
460
461         PRINTF("IP fragment states:\n\t%lu new\n\t%lu expired\n\t%lu hits\n",
462                 ifsp->ifs_new, ifsp->ifs_expire, ifsp->ifs_hits);
463         PRINTF("\t%lu no memory\n\t%lu already exist\n",
464                 ifsp->ifs_nomem, ifsp->ifs_exists);
465         PRINTF("\t%lu inuse\n", ifsp->ifs_inuse);
466         if (kmemcpy((char *)ipfrtab, (u_long)ifsp->ifs_table, sizeof(ipfrtab)))
467                 return;
468         for (i = 0; i < IPFT_SIZE; i++)
469                 while (ipfrtab[i]) {
470                         if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i],
471                                     sizeof(ifr)) == -1)
472                                 break;
473                         PRINTF("%s -> ", inet_ntoa(ifr.ipfr_src));
474                         PRINTF("%s %d %d %d %#02x = %#x\n",
475                                 inet_ntoa(ifr.ipfr_dst), ifr.ipfr_id,
476                                 ifr.ipfr_ttl, ifr.ipfr_p, ifr.ipfr_tos,
477                                 ifr.ipfr_pass);
478                         ipfrtab[i] = ifr.ipfr_next;
479                 }
480 }
481
482
483 static void showauthstates(fd, asp)
484 int fd;
485 fr_authstat_t *asp;
486 {
487 #ifdef  USE_QUAD_T
488         printf("Authorisation hits: %qd\tmisses %qd\n", asp->fas_hits,
489                 asp->fas_miss);
490 #else
491         printf("Authorisation hits: %ld\tmisses %ld\n", asp->fas_hits,
492                 asp->fas_miss);
493 #endif
494         printf("nospace %ld\nadded %ld\nsendfail %ld\nsendok %ld\n",
495                 asp->fas_nospace, asp->fas_added, asp->fas_sendfail,
496                 asp->fas_sendok);
497         printf("queok %ld\nquefail %ld\nexpire %ld\n",
498                 asp->fas_queok, asp->fas_quefail, asp->fas_expire);
499 }