]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/ipfilter/tools/ipftest.c
ipfilter #ifdef cleanup.
[FreeBSD/FreeBSD.git] / contrib / ipfilter / tools / ipftest.c
1 /*      $FreeBSD$       */
2
3 /*
4  * Copyright (C) 2012 by Darren Reed.
5  *
6  * See the IPFILTER.LICENCE file for details on licencing.
7  */
8 #include "ipf.h"
9 #include "ipt.h"
10 #include <sys/ioctl.h>
11 #include <sys/file.h>
12
13 #if !defined(lint)
14 static const char sccsid[] = "@(#)ipt.c 1.19 6/3/96 (C) 1993-2000 Darren Reed";
15 static const char rcsid[] = "@(#)$Id$";
16 #endif
17
18 extern  char    *optarg;
19 extern  struct ipread   pcap, iptext, iphex;
20 extern  struct ifnet    *get_unit __P((char *, int));
21 extern  void    init_ifp __P((void));
22 extern  ipnat_t *natparse __P((char *, int));
23 extern  hostmap_t **ipf_hm_maptable;
24 extern  hostmap_t *ipf_hm_maplist;
25
26 ipfmutex_t      ipl_mutex, ipf_auth_mx, ipf_rw, ipf_stinsert;
27 ipfmutex_t      ipf_nat_new, ipf_natio, ipf_timeoutlock;
28 ipfrwlock_t     ipf_mutex, ipf_global, ipf_ipidfrag, ip_poolrw, ipf_frcache;
29 ipfrwlock_t     ipf_frag, ipf_state, ipf_nat, ipf_natfrag, ipf_authlk;
30 ipfrwlock_t     ipf_tokens;
31 int     opts = OPT_DONTOPEN;
32 int     use_inet6 = 0;
33 int     docksum = 0;
34 int     pfil_delayed_copy = 0;
35 int     main __P((int, char *[]));
36 int     loadrules __P((char *, int));
37 int     kmemcpy __P((char *, long, int));
38 int     kstrncpy __P((char *, long, int n));
39 int     blockreason;
40 void    dumpnat __P((void *));
41 void    dumpgroups __P((ipf_main_softc_t *));
42 void    dumprules __P((frentry_t *));
43 void    drain_log __P((char *));
44 void    fixv4sums __P((mb_t *, ip_t *));
45
46 int ipftestioctl __P((int, ioctlcmd_t, ...));
47 int ipnattestioctl __P((int, ioctlcmd_t, ...));
48 int ipstatetestioctl __P((int, ioctlcmd_t, ...));
49 int ipauthtestioctl __P((int, ioctlcmd_t, ...));
50 int ipscantestioctl __P((int, ioctlcmd_t, ...));
51 int ipsynctestioctl __P((int, ioctlcmd_t, ...));
52 int ipooltestioctl __P((int, ioctlcmd_t, ...));
53
54 static  ioctlfunc_t     iocfunctions[IPL_LOGSIZE] = { ipftestioctl,
55                                                       ipnattestioctl,
56                                                       ipstatetestioctl,
57                                                       ipauthtestioctl,
58                                                       ipsynctestioctl,
59                                                       ipscantestioctl,
60                                                       ipooltestioctl,
61                                                       NULL };
62 static  ipf_main_softc_t        *softc = NULL;
63
64
65 int
66 main(argc,argv)
67         int argc;
68         char *argv[];
69 {
70         char    *datain, *iface, *ifname, *logout;
71         int     fd, i, dir, c, loaded, dump, hlen;
72         struct  in_addr sip;
73         struct  ifnet   *ifp;
74         struct  ipread  *r;
75         mb_t    mb, *m, *n;
76         ip_t    *ip;
77
78         m = &mb;
79         dir = 0;
80         dump = 0;
81         hlen = 0;
82         loaded = 0;
83         r = &iptext;
84         iface = NULL;
85         logout = NULL;
86         datain = NULL;
87         sip.s_addr = 0;
88         ifname = "anon0";
89
90         initparse();
91
92         ipf_load_all();
93
94         softc = ipf_create_all(NULL);
95         if (softc == NULL)
96                 exit(1);
97
98         if (ipf_init_all(softc) == -1)
99                 exit(1);
100
101         i = 1;
102         if (ipftestioctl(IPL_LOGIPF, SIOCFRENB, &i) != 0)
103                 exit(1);
104
105         while ((c = getopt(argc, argv, "6bCdDF:i:I:l:N:P:or:RS:T:vxX")) != -1)
106                 switch (c)
107                 {
108                 case '6' :
109 #ifdef  USE_INET6
110                         use_inet6 = 1;
111 #else
112                         fprintf(stderr, "IPv6 not supported\n");
113                         exit(1);
114 #endif
115                         break;
116                 case 'b' :
117                         opts |= OPT_BRIEF;
118                         break;
119                 case 'd' :
120                         opts |= OPT_DEBUG;
121                         break;
122                 case 'C' :
123                         docksum = 1;
124                         break;
125                 case 'D' :
126                         dump = 1;
127                         break;
128                 case 'F' :
129                         if (strcasecmp(optarg, "pcap") == 0)
130                                 r = &pcap;
131                         else if (strcasecmp(optarg, "hex") == 0)
132                                 r = &iphex;
133                         else if (strcasecmp(optarg, "text") == 0)
134                                 r = &iptext;
135                         break;
136                 case 'i' :
137                         datain = optarg;
138                         break;
139                 case 'I' :
140                         ifname = optarg;
141                         break;
142                 case 'l' :
143                         logout = optarg;
144                         break;
145                 case 'N' :
146                         if (ipnat_parsefile(-1, ipnat_addrule, ipnattestioctl,
147                                             optarg) == -1)
148                                 return -1;
149                         loaded = 1;
150                         opts |= OPT_NAT;
151                         break;
152                 case 'o' :
153                         opts |= OPT_SAVEOUT;
154                         break;
155                 case 'P' :
156                         if (ippool_parsefile(-1, optarg, ipooltestioctl) == -1)
157                                 return -1;
158                         loaded = 1;
159                         break;
160                 case 'r' :
161                         if (ipf_parsefile(-1, ipf_addrule, iocfunctions,
162                                           optarg) == -1)
163                                 return -1;
164                         loaded = 1;
165                         break;
166                 case 'S' :
167                         sip.s_addr = inet_addr(optarg);
168                         break;
169                 case 'R' :
170                         opts |= OPT_NORESOLVE;
171                         break;
172                 case 'T' :
173                         ipf_dotuning(-1, optarg, ipftestioctl);
174                         break;
175                 case 'v' :
176                         opts |= OPT_VERBOSE;
177                         break;
178                 case 'x' :
179                         opts |= OPT_HEX;
180                         break;
181                 }
182
183         if (loaded == 0) {
184                 (void)fprintf(stderr,"no rules loaded\n");
185                 exit(-1);
186         }
187
188         if (opts & OPT_SAVEOUT)
189                 init_ifp();
190
191         if (datain)
192                 fd = (*r->r_open)(datain);
193         else
194                 fd = (*r->r_open)("-");
195
196         if (fd < 0) {
197                 perror("error opening input");
198                 exit(-1);
199         }
200
201         m->m_data = (char *)m->mb_buf;
202         while ((i = (*r->r_readip)(m, &iface, &dir)) > 0) {
203
204                 if ((iface == NULL) || (*iface == '\0'))
205                         iface = ifname;
206
207                 ip = MTOD(m, ip_t *);
208                 ifp = get_unit(iface, IP_V(ip));
209
210                 if (IP_V(ip) == 4) {
211                         if ((r->r_flags & R_DO_CKSUM) || docksum)
212                                 fixv4sums(m, ip);
213                         hlen = IP_HL(ip) << 2;
214                         if (sip.s_addr)
215                                 dir = !(sip.s_addr == ip->ip_src.s_addr);
216                 }
217 #ifdef  USE_INET6
218                 else
219                         hlen = sizeof(ip6_t);
220 #endif
221                 /* ipfr_slowtimer(); */
222                 blockreason = 0;
223                 m = &mb;
224                 m->mb_ifp = ifp;
225                 m->mb_len = i;
226                 i = ipf_check(softc, ip, hlen, ifp, dir, &m);
227                 if ((opts & OPT_NAT) == 0)
228                         switch (i)
229                         {
230                         case -4 :
231                                 (void)printf("preauth");
232                                 break;
233                         case -3 :
234                                 (void)printf("account");
235                                 break;
236                         case -2 :
237                                 (void)printf("auth");
238                                 break;
239                         case -1 :
240                                 (void)printf("block");
241                                 break;
242                         case 0 :
243                                 (void)printf("pass");
244                                 break;
245                         case 1 :
246                                 if (m == NULL)
247                                         (void)printf("bad-packet");
248                                 else
249                                         (void)printf("nomatch");
250                                 break;
251                         case 3 :
252                                 (void)printf("block return-rst");
253                                 break;
254                         case 4 :
255                                 (void)printf("block return-icmp");
256                                 break;
257                         case 5 :
258                                 (void)printf("block return-icmp-as-dest");
259                                 break;
260                         default :
261                                 (void)printf("recognised return %#x\n", i);
262                                 break;
263                         }
264
265                 if (!(opts & OPT_BRIEF)) {
266                         putchar(' ');
267                         if (m != NULL)
268                                 printpacket(dir, m);
269                         else
270                                 printpacket(dir, &mb);
271                         printf("--------------");
272                 } else if ((opts & (OPT_BRIEF|OPT_NAT)) ==
273                            (OPT_NAT|OPT_BRIEF)) {
274                         if (m != NULL)
275                                 printpacket(dir, m);
276                         else
277                                 PRINTF("%d\n", blockreason);
278                 }
279
280                 ipf_state_flush(softc, 1, 0);
281
282                 if (dir && (ifp != NULL) && IP_V(ip) && (m != NULL))
283                         (*ifp->if_output)(ifp, (void *)m, NULL, 0);
284
285                 while ((m != NULL) && (m != &mb)) {
286                         n = m->mb_next;
287                         freembt(m);
288                         m = n;
289                 }
290
291                 if ((opts & (OPT_BRIEF|OPT_NAT)) != (OPT_NAT|OPT_BRIEF))
292                         putchar('\n');
293                 dir = 0;
294                 if (iface != ifname) {
295                         free(iface);
296                         iface = ifname;
297                 }
298                 m = &mb;
299                 m->mb_data = (char *)m->mb_buf;
300         }
301
302         if (i != 0)
303                 fprintf(stderr, "readip failed: %d\n", i);
304         (*r->r_close)();
305
306         if (logout != NULL) {
307                 drain_log(logout);
308         }
309
310         if (dump == 1)  {
311                 dumpnat(softc->ipf_nat_soft);
312                 ipf_state_dump(softc, softc->ipf_state_soft);
313                 ipf_lookup_dump(softc, softc->ipf_state_soft);
314                 dumpgroups(softc);
315         }
316
317         ipf_fini_all(softc);
318
319         ipf_destroy_all(softc);
320
321         ipf_unload_all();
322
323         ipf_mutex_clean();
324         ipf_rwlock_clean();
325
326         if (getenv("FINDLEAKS")) {
327                 fflush(stdout);
328                 abort();
329         }
330         return 0;
331 }
332
333
334 int ipftestioctl(int dev, ioctlcmd_t cmd, ...)
335 {
336         caddr_t data;
337         va_list ap;
338         int i;
339
340         dev = dev;      /* gcc -Wextra */
341         va_start(ap, cmd);
342         data = va_arg(ap, caddr_t);
343         va_end(ap);
344
345         i = ipfioctl(softc, IPL_LOGIPF, cmd, data, FWRITE|FREAD);
346         if (opts & OPT_DEBUG)
347                 fprintf(stderr, "ipfioctl(IPF,%#x,%p) = %d (%d)\n",
348                         (u_int)cmd, data, i, softc->ipf_interror);
349         if (i != 0) {
350                 errno = i;
351                 return -1;
352         }
353         return 0;
354 }
355
356
357 int ipnattestioctl(int dev, ioctlcmd_t cmd, ...)
358 {
359         caddr_t data;
360         va_list ap;
361         int i;
362
363         dev = dev;      /* gcc -Wextra */
364         va_start(ap, cmd);
365         data = va_arg(ap, caddr_t);
366         va_end(ap);
367
368         i = ipfioctl(softc, IPL_LOGNAT, cmd, data, FWRITE|FREAD);
369         if (opts & OPT_DEBUG)
370                 fprintf(stderr, "ipfioctl(NAT,%#x,%p) = %d\n",
371                         (u_int)cmd, data, i);
372         if (i != 0) {
373                 errno = i;
374                 return -1;
375         }
376         return 0;
377 }
378
379
380 int ipstatetestioctl(int dev, ioctlcmd_t cmd, ...)
381 {
382         caddr_t data;
383         va_list ap;
384         int i;
385
386         dev = dev;      /* gcc -Wextra */
387         va_start(ap, cmd);
388         data = va_arg(ap, caddr_t);
389         va_end(ap);
390
391         i = ipfioctl(softc, IPL_LOGSTATE, cmd, data, FWRITE|FREAD);
392         if ((opts & OPT_DEBUG) || (i != 0))
393                 fprintf(stderr, "ipfioctl(STATE,%#x,%p) = %d\n",
394                         (u_int)cmd, data, i);
395         if (i != 0) {
396                 errno = i;
397                 return -1;
398         }
399         return 0;
400 }
401
402
403 int ipauthtestioctl(int dev, ioctlcmd_t cmd, ...)
404 {
405         caddr_t data;
406         va_list ap;
407         int i;
408
409         dev = dev;      /* gcc -Wextra */
410         va_start(ap, cmd);
411         data = va_arg(ap, caddr_t);
412         va_end(ap);
413
414         i = ipfioctl(softc, IPL_LOGAUTH, cmd, data, FWRITE|FREAD);
415         if ((opts & OPT_DEBUG) || (i != 0))
416                 fprintf(stderr, "ipfioctl(AUTH,%#x,%p) = %d\n",
417                         (u_int)cmd, data, i);
418         if (i != 0) {
419                 errno = i;
420                 return -1;
421         }
422         return 0;
423 }
424
425
426 int ipscantestioctl(int dev, ioctlcmd_t cmd, ...)
427 {
428         caddr_t data;
429         va_list ap;
430         int i;
431
432         dev = dev;      /* gcc -Wextra */
433         va_start(ap, cmd);
434         data = va_arg(ap, caddr_t);
435         va_end(ap);
436
437         i = ipfioctl(softc, IPL_LOGSCAN, cmd, data, FWRITE|FREAD);
438         if ((opts & OPT_DEBUG) || (i != 0))
439                 fprintf(stderr, "ipfioctl(SCAN,%#x,%p) = %d\n",
440                         (u_int)cmd, data, i);
441         if (i != 0) {
442                 errno = i;
443                 return -1;
444         }
445         return 0;
446 }
447
448
449 int ipsynctestioctl(int dev, ioctlcmd_t cmd, ...)
450 {
451         caddr_t data;
452         va_list ap;
453         int i;
454
455         dev = dev;      /* gcc -Wextra */
456         va_start(ap, cmd);
457         data = va_arg(ap, caddr_t);
458         va_end(ap);
459
460         i = ipfioctl(softc, IPL_LOGSYNC, cmd, data, FWRITE|FREAD);
461         if ((opts & OPT_DEBUG) || (i != 0))
462                 fprintf(stderr, "ipfioctl(SYNC,%#x,%p) = %d\n",
463                         (u_int)cmd, data, i);
464         if (i != 0) {
465                 errno = i;
466                 return -1;
467         }
468         return 0;
469 }
470
471
472 int ipooltestioctl(int dev, ioctlcmd_t cmd, ...)
473 {
474         caddr_t data;
475         va_list ap;
476         int i;
477
478         dev = dev;      /* gcc -Wextra */
479         va_start(ap, cmd);
480         data = va_arg(ap, caddr_t);
481         va_end(ap);
482
483         i = ipfioctl(softc, IPL_LOGLOOKUP, cmd, data, FWRITE|FREAD);
484         if ((opts & OPT_DEBUG) || (i != 0))
485                 fprintf(stderr, "ipfioctl(POOL,%#x,%p) = %d (%d)\n",
486                         (u_int)cmd, data, i, softc->ipf_interror);
487         if (i != 0) {
488                 errno = i;
489                 return -1;
490         }
491         return 0;
492 }
493
494
495 int kmemcpy(addr, offset, size)
496         char *addr;
497         long offset;
498         int size;
499 {
500         bcopy((char *)offset, addr, size);
501         return 0;
502 }
503
504
505 int kstrncpy(buf, pos, n)
506         char *buf;
507         long pos;
508         int n;
509 {
510         char *ptr;
511
512         ptr = (char *)pos;
513
514         while ((n > 0) && (*buf++ = *ptr++))
515                 ;
516         return 0;
517 }
518
519
520 /*
521  * Display the built up NAT table rules and mapping entries.
522  */
523 void dumpnat(arg)
524         void *arg;
525 {
526         ipf_nat_softc_t *softn = arg;
527         hostmap_t *hm;
528         ipnat_t *ipn;
529         nat_t *nat;
530
531         printf("List of active MAP/Redirect filters:\n");
532         for (ipn = softn->ipf_nat_list; ipn != NULL; ipn = ipn->in_next)
533                 printnat(ipn, opts & (OPT_DEBUG|OPT_VERBOSE));
534         printf("\nList of active sessions:\n");
535         for (nat = softn->ipf_nat_instances; nat; nat = nat->nat_next) {
536                 printactivenat(nat, opts, 0);
537                 if (nat->nat_aps)
538                         printf("\tproxy active\n");
539         }
540
541         printf("\nHostmap table:\n");
542         for (hm = softn->ipf_hm_maplist; hm != NULL; hm = hm->hm_next)
543                 printhostmap(hm, hm->hm_hv);
544 }
545
546
547 void dumpgroups(softc)
548         ipf_main_softc_t *softc;
549 {
550         frgroup_t *fg;
551         int i;
552
553         printf("List of groups configured (set 0)\n");
554         for (i = 0; i < IPL_LOGSIZE; i++)
555                 for (fg =  softc->ipf_groups[i][0]; fg != NULL;
556                      fg = fg->fg_next) {
557                         printf("Dev.%d. Group %s Ref %d Flags %#x\n",
558                                 i, fg->fg_name, fg->fg_ref, fg->fg_flags);
559                         dumprules(fg->fg_start);
560                 }
561
562         printf("List of groups configured (set 1)\n");
563         for (i = 0; i < IPL_LOGSIZE; i++)
564                 for (fg =  softc->ipf_groups[i][1]; fg != NULL;
565                      fg = fg->fg_next) {
566                         printf("Dev.%d. Group %s Ref %d Flags %#x\n",
567                                 i, fg->fg_name, fg->fg_ref, fg->fg_flags);
568                         dumprules(fg->fg_start);
569                 }
570
571         printf("Rules configured (set 0, in)\n");
572         dumprules(softc->ipf_rules[0][0]);
573         printf("Rules configured (set 0, out)\n");
574         dumprules(softc->ipf_rules[1][0]);
575         printf("Rules configured (set 1, in)\n");
576         dumprules(softc->ipf_rules[0][1]);
577         printf("Rules configured (set 1, out)\n");
578         dumprules(softc->ipf_rules[1][1]);
579
580         printf("Accounting rules configured (set 0, in)\n");
581         dumprules(softc->ipf_acct[0][0]);
582         printf("Accounting rules configured (set 0, out)\n");
583         dumprules(softc->ipf_acct[0][1]);
584         printf("Accounting rules configured (set 1, in)\n");
585         dumprules(softc->ipf_acct[1][0]);
586         printf("Accounting rules configured (set 1, out)\n");
587         dumprules(softc->ipf_acct[1][1]);
588 }
589
590 void dumprules(rulehead)
591         frentry_t *rulehead;
592 {
593         frentry_t *fr;
594
595         for (fr = rulehead; fr != NULL; fr = fr->fr_next) {
596 #ifdef  USE_QUAD_T
597                 printf("%"PRIu64" ",(unsigned long long)fr->fr_hits);
598 #else
599                 printf("%ld ", fr->fr_hits);
600 #endif
601                 printfr(fr, ipftestioctl);
602         }
603 }
604
605
606 void drain_log(filename)
607         char *filename;
608 {
609         char buffer[DEFAULT_IPFLOGSIZE];
610         struct iovec iov;
611         struct uio uio;
612         size_t resid;
613         int fd, i;
614
615         fd = open(filename, O_CREAT|O_TRUNC|O_WRONLY, 0644);
616         if (fd == -1) {
617                 perror("drain_log:open");
618                 return;
619         }
620
621         for (i = 0; i <= IPL_LOGMAX; i++)
622                 while (1) {
623                         bzero((char *)&iov, sizeof(iov));
624                         iov.iov_base = buffer;
625                         iov.iov_len = sizeof(buffer);
626
627                         bzero((char *)&uio, sizeof(uio));
628                         uio.uio_iov = &iov;
629                         uio.uio_iovcnt = 1;
630                         uio.uio_resid = iov.iov_len;
631                         resid = uio.uio_resid;
632
633                         if (ipf_log_read(softc, i, &uio) == 0) {
634                                 /*
635                                  * If nothing was read then break out.
636                                  */
637                                 if (uio.uio_resid == resid)
638                                         break;
639                                 write(fd, buffer, resid - uio.uio_resid);
640                         } else
641                                 break;
642         }
643
644         close(fd);
645 }
646
647
648 void fixv4sums(m, ip)
649         mb_t *m;
650         ip_t *ip;
651 {
652         u_char *csump, *hdr, p;
653         fr_info_t tmp;
654         int len;
655
656         p = 0;
657         len = 0;
658         bzero((char *)&tmp, sizeof(tmp));
659
660         csump = (u_char *)ip;
661         if (IP_V(ip) == 4) {
662                 ip->ip_sum = 0;
663                 ip->ip_sum = ipf_cksum((u_short *)ip, IP_HL(ip) << 2);
664                 tmp.fin_hlen = IP_HL(ip) << 2;
665                 csump += IP_HL(ip) << 2;
666                 p = ip->ip_p;
667                 len = ntohs(ip->ip_len);
668 #ifdef USE_INET6
669         } else if (IP_V(ip) == 6) {
670                 tmp.fin_hlen = sizeof(ip6_t);
671                 csump += sizeof(ip6_t);
672                 p = ((ip6_t *)ip)->ip6_nxt;
673                 len = ntohs(((ip6_t *)ip)->ip6_plen);
674                 len += sizeof(ip6_t);
675 #endif
676         }
677         tmp.fin_plen = len;
678         tmp.fin_dlen = len - tmp.fin_hlen;
679
680         switch (p)
681         {
682         case IPPROTO_TCP :
683                 hdr = csump;
684                 csump += offsetof(tcphdr_t, th_sum);
685                 break;
686         case IPPROTO_UDP :
687                 hdr = csump;
688                 csump += offsetof(udphdr_t, uh_sum);
689                 break;
690         case IPPROTO_ICMP :
691                 hdr = csump;
692                 csump += offsetof(icmphdr_t, icmp_cksum);
693                 break;
694         default :
695                 csump = NULL;
696                 hdr = NULL;
697                 break;
698         }
699         if (hdr != NULL) {
700                 tmp.fin_m = m;
701                 tmp.fin_mp = &m;
702                 tmp.fin_dp = hdr;
703                 tmp.fin_ip = ip;
704                 tmp.fin_plen = len;
705                 *csump = 0;
706                 *(u_short *)csump = fr_cksum(&tmp, ip, p, hdr);
707         }
708 }
709
710 void
711 ip_fillid(struct ip *ip)
712 {
713         static uint16_t ip_id;
714
715         ip->ip_id = ip_id++;
716 }