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