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
main(argc,argv)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
ipftestioctl(int dev,ioctlcmd_t cmd,...)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
ipnattestioctl(int dev,ioctlcmd_t cmd,...)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
ipstatetestioctl(int dev,ioctlcmd_t cmd,...)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
ipauthtestioctl(int dev,ioctlcmd_t cmd,...)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
ipscantestioctl(int dev,ioctlcmd_t cmd,...)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
ipsynctestioctl(int dev,ioctlcmd_t cmd,...)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
ipooltestioctl(int dev,ioctlcmd_t cmd,...)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
kmemcpy(addr,offset,size)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
kstrncpy(buf,pos,n)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 */
dumpnat(arg)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
dumpgroups(softc)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
dumprules(rulehead)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
drain_log(filename)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
fixv4sums(m,ip)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
ip_fillid(struct ip * ip)711 ip_fillid(struct ip *ip)
712 {
713 static uint16_t ip_id;
714
715 ip->ip_id = ip_id++;
716 }
717