2 * Copyright (C) 1993-2001 by Darren Reed.
4 * See the IPFILTER.LICENCE file for details on licencing.
6 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
7 * Use is subject to license terms.
12 #include <sys/ioctl.h>
16 extern struct frentry
*ipfilter
[2][2];
17 extern struct ipread snoop
, etherf
, tcpd
, pcap
, iptext
, iphex
;
18 extern struct ifnet
*get_unit
__P((char *, int, ipf_stack_t
*));
19 extern void init_ifp
__P((void));
21 int opts
= OPT_DONOTHING
;
23 int pfil_delayed_copy
= 0;
24 int main
__P((int, char *[]));
25 int loadrules
__P((char *, int));
26 int kmemcpy
__P((char *, long, int));
27 int kstrncpy
__P((char *, long, int n
));
28 void dumpnat
__P((ipf_stack_t
*ifs
));
29 void dumpstate
__P((ipf_stack_t
*ifs
));
30 void dumplookups
__P((ipf_stack_t
*ifs
));
31 void dumpgroups
__P((ipf_stack_t
*ifs
));
32 void drain_log
__P((char *, ipf_stack_t
*ifs
));
33 void fixv4sums
__P((mb_t
*, ip_t
*));
34 ipf_stack_t
*get_ifs
__P((void));
35 ipf_stack_t
*create_ifs
__P((void));
38 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(SOLARIS) || \
39 (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000) || \
40 defined(__osf__) || defined(linux)
41 int ipftestioctl
__P((int, ioctlcmd_t
, ...));
42 int ipnattestioctl
__P((int, ioctlcmd_t
, ...));
43 int ipstatetestioctl
__P((int, ioctlcmd_t
, ...));
44 int ipauthtestioctl
__P((int, ioctlcmd_t
, ...));
45 int ipscantestioctl
__P((int, ioctlcmd_t
, ...));
46 int ipsynctestioctl
__P((int, ioctlcmd_t
, ...));
47 int ipooltestioctl
__P((int, ioctlcmd_t
, ...));
49 int ipftestioctl
__P((dev_t
, ioctlcmd_t
, void *));
50 int ipnattestioctl
__P((dev_t
, ioctlcmd_t
, void *));
51 int ipstatetestioctl
__P((dev_t
, ioctlcmd_t
, void *));
52 int ipauthtestioctl
__P((dev_t
, ioctlcmd_t
, void *));
53 int ipsynctestioctl
__P((dev_t
, ioctlcmd_t
, void *));
54 int ipscantestioctl
__P((dev_t
, ioctlcmd_t
, void *));
55 int ipooltestioctl
__P((dev_t
, ioctlcmd_t
, void *));
58 static ioctlfunc_t iocfunctions
[IPL_LOGSIZE
] = { ipftestioctl
,
72 char *datain
, *iface
, *ifname
, *logout
;
73 int fd
, i
, dir
, c
, loaded
, dump
, hlen
;
94 #if defined(IPFILTER_DEFAULT_BLOCK)
95 ifs
->ifs_fr_pass
= FR_BLOCK
|FR_NOMATCH
;
97 ifs
->ifs_fr_pass
= (IPF_DEFAULT_PASS
)|FR_NOMATCH
;
99 ipftuneable_alloc(ifs
);
101 MUTEX_INIT(&ifs
->ifs_ipf_rw
, "ipf rw mutex");
102 MUTEX_INIT(&ifs
->ifs_ipf_timeoutlock
, "ipf timeout lock");
103 RWLOCK_INIT(&ifs
->ifs_ipf_global
, "ipf filter load/unload mutex");
104 RWLOCK_INIT(&ifs
->ifs_ipf_mutex
, "ipf filter rwlock");
105 RWLOCK_INIT(&ifs
->ifs_ipf_ipidfrag
, "ipf IP NAT-Frag rwlock");
106 RWLOCK_INIT(&ifs
->ifs_ipf_frcache
, "ipf rule cache rwlock");
115 ifs
->ifs_fr_running
= 1;
117 while ((c
= getopt(argc
, argv
, "6bdDF:i:I:l:N:P:or:RT:vxX")) != -1)
124 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)
164 if (ipf_parsefile(-1, ipf_addrule
, iocfunctions
,
170 opts
|= OPT_NORESOLVE
;
176 if (ipnat_parsefile(-1, ipnat_addrule
, ipnattestioctl
,
183 if (ippool_parsefile(-1, optarg
, ipooltestioctl
) == -1)
188 ipf_dotuning(-1, optarg
, ipftestioctl
);
196 (void)fprintf(stderr
,"no rules loaded\n");
200 if (opts
& OPT_SAVEOUT
)
204 fd
= (*r
->r_open
)(datain
);
206 fd
= (*r
->r_open
)("-");
211 ip
= MTOD(m
, ip_t
*);
212 while ((i
= (*r
->r_readip
)(MTOD(m
, char *), sizeof(m
->mb_buf
),
213 &iface
, &dir
)) > 0) {
214 if (iface
== NULL
|| *iface
== '\0')
216 ifp
= get_unit(iface
, IP_V(ip
), ifs
);
218 fprintf(stderr
, "out of memory\n");
222 ip
->ip_off
= ntohs(ip
->ip_off
);
223 ip
->ip_len
= ntohs(ip
->ip_len
);
224 if (r
->r_flags
& R_DO_CKSUM
)
226 hlen
= IP_HL(ip
) << 2;
230 hlen
= sizeof(ip6_t
);
232 /* ipfr_slowtimer(); */
235 i
= fr_check(ip
, hlen
, ifp
, dir
, &m
, ifs
);
236 if ((opts
& OPT_NAT
) == 0)
240 (void)printf("preauth");
243 (void)printf("account");
246 (void)printf("auth");
249 (void)printf("block");
252 (void)printf("pass");
255 (void)printf("nomatch");
258 (void)printf("block return-rst");
261 (void)printf("block return-icmp");
264 (void)printf("block return-icmp-as-dest");
267 (void)printf("recognised return %#x\n", i
);
271 ip
->ip_off
= htons(ip
->ip_off
);
272 ip
->ip_len
= htons(ip
->ip_len
);
275 if (!(opts
& OPT_BRIEF
)) {
278 printf("--------------");
279 } else if ((opts
& (OPT_BRIEF
|OPT_NAT
)) == (OPT_NAT
|OPT_BRIEF
))
281 if (dir
&& (ifp
!= NULL
) && IP_V(ip
) && (m
!= NULL
))
282 #if defined(__sgi) && (IRIX < 60500)
283 (*ifp
->if_output
)(ifp
, (void *)m
, NULL
);
286 (*ifp
->if_output
)(ifp
, (void *)m
, NULL
, 0, 0);
288 (*ifp
->if_output
)(ifp
, (void *)m
, NULL
, 0);
291 if ((opts
& (OPT_BRIEF
|OPT_NAT
)) != (OPT_NAT
|OPT_BRIEF
))
294 if (iface
!= ifname
) {
302 if (logout
!= NULL
) {
303 drain_log(logout
, ifs
);
313 fr_deinitialise(ifs
);
319 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(SOLARIS) || \
320 (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000) || \
321 defined(__osf__) || defined(linux)
322 int ipftestioctl(int dev
, ioctlcmd_t cmd
, ...)
329 data
= va_arg(ap
, caddr_t
);
332 i
= iplioctl(IPL_LOGIPF
, cmd
, data
, FWRITE
|FREAD
);
333 if (opts
& OPT_DEBUG
)
334 fprintf(stderr
, "iplioctl(IPF,%#x,%p) = %d\n",
335 (u_int
)cmd
, data
, i
);
344 int ipnattestioctl(int dev
, ioctlcmd_t cmd
, ...)
351 data
= va_arg(ap
, caddr_t
);
354 i
= iplioctl(IPL_LOGNAT
, cmd
, data
, FWRITE
|FREAD
);
355 if (opts
& OPT_DEBUG
)
356 fprintf(stderr
, "iplioctl(NAT,%#x,%p) = %d\n",
357 (u_int
)cmd
, data
, i
);
366 int ipstatetestioctl(int dev
, ioctlcmd_t cmd
, ...)
373 data
= va_arg(ap
, caddr_t
);
376 i
= iplioctl(IPL_LOGSTATE
, cmd
, data
, FWRITE
|FREAD
);
377 if ((opts
& OPT_DEBUG
) || (i
!= 0))
378 fprintf(stderr
, "iplioctl(STATE,%#x,%p) = %d\n",
379 (u_int
)cmd
, data
, i
);
388 int ipauthtestioctl(int dev
, ioctlcmd_t cmd
, ...)
395 data
= va_arg(ap
, caddr_t
);
398 i
= iplioctl(IPL_LOGAUTH
, cmd
, data
, FWRITE
|FREAD
);
399 if ((opts
& OPT_DEBUG
) || (i
!= 0))
400 fprintf(stderr
, "iplioctl(AUTH,%#x,%p) = %d\n",
401 (u_int
)cmd
, data
, i
);
410 int ipscantestioctl(int dev
, ioctlcmd_t cmd
, ...)
417 data
= va_arg(ap
, caddr_t
);
420 i
= iplioctl(IPL_LOGSCAN
, cmd
, data
, FWRITE
|FREAD
);
421 if ((opts
& OPT_DEBUG
) || (i
!= 0))
422 fprintf(stderr
, "iplioctl(SCAN,%#x,%p) = %d\n",
423 (u_int
)cmd
, data
, i
);
432 int ipsynctestioctl(int dev
, ioctlcmd_t cmd
, ...)
439 data
= va_arg(ap
, caddr_t
);
442 i
= iplioctl(IPL_LOGSYNC
, cmd
, data
, FWRITE
|FREAD
);
443 if ((opts
& OPT_DEBUG
) || (i
!= 0))
444 fprintf(stderr
, "iplioctl(SYNC,%#x,%p) = %d\n",
445 (u_int
)cmd
, data
, i
);
454 int ipooltestioctl(int dev
, ioctlcmd_t cmd
, ...)
461 data
= va_arg(ap
, caddr_t
);
464 i
= iplioctl(IPL_LOGLOOKUP
, cmd
, data
, FWRITE
|FREAD
);
465 if ((opts
& OPT_DEBUG
) || (i
!= 0))
466 fprintf(stderr
, "iplioctl(POOL,%#x,%p) = %d\n",
467 (u_int
)cmd
, data
, i
);
475 int ipftestioctl(dev
, cmd
, data
)
482 i
= iplioctl(IPL_LOGIPF
, cmd
, data
, FWRITE
|FREAD
);
483 if ((opts
& OPT_DEBUG
) || (i
!= 0))
484 fprintf(stderr
, "iplioctl(IPF,%#x,%p) = %d\n", cmd
, data
, i
);
493 int ipnattestioctl(dev
, cmd
, data
)
500 i
= iplioctl(IPL_LOGNAT
, cmd
, data
, FWRITE
|FREAD
);
501 if ((opts
& OPT_DEBUG
) || (i
!= 0))
502 fprintf(stderr
, "iplioctl(NAT,%#x,%p) = %d\n", cmd
, data
, i
);
511 int ipstatetestioctl(dev
, cmd
, data
)
518 i
= iplioctl(IPL_LOGSTATE
, cmd
, data
, FWRITE
|FREAD
);
519 if ((opts
& OPT_DEBUG
) || (i
!= 0))
520 fprintf(stderr
, "iplioctl(STATE,%#x,%p) = %d\n", cmd
, data
, i
);
529 int ipauthtestioctl(dev
, cmd
, data
)
536 i
= iplioctl(IPL_LOGAUTH
, cmd
, data
, FWRITE
|FREAD
);
537 if ((opts
& OPT_DEBUG
) || (i
!= 0))
538 fprintf(stderr
, "iplioctl(AUTH,%#x,%p) = %d\n", cmd
, data
, i
);
547 int ipsynctestioctl(dev
, cmd
, data
)
554 i
= iplioctl(IPL_LOGSYNC
, cmd
, data
, FWRITE
|FREAD
);
555 if ((opts
& OPT_DEBUG
) || (i
!= 0))
556 fprintf(stderr
, "iplioctl(SYNC,%#x,%p) = %d\n", cmd
, data
, i
);
565 int ipscantestioctl(dev
, cmd
, data
)
572 i
= iplioctl(IPL_LOGSCAN
, cmd
, data
, FWRITE
|FREAD
);
573 if ((opts
& OPT_DEBUG
) || (i
!= 0))
574 fprintf(stderr
, "iplioctl(SCAN,%#x,%p) = %d\n", cmd
, data
, i
);
583 int ipooltestioctl(dev
, cmd
, data
)
590 i
= iplioctl(IPL_LOGLOOKUP
, cmd
, data
, FWRITE
|FREAD
);
591 if (opts
& OPT_DEBUG
)
592 fprintf(stderr
, "iplioctl(POOL,%#x,%p) = %d\n", cmd
, data
, i
);
602 int kmemcpy(addr
, offset
, size
)
607 bcopy((char *)offset
, addr
, size
);
612 int kstrncpy(buf
, pos
, n
)
621 while ((n
-- > 0) && (*buf
++ = *ptr
++))
628 * Display the built up NAT table rules and mapping entries.
636 printf("List of active MAP/Redirect filters:\n");
637 for (ipn
= ifs
->ifs_nat_list
; ipn
!= NULL
; ipn
= ipn
->in_next
)
638 printnat(ipn
, opts
& (OPT_DEBUG
|OPT_VERBOSE
));
639 printf("\nList of active sessions:\n");
640 for (nat
= ifs
->ifs_nat_instances
; nat
; nat
= nat
->nat_next
) {
641 printactivenat(nat
, opts
, 0);
643 printaps(nat
->nat_aps
, opts
);
649 * Display the built up state table rules and mapping entries.
656 printf("List of active state sessions:\n");
657 for (ips
= ifs
->ifs_ips_list
; ips
!= NULL
; )
658 ips
= printstate(ips
, opts
& (OPT_DEBUG
|OPT_VERBOSE
),
663 void dumplookups(ifs
)
670 printf("List of configured pools\n");
671 for (i
= 0; i
< IPL_LOGSIZE
; i
++)
672 for (ipl
= ifs
->ifs_ip_pool_list
[i
]; ipl
!= NULL
;
674 printpool(ipl
, bcopywrap
, NULL
, opts
);
676 printf("List of configured hash tables\n");
677 for (i
= 0; i
< IPL_LOGSIZE
; i
++)
678 for (iph
= ifs
->ifs_ipf_htables
[i
]; iph
!= NULL
;
680 printhash(iph
, bcopywrap
, NULL
, opts
);
691 printf("List of groups configured (set 0)\n");
692 for (i
= 0; i
< IPL_LOGSIZE
; i
++)
693 for (fg
= ifs
->ifs_ipfgroups
[i
][0]; fg
!= NULL
;
695 printf("Dev.%d. Group %s Ref %d Flags %#x\n",
696 i
, fg
->fg_name
, fg
->fg_ref
, fg
->fg_flags
);
697 for (fr
= fg
->fg_start
; fr
!= NULL
; fr
= fr
->fr_next
) {
699 printf("%qu ",(unsigned long long)fr
->fr_hits
);
701 printf("%ld ", fr
->fr_hits
);
703 printfr(fr
, ipftestioctl
);
707 printf("List of groups configured (set 1)\n");
708 for (i
= 0; i
< IPL_LOGSIZE
; i
++)
709 for (fg
= ifs
->ifs_ipfgroups
[i
][1]; fg
!= NULL
;
711 printf("Dev.%d. Group %s Ref %d Flags %#x\n",
712 i
, fg
->fg_name
, fg
->fg_ref
, fg
->fg_flags
);
713 for (fr
= fg
->fg_start
; fr
!= NULL
; fr
= fr
->fr_next
) {
715 printf("%qu ",(unsigned long long)fr
->fr_hits
);
717 printf("%ld ", fr
->fr_hits
);
719 printfr(fr
, ipftestioctl
);
725 void drain_log(filename
, ifs
)
729 char buffer
[DEFAULT_IPFLOGSIZE
];
735 fd
= open(filename
, O_CREAT
|O_TRUNC
|O_WRONLY
, 0644);
737 perror("drain_log:open");
741 for (i
= 0; i
<= IPL_LOGMAX
; i
++)
743 bzero((char *)&iov
, sizeof(iov
));
744 iov
.iov_base
= buffer
;
745 iov
.iov_len
= sizeof(buffer
);
747 bzero((char *)&uio
, sizeof(uio
));
750 uio
.uio_resid
= iov
.iov_len
;
751 resid
= uio
.uio_resid
;
753 if (ipflog_read(i
, &uio
, ifs
) == 0) {
755 * If nothing was read then break out.
757 if (uio
.uio_resid
== resid
)
759 write(fd
, buffer
, resid
- uio
.uio_resid
);
768 void fixv4sums(m
, ip
)
775 ip
->ip_sum
= ipf_cksum((u_short
*)ip
, IP_HL(ip
) << 2);
777 csump
= (u_char
*)ip
;
778 csump
+= IP_HL(ip
) << 2;
784 csump
+= offsetof(tcphdr_t
, th_sum
);
788 csump
+= offsetof(udphdr_t
, uh_sum
);
797 *(u_short
*)csump
= fr_cksum(m
, ip
, ip
->ip_p
, hdr
);
804 * Allocate and keep pointer for get_ifs()
811 KMALLOCS(ifs
, ipf_stack_t
*, sizeof (*ifs
));
812 bzero(ifs
, sizeof (*ifs
));