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);