2 * Copyright (C) 1993-2002 by Darren Reed.
4 * See the IPFILTER.LICENCE file for details on licencing.
7 # ifndef __FreeBSD_cc_version
8 # include <osreldate.h>
10 # if __FreeBSD_cc_version < 430000
11 # include <osreldate.h>
15 #if defined(__sgi) && (IRIX > 602)
17 # include <sys/ptimers.h>
22 #include <sys/types.h>
23 #if !defined(__SVR4) && !defined(__svr4__) && !defined(__sgi)
27 #include <sys/byteorder.h>
31 #include <sys/param.h>
36 #include <sys/socket.h>
37 #include <sys/ioctl.h>
38 #include <netinet/in.h>
39 #include <netinet/in_systm.h>
41 #include <netinet/ip_var.h>
43 #include <netinet/ip.h>
44 #include <netinet/udp.h>
45 #include <netinet/tcp.h>
46 #include <netinet/ip_icmp.h>
48 #if __FreeBSD_version >= 300000
49 # include <net/if_var.h>
52 #include <arpa/nameser.h>
53 #include <arpa/inet.h>
56 #include "ip_compat.h"
57 #include <netinet/tcpip.h>
66 static const char sccsid
[] = "@(#)ipt.c 1.19 6/3/96 (C) 1993-2000 Darren Reed";
67 static const char rcsid
[] = "@(#)$Id: ipt.c,v 2.6.2.26 2003/11/09 17:22:21 darrenr Exp $";
71 extern struct frentry
*ipfilter
[2][2];
72 extern struct ipread snoop
, etherf
, tcpd
, pcap
, iptext
, iphex
;
73 extern struct ifnet
*get_unit
__P((char *, int));
74 extern void init_ifp
__P((void));
75 extern ipnat_t
*natparse
__P((char *, int, int *));
76 extern int fr_running
;
81 int main
__P((int, char *[]));
82 int loadrules
__P((char *));
83 int kmemcpy
__P((char *, long, int));
84 void dumpnat
__P((void));
85 void dumpstate
__P((void));
86 char *getifname
__P((void *));
87 void drain_log
__P((char *));
93 char *datain
, *iface
, *ifname
, *packet
, *logout
;
94 int fd
, i
, dir
, c
, loaded
, dump
, hlen
;
117 while ((c
= getopt(argc
, argv
, "6bdDEHi:I:l:NoPr:Rs:STvxX")) != -1)
125 fprintf(stderr
, "IPv6 not supported\n");
150 if (loadrules(optarg
) == -1)
155 src
.s_addr
= inet_addr(optarg
);
190 (void)fprintf(stderr
,"no rules loaded\n");
194 if (opts
& OPT_SAVEOUT
)
198 fd
= (*r
->r_open
)(datain
);
200 fd
= (*r
->r_open
)("-");
206 while ((i
= (*r
->r_readip
)((char *)buf
, sizeof(buf
),
207 &iface
, &dir
)) > 0) {
208 if (iface
== NULL
|| *iface
== '\0')
210 ifp
= get_unit(iface
, ip
->ip_v
);
213 ip
->ip_off
= ntohs(ip
->ip_off
);
214 ip
->ip_len
= ntohs(ip
->ip_len
);
215 hlen
= ip
->ip_hl
<< 2;
216 if (src
.s_addr
!= 0) {
217 if (src
.s_addr
== ip
->ip_src
.s_addr
)
219 else if (src
.s_addr
== ip
->ip_dst
.s_addr
)
225 hlen
= sizeof(ip6_t
);
227 if (opts
& OPT_VERBOSE
) {
228 printf("%s on [%s]: ", dir
? "out" : "in",
229 (iface
&& *iface
) ? iface
: "??");
231 packet
= (char *)buf
;
232 /* ipfr_slowtimer(); */
233 i
= fr_check(ip
, hlen
, ifp
, dir
, (mb_t
**)&packet
);
234 if ((opts
& OPT_NAT
) == 0)
238 (void)printf("block return-icmp-as-dest");
241 (void)printf("block return-icmp");
244 (void)printf("block return-rst");
247 (void)printf("auth");
250 (void)printf("block");
253 (void)printf("pass");
256 (void)printf("nomatch");
260 ip
->ip_off
= htons(ip
->ip_off
);
261 ip
->ip_len
= htons(ip
->ip_len
);
264 if (!(opts
& OPT_BRIEF
)) {
266 printpacket((ip_t
*)buf
);
267 printf("--------------");
268 } else if ((opts
& (OPT_BRIEF
|OPT_NAT
)) == (OPT_NAT
|OPT_BRIEF
))
269 printpacket((ip_t
*)buf
);
271 if (dir
&& (ifp
!= NULL
) && ip
->ip_v
&& (packet
!= NULL
))
272 # if defined(__sgi) && (IRIX < 605)
273 (*ifp
->if_output
)(ifp
, (void *)packet
, NULL
);
275 (*ifp
->if_output
)(ifp
, (void *)packet
, NULL
, 0);
278 if ((opts
& (OPT_BRIEF
|OPT_NAT
)) != (OPT_NAT
|OPT_BRIEF
))
281 if (iface
!= ifname
) {
288 if (logout
!= NULL
) {
302 * Load in either NAT or ipf rules from a file, which is treated as stdin
303 * if the name is "-". NOTE, stdin can only be used once as the file is
315 if (!strcmp(file
, "-"))
317 else if (!(fp
= fopen(file
, "r"))) {
318 (void)fprintf(stderr
, "couldn't open %s\n", file
);
322 if (!(opts
& OPT_BRIEF
))
323 (void)printf("opening rule file \"%s\"\n", file
);
327 while (fgets(line
, sizeof(line
) - 1, fp
)) {
331 * treat both CR and LF as EOL
333 if ((s
= index(line
, '\n')))
335 if ((s
= index(line
, '\r')))
339 * # is comment marker, everything after is a ignored
341 if ((s
= index(line
, '#')))
347 /* fake an `ioctl' call :) */
349 if ((opts
& OPT_NAT
) != 0) {
351 fr
= natparse(line
, linenum
, &parsestatus
);
352 if (parsestatus
!= 0) {
355 "%d: syntax error in \"%s\"\n",
358 fprintf(stderr
, "%s: %s error (%d), quitting\n",
360 ((parsestatus
< 0)? "parse": "internal"),
368 i
= IPL_EXTERN(ioctl
)(IPL_LOGNAT
, SIOCADNAT
,
371 if (opts
& OPT_DEBUG
)
373 "iplioctl(ADNAT,%p,1) = %d\n",
376 i
= IPL_EXTERN(ioctl
)(IPL_LOGNAT
, SIOCRMNAT
,
379 if (opts
& OPT_DEBUG
)
381 "iplioctl(RMNAT,%p,1) = %d\n",
385 fr
= parse(line
, linenum
, &parsestatus
);
387 if (parsestatus
!= 0) {
388 fprintf(stderr
, "%s: %s error (%d), quitting\n",
390 ((parsestatus
< 0)? "parse": "internal"),
400 i
= IPL_EXTERN(ioctl
)(0, SIOCADAFR
,
403 if (opts
& OPT_DEBUG
)
405 "iplioctl(ADAFR,%p,1) = %d\n",
408 i
= IPL_EXTERN(ioctl
)(0, SIOCRMAFR
,
411 if (opts
& OPT_DEBUG
)
413 "iplioctl(RMAFR,%p,1) = %d\n",
424 int kmemcpy(addr
, offset
, size
)
429 bcopy((char *)offset
, addr
, size
);
435 * Display the built up NAT table rules and mapping entries.
442 printf("List of active MAP/Redirect filters:\n");
443 for (ipn
= nat_list
; ipn
!= NULL
; ipn
= ipn
->in_next
)
444 printnat(ipn
, opts
& (OPT_DEBUG
|OPT_VERBOSE
));
445 printf("\nList of active sessions:\n");
446 for (nat
= nat_instances
; nat
; nat
= nat
->nat_next
)
447 printactivenat(nat
, opts
);
452 * Display the built up state table rules and mapping entries.
458 printf("List of active state sessions:\n");
459 for (ips
= ips_list
; ips
!= NULL
; )
460 ips
= printstate(ips
, opts
& (OPT_DEBUG
|OPT_VERBOSE
));
465 * Given a pointer to an interface in the kernel, return a pointer to a
466 * string which is the interface name.
471 #if defined(NetBSD) && (NetBSD >= 199905) && (NetBSD < 1991011) || \
479 if (ptr
== (void *)-1)
484 if (kmemcpy((char *)&netif
, (u_long
)ptr
, sizeof(netif
)) == -1)
486 #if defined(NetBSD) && (NetBSD >= 199905) && (NetBSD < 1991011) || \
487 defined(__OpenBSD__) || defined(__DragonFly__)
488 return strdup(netif
.if_xname
);
490 if (kmemcpy(buf
, (u_long
)netif
.if_name
, sizeof(buf
)) == -1)
492 if (netif
.if_unit
< 10)
494 else if (netif
.if_unit
< 1000)
496 else if (netif
.if_unit
< 10000)
500 buf
[sizeof(buf
) - len
] = '\0';
501 for (s
= buf
; *s
&& !isdigit(*s
); s
++)
505 sprintf(buf
+ strlen(buf
), "%d", netif
.if_unit
% 10000);
511 void drain_log(filename
)
514 char buffer
[IPLLOGSIZE
];
520 fd
= open(filename
, O_CREAT
|O_TRUNC
|O_WRONLY
, 0644);
522 perror("drain_log:open");
527 bzero((char *)&iov
, sizeof(iov
));
528 iov
.iov_base
= buffer
;
529 iov
.iov_len
= sizeof(buffer
);
531 bzero((char *)&uio
, sizeof(uio
));
534 uio
.uio_resid
= iov
.iov_len
;
535 resid
= uio
.uio_resid
;
537 if (ipflog_read(0, &uio
) == 0) {
539 * If nothing was read then break out.
541 if (uio
.uio_resid
== resid
)
543 write(fd
, buffer
, resid
- uio
.uio_resid
);