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