4 * Copyright (C) 1993-2001 by Darren Reed.
6 * See the IPFILTER.LICENCE file for details on licencing.
9 static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed";
10 static const char rcsid[] = "@(#)$Id: ip_fil.c,v 2.133.2.18 2007/09/09 11:32:05 darrenr Exp $";
14 #define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
17 #include <sys/param.h>
18 #if defined(__FreeBSD__) && !defined(__FreeBSD_version)
19 # if defined(IPFILTER_LKM)
20 # ifndef __FreeBSD_cc_version
21 # include <osreldate.h>
23 # if __FreeBSD_cc_version < 430000
24 # include <osreldate.h>
29 #include <sys/errno.h>
30 #if defined(__hpux) && (HPUXREV >= 1111) && !defined(_KERNEL)
31 # include <sys/kern_svcs.h>
33 #include <sys/types.h>
43 #include <sys/ioctl.h>
45 # include <sys/ptimers.h>
49 # if (NetBSD > 199609) || (OpenBSD > 199603) || (__FreeBSD_version >= 300000)
50 # include <sys/dirent.h>
55 # include <sys/filio.h>
58 # include <sys/protosw.h>
60 #include <sys/socket.h>
69 # define _NET_ROUTE_INCLUDED
75 #if __FreeBSD_version >= 300000
76 # include <net/if_var.h>
79 #include <sys/debug.h>
80 # ifdef IFF_DRVRLOCK /* IRIX6 */
81 #include <sys/hashing.h>
84 #if defined(__FreeBSD__) || defined(SOLARIS2)
85 # include "radix_ipf.h"
88 # include <net/route.h>
90 #include <netinet/in.h>
91 #if !(defined(__sgi) && !defined(IFF_DRVRLOCK)) /* IRIX < 6 */ && \
92 !defined(__hpux) && !defined(linux)
93 # include <netinet/in_var.h>
95 #include <netinet/in_systm.h>
96 #include <netinet/ip.h>
98 # include <netinet/ip_var.h>
100 #include <netinet/tcp.h>
102 # include <netinet/tcp_timer.h>
104 #if defined(__osf__) || defined(__hpux) || defined(__sgi)
105 # include "radix_ipf_local.h"
108 #include <netinet/udp.h>
109 #include <netinet/tcpip.h>
110 #include <netinet/ip_icmp.h>
113 #include <arpa/inet.h>
115 # undef _NET_ROUTE_INCLUDED
117 #include "netinet/ip_compat.h"
118 #include "netinet/ip_fil.h"
119 #include "netinet/ip_nat.h"
120 #include "netinet/ip_frag.h"
121 #include "netinet/ip_state.h"
122 #include "netinet/ip_proxy.h"
123 #include "netinet/ip_auth.h"
125 #include "netinet/ip_sync.h"
128 #include "netinet/ip_scan.h"
130 #include "netinet/ip_pool.h"
131 #ifdef IPFILTER_COMPILED
132 # include "netinet/ip_rules.h"
134 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
135 # include <sys/malloc.h>
143 #if !defined(__osf__) && !defined(__linux__)
144 extern struct protosw inetsw[];
148 static struct ifnet **ifneta = NULL;
151 static void fr_setifpaddr __P((struct ifnet *, char *));
152 void init_ifp __P((void));
153 #if defined(__sgi) && (IRIX < 60500)
154 static int no_output __P((struct ifnet *, struct mbuf *,
156 static int write_output __P((struct ifnet *, struct mbuf *,
160 static int no_output __P((struct ifnet *, struct mbuf *,
161 struct sockaddr *, struct rtentry *, char *));
162 static int write_output __P((struct ifnet *, struct mbuf *,
163 struct sockaddr *, struct rtentry *, char *));
165 static int no_output __P((struct ifnet *, struct mbuf *,
166 struct sockaddr *, struct rtentry *));
167 static int write_output __P((struct ifnet *, struct mbuf *,
168 struct sockaddr *, struct rtentry *));
188 * Filter ioctl interface.
190 int iplioctl(dev, cmd, data, mode)
196 int error = 0, unit = 0, uid;
204 error = fr_ioctlswitch(unit, data, cmd, mode, uid, NULL);
215 void fr_forgetifp(ifp)
218 register frentry_t *f;
220 WRITE_ENTER(&ipf_mutex);
221 for (f = ipacct[0][fr_active]; (f != NULL); f = f->fr_next)
222 if (f->fr_ifa == ifp)
223 f->fr_ifa = (void *)-1;
224 for (f = ipacct[1][fr_active]; (f != NULL); f = f->fr_next)
225 if (f->fr_ifa == ifp)
226 f->fr_ifa = (void *)-1;
227 for (f = ipfilter[0][fr_active]; (f != NULL); f = f->fr_next)
228 if (f->fr_ifa == ifp)
229 f->fr_ifa = (void *)-1;
230 for (f = ipfilter[1][fr_active]; (f != NULL); f = f->fr_next)
231 if (f->fr_ifa == ifp)
232 f->fr_ifa = (void *)-1;
234 for (f = ipacct6[0][fr_active]; (f != NULL); f = f->fr_next)
235 if (f->fr_ifa == ifp)
236 f->fr_ifa = (void *)-1;
237 for (f = ipacct6[1][fr_active]; (f != NULL); f = f->fr_next)
238 if (f->fr_ifa == ifp)
239 f->fr_ifa = (void *)-1;
240 for (f = ipfilter6[0][fr_active]; (f != NULL); f = f->fr_next)
241 if (f->fr_ifa == ifp)
242 f->fr_ifa = (void *)-1;
243 for (f = ipfilter6[1][fr_active]; (f != NULL); f = f->fr_next)
244 if (f->fr_ifa == ifp)
245 f->fr_ifa = (void *)-1;
247 RWLOCK_EXIT(&ipf_mutex);
252 #if defined(__sgi) && (IRIX < 60500)
253 static int no_output(ifp, m, s)
256 static int no_output (ifp, m, s, rt, cp)
259 static int no_output(ifp, m, s, rt)
271 #if defined(__sgi) && (IRIX < 60500)
272 static int write_output(ifp, m, s)
275 static int write_output (ifp, m, s, rt, cp)
278 static int write_output(ifp, m, s, rt)
292 ip = MTOD(mb, ip_t *);
294 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
295 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
296 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
297 sprintf(fname, "/tmp/%s", ifp->if_xname);
299 sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
301 fd = open(fname, O_WRONLY|O_APPEND);
306 write(fd, (char *)ip, ntohs(ip->ip_len));
312 static void fr_setifpaddr(ifp, addr)
317 struct in_ifaddr *ifa;
322 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
323 if (ifp->if_addrlist.tqh_first != NULL)
326 if (ifp->in_ifaddr != NULL)
328 if (ifp->if_addrlist != NULL)
333 ifa = (struct ifaddr *)malloc(sizeof(*ifa));
334 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
335 ifp->if_addrlist.tqh_first = ifa;
338 ifp->in_ifaddr = ifa;
340 ifp->if_addrlist = ifa;
345 struct sockaddr_in *sin;
348 sin = (struct sockaddr_in *)&ifa->ia_addr;
350 sin = (struct sockaddr_in *)&ifa->ifa_addr;
352 sin->sin_addr.s_addr = inet_addr(addr);
353 if (sin->sin_addr.s_addr == 0)
358 struct ifnet *get_unit(name, v)
362 struct ifnet *ifp, **ifpp, **old_ifneta;
364 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
365 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
366 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
371 addr = strchr(name, '=');
375 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
376 if (!strcmp(name, ifp->if_xname)) {
378 fr_setifpaddr(ifp, addr);
383 char *s, ifname[LIFNAMSIZ+1];
388 addr = strchr(name, '=');
392 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
393 COPYIFNAME(v, ifp, ifname);
394 if (!strcmp(name, ifname)) {
396 fr_setifpaddr(ifp, addr);
403 ifneta = (struct ifnet **)malloc(sizeof(ifp) * 2);
407 ifneta[0] = (struct ifnet *)calloc(1, sizeof(*ifp));
416 ifneta = (struct ifnet **)realloc(ifneta,
417 (nifs + 1) * sizeof(ifp));
424 ifneta[nifs - 1] = (struct ifnet *)malloc(sizeof(*ifp));
425 if (!ifneta[nifs - 1]) {
430 ifp = ifneta[nifs - 1];
432 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
433 TAILQ_INIT(&ifp->if_addrlist);
435 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
436 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
437 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
438 (void) strncpy(ifp->if_xname, name, sizeof(ifp->if_xname));
440 for (s = name; *s && !ISDIGIT(*s); s++)
442 if (*s && ISDIGIT(*s)) {
443 ifp->if_unit = atoi(s);
444 ifp->if_name = (char *)malloc(s - name + 1);
445 (void) strncpy(ifp->if_name, name, s - name);
446 ifp->if_name[s - name] = '\0';
448 ifp->if_name = strdup(name);
452 ifp->if_output = (void *)no_output;
455 fr_setifpaddr(ifp, addr);
462 char *get_ifname(ifp)
465 static char ifname[LIFNAMSIZ];
467 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(linux) || \
468 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
469 sprintf(ifname, "%s", ifp->if_xname);
471 sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit);
480 struct ifnet *ifp, **ifpp;
484 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
485 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
486 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
487 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
488 ifp->if_output = (void *)write_output;
489 sprintf(fname, "/tmp/%s", ifp->if_xname);
490 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
498 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
499 ifp->if_output = write_output;
500 sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
501 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
511 int fr_fastroute(m, mpp, fin, fdp)
516 struct ifnet *ifp = fdp->fd_ifp;
517 ip_t *ip = fin->fin_ip;
523 return 0; /* no routing table out here */
528 if (fin->fin_out == 0) {
532 (void) fr_acctpkt(fin, NULL);
534 if (!fr || !(fr->fr_flags & FR_RETMASK)) {
537 (void) fr_checkstate(fin, &pass);
540 switch (fr_checknatout(fin, NULL))
557 #if defined(__sgi) && (IRIX < 60500)
558 (*ifp->if_output)(ifp, (void *)ip, NULL);
560 (*ifp->if_output)(ifp, (void *)m, NULL, 0, 0);
562 (*ifp->if_output)(ifp, (void *)m, NULL, 0);
570 int fr_send_reset(fin)
573 verbose("- TCP RST sent\n");
578 int fr_send_icmp_err(type, fin, dst)
583 verbose("- ICMP unreachable sent\n");
602 void m_copydata(m, off, len, cp)
607 bcopy((char *)m + off, cp, len);
611 int ipfuiomove(buf, len, rwflag, uio)
616 int left, ioc, num, offset;
620 if (rwflag == UIO_READ) {
624 offset = uio->uio_offset;
626 while ((left > 0) && (ioc < uio->uio_iovcnt)) {
627 io = uio->uio_iov + ioc;
631 start = (char *)io->iov_base + offset;
632 if (start > (char *)io->iov_base + io->iov_len) {
633 offset -= io->iov_len;
637 bcopy(buf, start, num);
638 uio->uio_resid -= num;
639 uio->uio_offset += num;
651 u_32_t fr_newisn(fin)
654 static int iss_seq_off = 0;
660 * Compute the base value of the ISS. It is a hash
661 * of (saddr, sport, daddr, dport, secret).
665 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src,
666 sizeof(fin->fin_fi.fi_src));
667 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst,
668 sizeof(fin->fin_fi.fi_dst));
669 MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat));
671 /* MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); */
673 MD5Final(hash, &ctx);
675 memcpy(&newiss, hash, sizeof(newiss));
678 * Now increment our "timer", and add it in to
679 * the computed value.
682 * XXX TCP_ISSINCR too large to use?
684 iss_seq_off += 0x00010000;
685 newiss += iss_seq_off;
690 /* ------------------------------------------------------------------------ */
691 /* Function: fr_nextipid */
692 /* Returns: int - 0 == success, -1 == error (packet should be droppped) */
693 /* Parameters: fin(I) - pointer to packet information */
695 /* Returns the next IPv4 ID to use for this packet. */
696 /* ------------------------------------------------------------------------ */
697 INLINE u_short fr_nextipid(fin)
700 static u_short ipid = 0;
703 MUTEX_ENTER(&ipf_rw);
711 INLINE void fr_checkv4sum(fin)
714 if (fr_checkl4sum(fin) == -1)
715 fin->fin_flx |= FI_BAD;
720 INLINE void fr_checkv6sum(fin)
723 if (fr_checkl4sum(fin) == -1)
724 fin->fin_flx |= FI_BAD;
730 * See above for description, except that all addressing is in user space.
732 int copyoutptr(src, dst, size)
738 bcopy(dst, (char *)&ca, sizeof(ca));
739 bcopy(src, ca, size);
745 * See above for description, except that all addressing is in user space.
747 int copyinptr(src, dst, size)
753 bcopy(src, (char *)&ca, sizeof(ca));
754 bcopy(ca, dst, size);
760 * return the first IP Address associated with an interface
762 int fr_ifpaddr(v, atype, ifptr, inp, inpmask)
765 struct in_addr *inp, *inpmask;
767 struct ifnet *ifp = ifptr;
769 struct in_ifaddr *ifa;
774 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
775 ifa = ifp->if_addrlist.tqh_first;
778 ifa = (struct in_ifaddr *)ifp->in_ifaddr;
780 ifa = ifp->if_addrlist;
784 struct sockaddr_in *sin, mask;
786 mask.sin_addr.s_addr = 0xffffffff;
789 sin = (struct sockaddr_in *)&ifa->ia_addr;
791 sin = (struct sockaddr_in *)&ifa->ifa_addr;
794 return fr_ifpfillv4addr(atype, sin, &mask, inp, inpmask);
809 static int seeded = 0;
812 * Choose a non-random seed so that "randomness" can be "tested."