4 * Copyright (C) 2002-2006 by Darren Reed.
6 * See the IPFILTER.LICENCE file for details on licencing.
10 #include <sys/ioctl.h>
14 static const char sccsid
[] = "@(#)ipt.c 1.19 6/3/96 (C) 1993-2000 Darren Reed";
15 static const char rcsid
[] = "@(#)Id: ipftest.c,v 1.44.2.14 2008/11/06 21:18:20 darrenr Exp";
19 extern struct frentry
*ipfilter
[2][2];
20 extern struct ipread snoop
, etherf
, tcpd
, pcap
, iptext
, iphex
;
21 extern struct ifnet
*get_unit
__P((char *, int));
22 extern void init_ifp
__P((void));
23 extern ipnat_t
*natparse
__P((char *, int));
24 extern int fr_running
;
25 extern hostmap_t
**ipf_hm_maptable
;
26 extern hostmap_t
*ipf_hm_maplist
;
28 ipfmutex_t ipl_mutex
, ipf_authmx
, ipf_rw
, ipf_stinsert
;
29 ipfmutex_t ipf_nat_new
, ipf_natio
, ipf_timeoutlock
;
30 ipfrwlock_t ipf_mutex
, ipf_global
, ipf_ipidfrag
, ip_poolrw
, ipf_frcache
;
31 ipfrwlock_t ipf_frag
, ipf_state
, ipf_nat
, ipf_natfrag
, ipf_auth
, ipf_tokens
;
32 int opts
= OPT_DONOTHING
;
35 int pfil_delayed_copy
= 0;
36 int main
__P((int, char *[]));
37 int loadrules
__P((char *, int));
38 int kmemcpy
__P((char *, long, int));
39 int kstrncpy
__P((char *, long, int n
));
40 void dumpnat
__P((void));
41 void dumpstate
__P((void));
42 void dumplookups
__P((void));
43 void dumpgroups
__P((void));
44 void drain_log
__P((char *));
45 void fixv4sums
__P((mb_t
*, ip_t
*));
47 #if defined(__NetBSD__) || defined(__OpenBSD__) || SOLARIS || \
48 (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000) || \
49 defined(__osf__) || defined(linux)
50 int ipftestioctl
__P((int, ioctlcmd_t
, ...));
51 int ipnattestioctl
__P((int, ioctlcmd_t
, ...));
52 int ipstatetestioctl
__P((int, ioctlcmd_t
, ...));
53 int ipauthtestioctl
__P((int, ioctlcmd_t
, ...));
54 int ipscantestioctl
__P((int, ioctlcmd_t
, ...));
55 int ipsynctestioctl
__P((int, ioctlcmd_t
, ...));
56 int ipooltestioctl
__P((int, ioctlcmd_t
, ...));
58 int ipftestioctl
__P((dev_t
, ioctlcmd_t
, void *));
59 int ipnattestioctl
__P((dev_t
, ioctlcmd_t
, void *));
60 int ipstatetestioctl
__P((dev_t
, ioctlcmd_t
, void *));
61 int ipauthtestioctl
__P((dev_t
, ioctlcmd_t
, void *));
62 int ipsynctestioctl
__P((dev_t
, ioctlcmd_t
, void *));
63 int ipscantestioctl
__P((dev_t
, ioctlcmd_t
, void *));
64 int ipooltestioctl
__P((dev_t
, ioctlcmd_t
, void *));
67 static ioctlfunc_t iocfunctions
[IPL_LOGSIZE
] = { ipftestioctl
,
81 int fd
, i
, dir
, c
, loaded
, dump
, hlen
, eol
;
82 char *datain
, *iface
, *ifname
, *logout
;
101 MUTEX_INIT(&ipf_rw
, "ipf rw mutex");
102 MUTEX_INIT(&ipf_timeoutlock
, "ipf timeout lock");
103 RWLOCK_INIT(&ipf_global
, "ipf filter load/unload mutex");
104 RWLOCK_INIT(&ipf_mutex
, "ipf filter rwlock");
105 RWLOCK_INIT(&ipf_ipidfrag
, "ipf IP NAT-Frag rwlock");
106 RWLOCK_INIT(&ipf_frcache
, "ipf filter cache");
107 RWLOCK_INIT(&ipf_tokens
, "ipf token rwlock");
110 if (fr_initialise() == -1)
114 while ((c
= getopt(argc
, argv
, "6bCdDF:i:I:l:N:P:or:RS:T:vxX")) != -1)
121 fprintf(stderr
, "IPv6 not supported\n");
138 if (strcasecmp(optarg
, "pcap") == 0)
140 else if (strcasecmp(optarg
, "etherfind") == 0)
142 else if (strcasecmp(optarg
, "snoop") == 0)
144 else if (strcasecmp(optarg
, "tcpdump") == 0)
146 else if (strcasecmp(optarg
, "hex") == 0)
148 else if (strcasecmp(optarg
, "text") == 0)
161 if (ipnat_parsefile(-1, ipnat_addrule
, ipnattestioctl
,
171 if (ippool_parsefile(-1, optarg
, ipooltestioctl
) == -1)
176 if (ipf_parsefile(-1, ipf_addrule
, iocfunctions
,
182 sip
.s_addr
= inet_addr(optarg
);
185 opts
|= OPT_NORESOLVE
;
188 ipf_dotuning(-1, optarg
, ipftestioctl
);
199 (void)fprintf(stderr
,"no rules loaded\n");
203 if (opts
& OPT_SAVEOUT
)
207 fd
= (*r
->r_open
)(datain
);
209 fd
= (*r
->r_open
)("-");
214 ip
= MTOD(m
, ip_t
*);
215 while ((i
= (*r
->r_readip
)(MTOD(m
, char *), sizeof(m
->mb_buf
),
216 &iface
, &dir
)) > 0) {
217 if ((iface
== NULL
) || (*iface
== '\0'))
219 ifp
= get_unit(iface
, IP_V(ip
));
221 ip
->ip_off
= ntohs(ip
->ip_off
);
222 ip
->ip_len
= ntohs(ip
->ip_len
);
223 if ((r
->r_flags
& R_DO_CKSUM
) || docksum
)
225 hlen
= IP_HL(ip
) << 2;
227 dir
= !(sip
.s_addr
== ip
->ip_src
.s_addr
);
231 hlen
= sizeof(ip6_t
);
233 /* ipfr_slowtimer(); */
236 i
= fr_check(ip
, hlen
, ifp
, dir
, &m
);
237 if ((opts
& OPT_NAT
) == 0) {
241 (void)printf("preauth");
244 (void)printf("account");
247 (void)printf("auth");
250 (void)printf("block");
253 (void)printf("pass");
257 (void)printf("bad-packet");
259 (void)printf("nomatch");
262 (void)printf("block return-rst");
265 (void)printf("block return-icmp");
268 (void)printf("block return-icmp-as-dest");
271 (void)printf("recognised return %#x\n", i
);
276 (void)printf("block ");
281 ip
->ip_off
= htons(ip
->ip_off
);
282 ip
->ip_len
= htons(ip
->ip_len
);
286 if (!(opts
& OPT_BRIEF
)) {
289 printf("--------------");
292 if (opts
& OPT_NAT
) {
298 if (dir
&& (ifp
!= NULL
) && IP_V(ip
) && (m
!= NULL
))
299 #if defined(__sgi) && (IRIX < 60500)
300 (*ifp
->if_output
)(ifp
, (void *)m
, NULL
);
303 (*ifp
->if_output
)(ifp
, (void *)m
, NULL
, 0, 0);
305 (*ifp
->if_output
)(ifp
, (void *)m
, NULL
, 0);
310 * Because we have no timers to clear out a state entry, we
311 * do a flush call after every packet. Thus once an entry
312 * is recorded as starting to close (TCP), it will be flushed.
313 * This allows verification that flushing does work and that a
314 * packet arriving late will not match, along with the state
315 * table being empty when state is dumped at the end.
317 fr_state_flush(1, 0);
322 if (iface
!= ifname
) {
330 fprintf(stderr
, "readip failed: %d\n", i
);
333 if (logout
!= NULL
) {
350 #if defined(__NetBSD__) || defined(__OpenBSD__) || SOLARIS || \
351 (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000) || \
352 defined(__osf__) || defined(linux)
353 int ipftestioctl(int dev
, ioctlcmd_t cmd
, ...)
360 data
= va_arg(ap
, caddr_t
);
363 i
= iplioctl(IPL_LOGIPF
, cmd
, data
, FWRITE
|FREAD
);
364 if (opts
& OPT_DEBUG
)
365 fprintf(stderr
, "iplioctl(IPF,%#x,%p) = %d\n",
366 (u_int
)cmd
, data
, i
);
375 int ipnattestioctl(int dev
, ioctlcmd_t cmd
, ...)
382 data
= va_arg(ap
, caddr_t
);
385 i
= iplioctl(IPL_LOGNAT
, cmd
, data
, FWRITE
|FREAD
);
386 if (opts
& OPT_DEBUG
)
387 fprintf(stderr
, "iplioctl(NAT,%#x,%p) = %d\n",
388 (u_int
)cmd
, data
, i
);
397 int ipstatetestioctl(int dev
, ioctlcmd_t cmd
, ...)
404 data
= va_arg(ap
, caddr_t
);
407 i
= iplioctl(IPL_LOGSTATE
, cmd
, data
, FWRITE
|FREAD
);
408 if ((opts
& OPT_DEBUG
) || (i
!= 0))
409 fprintf(stderr
, "iplioctl(STATE,%#x,%p) = %d\n",
410 (u_int
)cmd
, data
, i
);
419 int ipauthtestioctl(int dev
, ioctlcmd_t cmd
, ...)
426 data
= va_arg(ap
, caddr_t
);
429 i
= iplioctl(IPL_LOGAUTH
, cmd
, data
, FWRITE
|FREAD
);
430 if ((opts
& OPT_DEBUG
) || (i
!= 0))
431 fprintf(stderr
, "iplioctl(AUTH,%#x,%p) = %d\n",
432 (u_int
)cmd
, data
, i
);
441 int ipscantestioctl(int dev
, ioctlcmd_t cmd
, ...)
448 data
= va_arg(ap
, caddr_t
);
451 i
= iplioctl(IPL_LOGSCAN
, cmd
, data
, FWRITE
|FREAD
);
452 if ((opts
& OPT_DEBUG
) || (i
!= 0))
453 fprintf(stderr
, "iplioctl(SCAN,%#x,%p) = %d\n",
454 (u_int
)cmd
, data
, i
);
463 int ipsynctestioctl(int dev
, ioctlcmd_t cmd
, ...)
470 data
= va_arg(ap
, caddr_t
);
473 i
= iplioctl(IPL_LOGSYNC
, cmd
, data
, FWRITE
|FREAD
);
474 if ((opts
& OPT_DEBUG
) || (i
!= 0))
475 fprintf(stderr
, "iplioctl(SYNC,%#x,%p) = %d\n",
476 (u_int
)cmd
, data
, i
);
485 int ipooltestioctl(int dev
, ioctlcmd_t cmd
, ...)
492 data
= va_arg(ap
, caddr_t
);
495 i
= iplioctl(IPL_LOGLOOKUP
, cmd
, data
, FWRITE
|FREAD
);
496 if ((opts
& OPT_DEBUG
) || (i
!= 0))
497 fprintf(stderr
, "iplioctl(POOL,%#x,%p) = %d\n",
498 (u_int
)cmd
, data
, i
);
506 int ipftestioctl(dev
, cmd
, data
)
513 i
= iplioctl(IPL_LOGIPF
, cmd
, data
, FWRITE
|FREAD
);
514 if ((opts
& OPT_DEBUG
) || (i
!= 0))
515 fprintf(stderr
, "iplioctl(IPF,%#x,%p) = %d\n", cmd
, data
, i
);
524 int ipnattestioctl(dev
, cmd
, data
)
531 i
= iplioctl(IPL_LOGNAT
, cmd
, data
, FWRITE
|FREAD
);
532 if ((opts
& OPT_DEBUG
) || (i
!= 0))
533 fprintf(stderr
, "iplioctl(NAT,%#x,%p) = %d\n", cmd
, data
, i
);
542 int ipstatetestioctl(dev
, cmd
, data
)
549 i
= iplioctl(IPL_LOGSTATE
, cmd
, data
, FWRITE
|FREAD
);
550 if ((opts
& OPT_DEBUG
) || (i
!= 0))
551 fprintf(stderr
, "iplioctl(STATE,%#x,%p) = %d\n", cmd
, data
, i
);
560 int ipauthtestioctl(dev
, cmd
, data
)
567 i
= iplioctl(IPL_LOGAUTH
, cmd
, data
, FWRITE
|FREAD
);
568 if ((opts
& OPT_DEBUG
) || (i
!= 0))
569 fprintf(stderr
, "iplioctl(AUTH,%#x,%p) = %d\n", cmd
, data
, i
);
578 int ipsynctestioctl(dev
, cmd
, data
)
585 i
= iplioctl(IPL_LOGSYNC
, cmd
, data
, FWRITE
|FREAD
);
586 if ((opts
& OPT_DEBUG
) || (i
!= 0))
587 fprintf(stderr
, "iplioctl(SYNC,%#x,%p) = %d\n", cmd
, data
, i
);
596 int ipscantestioctl(dev
, cmd
, data
)
603 i
= iplioctl(IPL_LOGSCAN
, cmd
, data
, FWRITE
|FREAD
);
604 if ((opts
& OPT_DEBUG
) || (i
!= 0))
605 fprintf(stderr
, "iplioctl(SCAN,%#x,%p) = %d\n", cmd
, data
, i
);
614 int ipooltestioctl(dev
, cmd
, data
)
621 i
= iplioctl(IPL_LOGLOOKUP
, cmd
, data
, FWRITE
|FREAD
);
622 if (opts
& OPT_DEBUG
)
623 fprintf(stderr
, "iplioctl(POOL,%#x,%p) = %d\n", cmd
, data
, i
);
633 int kmemcpy(addr
, offset
, size
)
638 bcopy((char *)offset
, addr
, size
);
643 int kstrncpy(buf
, pos
, n
)
652 while ((n
> 0) && (*buf
++ = *ptr
++))
659 * Display the built up NAT table rules and mapping entries.
667 printf("List of active MAP/Redirect filters:\n");
668 for (ipn
= nat_list
; ipn
!= NULL
; ipn
= ipn
->in_next
)
669 printnat(ipn
, opts
& (OPT_DEBUG
|OPT_VERBOSE
));
670 printf("\nList of active sessions:\n");
671 for (nat
= nat_instances
; nat
; nat
= nat
->nat_next
) {
672 printactivenat(nat
, opts
, 0, 0);
674 printaps(nat
->nat_aps
, opts
);
677 printf("\nHostmap table:\n");
678 for (hm
= ipf_hm_maplist
; hm
!= NULL
; hm
= hm
->hm_next
)
684 * Display the built up state table rules and mapping entries.
690 printf("List of active state sessions:\n");
691 for (ips
= ips_list
; ips
!= NULL
; )
692 ips
= printstate(ips
, opts
& (OPT_DEBUG
|OPT_VERBOSE
),
703 printf("List of configured pools\n");
704 for (i
= 0; i
< IPL_LOGSIZE
; i
++)
705 for (ipl
= ip_pool_list
[i
]; ipl
!= NULL
; ipl
= ipl
->ipo_next
)
706 printpool(ipl
, bcopywrap
, NULL
, opts
);
708 printf("List of configured hash tables\n");
709 for (i
= 0; i
< IPL_LOGSIZE
; i
++)
710 for (iph
= ipf_htables
[i
]; iph
!= NULL
; iph
= iph
->iph_next
)
711 printhash(iph
, bcopywrap
, NULL
, opts
);
721 printf("List of groups configured (set 0)\n");
722 for (i
= 0; i
< IPL_LOGSIZE
; i
++)
723 for (fg
= ipfgroups
[i
][0]; fg
!= NULL
; fg
= fg
->fg_next
) {
724 printf("Dev.%d. Group %s Ref %d Flags %#x\n",
725 i
, fg
->fg_name
, fg
->fg_ref
, fg
->fg_flags
);
726 for (fr
= fg
->fg_start
; fr
!= NULL
; fr
= fr
->fr_next
) {
728 printf("%qu ",(unsigned long long)fr
->fr_hits
);
730 printf("%ld ", fr
->fr_hits
);
732 printfr(fr
, ipftestioctl
);
736 printf("List of groups configured (set 1)\n");
737 for (i
= 0; i
< IPL_LOGSIZE
; i
++)
738 for (fg
= ipfgroups
[i
][1]; fg
!= NULL
; fg
= fg
->fg_next
) {
739 printf("Dev.%d. Group %s Ref %d Flags %#x\n",
740 i
, fg
->fg_name
, fg
->fg_ref
, fg
->fg_flags
);
741 for (fr
= fg
->fg_start
; fr
!= NULL
; fr
= fr
->fr_next
) {
743 printf("%qu ",(unsigned long long)fr
->fr_hits
);
745 printf("%ld ", fr
->fr_hits
);
747 printfr(fr
, ipftestioctl
);
753 void drain_log(filename
)
756 char buffer
[DEFAULT_IPFLOGSIZE
];
762 fd
= open(filename
, O_CREAT
|O_TRUNC
|O_WRONLY
, 0644);
764 perror("drain_log:open");
768 for (i
= 0; i
<= IPL_LOGMAX
; i
++)
770 bzero((char *)&iov
, sizeof(iov
));
771 iov
.iov_base
= buffer
;
772 iov
.iov_len
= sizeof(buffer
);
774 bzero((char *)&uio
, sizeof(uio
));
777 uio
.uio_resid
= iov
.iov_len
;
778 resid
= uio
.uio_resid
;
780 if (ipflog_read(i
, &uio
) == 0) {
782 * If nothing was read then break out.
784 if (uio
.uio_resid
== resid
)
786 write(fd
, buffer
, resid
- uio
.uio_resid
);
795 void fixv4sums(m
, ip
)
802 ip
->ip_sum
= ipf_cksum((u_short
*)ip
, IP_HL(ip
) << 2);
804 csump
= (u_char
*)ip
;
805 csump
+= IP_HL(ip
) << 2;
811 csump
+= offsetof(tcphdr_t
, th_sum
);
815 csump
+= offsetof(udphdr_t
, uh_sum
);
819 csump
+= offsetof(icmphdr_t
, icmp_cksum
);
828 *(u_short
*)csump
= fr_cksum(m
, ip
, ip
->ip_p
, hdr
, ip
->ip_len
);