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.11 2006/03/25 11:15:30 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>
67 #include <arpa/inet.h>
70 # define _NET_ROUTE_INCLUDED
76 #if __FreeBSD_version >= 300000
77 # include <net/if_var.h>
80 #include <sys/debug.h>
81 # ifdef IFF_DRVRLOCK /* IRIX6 */
82 #include <sys/hashing.h>
85 #if defined(__FreeBSD__)
86 # include "radix_ipf.h"
88 #include <net/route.h>
89 #include <netinet/in.h>
90 #if !(defined(__sgi) && !defined(IFF_DRVRLOCK)) /* IRIX < 6 */ && \
91 !defined(__hpux) && !defined(linux)
92 # include <netinet/in_var.h>
94 #include <netinet/in_systm.h>
95 #include <netinet/ip.h>
97 # include <netinet/ip_var.h>
99 #include <netinet/tcp.h>
101 # include <netinet/tcp_timer.h>
103 #if defined(__osf__) || defined(__hpux) || defined(__sgi)
104 # include "radix_ipf_local.h"
107 #include <netinet/udp.h>
108 #include <netinet/tcpip.h>
109 #include <netinet/ip_icmp.h>
113 # undef _NET_ROUTE_INCLUDED
115 #include "netinet/ip_compat.h"
116 #include "netinet/ip_fil.h"
117 #include "netinet/ip_nat.h"
118 #include "netinet/ip_frag.h"
119 #include "netinet/ip_state.h"
120 #include "netinet/ip_proxy.h"
121 #include "netinet/ip_auth.h"
123 #include "netinet/ip_sync.h"
126 #include "netinet/ip_scan.h"
128 #include "netinet/ip_pool.h"
129 #ifdef IPFILTER_COMPILED
130 # include "netinet/ip_rules.h"
132 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
133 # include <sys/malloc.h>
141 #if !defined(__osf__) && !defined(__linux__)
142 extern struct protosw inetsw[];
146 static struct ifnet **ifneta = NULL;
149 static int frzerostats __P((caddr_t));
150 static void fr_setifpaddr __P((struct ifnet *, char *));
151 void init_ifp __P((void));
152 #if defined(__sgi) && (IRIX < 60500)
153 static int no_output __P((struct ifnet *, struct mbuf *,
155 static int write_output __P((struct ifnet *, struct mbuf *,
159 static int no_output __P((struct ifnet *, struct mbuf *,
160 struct sockaddr *, struct rtentry *, char *));
161 static int write_output __P((struct ifnet *, struct mbuf *,
162 struct sockaddr *, struct rtentry *, char *));
164 static int no_output __P((struct ifnet *, struct mbuf *,
165 struct sockaddr *, struct rtentry *));
166 static int write_output __P((struct ifnet *, struct mbuf *,
167 struct sockaddr *, struct rtentry *));
186 static int frzerostats(data)
193 error = copyoutptr(&fio, data, sizeof(fio));
197 bzero((char *)frstats, sizeof(*frstats) * 2);
204 * Filter ioctl interface.
206 int iplioctl(dev, cmd, data, mode)
212 int error = 0, unit = 0, tmp;
219 if (unit == IPL_LOGNAT) {
221 error = fr_nat_ioctl(data, cmd, mode);
227 if (unit == IPL_LOGSTATE) {
229 error = fr_state_ioctl(data, cmd, mode);
235 if (unit == IPL_LOGAUTH) {
236 if (fr_running > 0) {
237 if ((cmd == (ioctlcmd_t)SIOCADAFR) ||
238 (cmd == (ioctlcmd_t)SIOCRMAFR)) {
239 if (!(mode & FWRITE)) {
242 error = frrequest(unit, cmd, data,
246 error = fr_auth_ioctl(data, mode, cmd);
253 if (unit == IPL_LOGSYNC) {
256 error = fr_sync_ioctl(data, cmd, mode);
263 if (unit == IPL_LOGSCAN) {
266 error = fr_scan_ioctl(data, cmd, mode);
273 if (unit == IPL_LOGLOOKUP) {
275 error = ip_lookup_ioctl(data, cmd, mode);
286 error = COPYOUT(&iplused[IPL_LOGIPF], (caddr_t)data,
287 sizeof(iplused[IPL_LOGIPF]));
291 if (!(mode & FWRITE))
294 error = COPYIN(data, &tmp, sizeof(tmp));
304 if (!(mode & FWRITE)) {
308 case SIOCIPFGETNEXT :
310 error = fr_ipftune(cmd, (void *)data);
313 if (!(mode & FWRITE))
316 error = COPYIN(data, &fr_flags, sizeof(fr_flags));
319 error = COPYOUT(&fr_flags, data, sizeof(fr_flags));
322 error = fr_resolvefunc(data);
328 if (!(mode & FWRITE))
331 error = frrequest(unit, cmd, data, fr_active, 1);
336 if (!(mode & FWRITE))
339 error = frrequest(unit, cmd, data, 1 - fr_active, 1);
342 if (!(mode & FWRITE))
345 bzero((char *)frcache, sizeof(frcache[0]) * 2);
346 *(u_int *)data = fr_active;
347 fr_active = 1 - fr_active;
352 error = fr_outobj(data, &fio, IPFOBJ_IPFSTAT);
355 if (!(mode & FWRITE))
358 error = frzerostats(data);
361 if (!(mode & FWRITE))
364 error = COPYIN(data, &tmp, sizeof(tmp));
366 tmp = frflush(unit, 4, tmp);
367 error = COPYOUT(&tmp, data, sizeof(tmp));
373 if (!(mode & FWRITE))
376 error = COPYIN(data, &tmp, sizeof(tmp));
378 tmp = frflush(unit, 6, tmp);
379 error = COPYOUT(&tmp, data, sizeof(tmp));
385 error = COPYIN(data, &tmp, sizeof(tmp));
396 if (!(mode & FWRITE))
399 *(int *)data = ipflog_clear(unit);
401 #endif /* IPFILTER_LOG */
403 error = fr_outobj(data, fr_fragstats(), IPFOBJ_FRAGSTAT);
406 if (!(mode & FWRITE))
421 void fr_forgetifp(ifp)
424 register frentry_t *f;
426 WRITE_ENTER(&ipf_mutex);
427 for (f = ipacct[0][fr_active]; (f != NULL); f = f->fr_next)
428 if (f->fr_ifa == ifp)
429 f->fr_ifa = (void *)-1;
430 for (f = ipacct[1][fr_active]; (f != NULL); f = f->fr_next)
431 if (f->fr_ifa == ifp)
432 f->fr_ifa = (void *)-1;
433 for (f = ipfilter[0][fr_active]; (f != NULL); f = f->fr_next)
434 if (f->fr_ifa == ifp)
435 f->fr_ifa = (void *)-1;
436 for (f = ipfilter[1][fr_active]; (f != NULL); f = f->fr_next)
437 if (f->fr_ifa == ifp)
438 f->fr_ifa = (void *)-1;
440 for (f = ipacct6[0][fr_active]; (f != NULL); f = f->fr_next)
441 if (f->fr_ifa == ifp)
442 f->fr_ifa = (void *)-1;
443 for (f = ipacct6[1][fr_active]; (f != NULL); f = f->fr_next)
444 if (f->fr_ifa == ifp)
445 f->fr_ifa = (void *)-1;
446 for (f = ipfilter6[0][fr_active]; (f != NULL); f = f->fr_next)
447 if (f->fr_ifa == ifp)
448 f->fr_ifa = (void *)-1;
449 for (f = ipfilter6[1][fr_active]; (f != NULL); f = f->fr_next)
450 if (f->fr_ifa == ifp)
451 f->fr_ifa = (void *)-1;
453 RWLOCK_EXIT(&ipf_mutex);
458 #if defined(__sgi) && (IRIX < 60500)
459 static int no_output(ifp, m, s)
462 static int no_output (ifp, m, s, rt, cp)
465 static int no_output(ifp, m, s, rt)
477 #if defined(__sgi) && (IRIX < 60500)
478 static int write_output(ifp, m, s)
481 static int write_output (ifp, m, s, rt, cp)
484 static int write_output(ifp, m, s, rt)
498 ip = MTOD(mb, ip_t *);
500 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
501 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
502 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
503 sprintf(fname, "/tmp/%s", ifp->if_xname);
505 sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
507 fd = open(fname, O_WRONLY|O_APPEND);
512 write(fd, (char *)ip, ntohs(ip->ip_len));
518 static void fr_setifpaddr(ifp, addr)
523 struct in_ifaddr *ifa;
528 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
529 if (ifp->if_addrlist.tqh_first != NULL)
532 if (ifp->in_ifaddr != NULL)
534 if (ifp->if_addrlist != NULL)
539 ifa = (struct ifaddr *)malloc(sizeof(*ifa));
540 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
541 ifp->if_addrlist.tqh_first = ifa;
544 ifp->in_ifaddr = ifa;
546 ifp->if_addrlist = ifa;
551 struct sockaddr_in *sin;
554 sin = (struct sockaddr_in *)&ifa->ia_addr;
556 sin = (struct sockaddr_in *)&ifa->ifa_addr;
558 sin->sin_addr.s_addr = inet_addr(addr);
559 if (sin->sin_addr.s_addr == 0)
564 struct ifnet *get_unit(name, v)
568 struct ifnet *ifp, **ifpp, **old_ifneta;
570 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
571 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
572 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
577 addr = strchr(name, '=');
581 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
582 if (!strcmp(name, ifp->if_xname)) {
584 fr_setifpaddr(ifp, addr);
589 char *s, ifname[LIFNAMSIZ+1];
594 addr = strchr(name, '=');
598 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
599 COPYIFNAME(ifp, ifname);
600 if (!strcmp(name, ifname)) {
602 fr_setifpaddr(ifp, addr);
609 ifneta = (struct ifnet **)malloc(sizeof(ifp) * 2);
613 ifneta[0] = (struct ifnet *)calloc(1, sizeof(*ifp));
622 ifneta = (struct ifnet **)realloc(ifneta,
623 (nifs + 1) * sizeof(ifp));
630 ifneta[nifs - 1] = (struct ifnet *)malloc(sizeof(*ifp));
631 if (!ifneta[nifs - 1]) {
636 ifp = ifneta[nifs - 1];
638 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
639 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
640 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
641 (void) strncpy(ifp->if_xname, name, sizeof(ifp->if_xname));
643 for (s = name; *s && !ISDIGIT(*s); s++)
645 if (*s && ISDIGIT(*s)) {
646 ifp->if_unit = atoi(s);
647 ifp->if_name = (char *)malloc(s - name + 1);
648 (void) strncpy(ifp->if_name, name, s - name);
649 ifp->if_name[s - name] = '\0';
651 ifp->if_name = strdup(name);
655 ifp->if_output = no_output;
658 fr_setifpaddr(ifp, addr);
665 char *get_ifname(ifp)
668 static char ifname[LIFNAMSIZ];
670 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(linux) || \
671 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
672 sprintf(ifname, "%s", ifp->if_xname);
674 sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit);
683 struct ifnet *ifp, **ifpp;
687 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
688 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
689 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
690 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
691 ifp->if_output = write_output;
692 sprintf(fname, "/tmp/%s", ifp->if_xname);
693 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
701 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
702 ifp->if_output = write_output;
703 sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
704 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
714 int fr_fastroute(m, mpp, fin, fdp)
719 struct ifnet *ifp = fdp->fd_ifp;
720 ip_t *ip = fin->fin_ip;
726 return 0; /* no routing table out here */
731 if (fin->fin_out == 0) {
735 (void) fr_acctpkt(fin, NULL);
737 if (!fr || !(fr->fr_flags & FR_RETMASK)) {
740 (void) fr_checkstate(fin, &pass);
743 switch (fr_checknatout(fin, NULL))
760 #if defined(__sgi) && (IRIX < 60500)
761 (*ifp->if_output)(ifp, (void *)ip, NULL);
763 (*ifp->if_output)(ifp, (void *)m, NULL, 0, 0);
765 (*ifp->if_output)(ifp, (void *)m, NULL, 0);
773 int fr_send_reset(fin)
776 verbose("- TCP RST sent\n");
781 int fr_send_icmp_err(type, fin, dst)
786 verbose("- ICMP unreachable sent\n");
805 void m_copydata(m, off, len, cp)
810 bcopy((char *)m + off, cp, len);
814 int ipfuiomove(buf, len, rwflag, uio)
819 int left, ioc, num, offset;
823 if (rwflag == UIO_READ) {
827 offset = uio->uio_offset;
829 while ((left > 0) && (ioc < uio->uio_iovcnt)) {
830 io = uio->uio_iov + ioc;
834 start = (char *)io->iov_base + offset;
835 if (start > (char *)io->iov_base + io->iov_len) {
836 offset -= io->iov_len;
840 bcopy(buf, start, num);
841 uio->uio_resid -= num;
842 uio->uio_offset += num;
854 u_32_t fr_newisn(fin)
857 static int iss_seq_off = 0;
863 * Compute the base value of the ISS. It is a hash
864 * of (saddr, sport, daddr, dport, secret).
868 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src,
869 sizeof(fin->fin_fi.fi_src));
870 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst,
871 sizeof(fin->fin_fi.fi_dst));
872 MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat));
874 /* MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); */
876 MD5Final(hash, &ctx);
878 memcpy(&newiss, hash, sizeof(newiss));
881 * Now increment our "timer", and add it in to
882 * the computed value.
885 * XXX TCP_ISSINCR too large to use?
887 iss_seq_off += 0x00010000;
888 newiss += iss_seq_off;
893 /* ------------------------------------------------------------------------ */
894 /* Function: fr_nextipid */
895 /* Returns: int - 0 == success, -1 == error (packet should be droppped) */
896 /* Parameters: fin(I) - pointer to packet information */
898 /* Returns the next IPv4 ID to use for this packet. */
899 /* ------------------------------------------------------------------------ */
900 INLINE u_short fr_nextipid(fin)
903 static u_short ipid = 0;
906 MUTEX_ENTER(&ipf_rw);
914 INLINE void fr_checkv4sum(fin)
917 if (fr_checkl4sum(fin) == -1)
918 fin->fin_flx |= FI_BAD;
923 INLINE void fr_checkv6sum(fin)
926 if (fr_checkl4sum(fin) == -1)
927 fin->fin_flx |= FI_BAD;
933 * See above for description, except that all addressing is in user space.
935 int copyoutptr(src, dst, size)
941 bcopy(dst, (char *)&ca, sizeof(ca));
942 bcopy(src, ca, size);
948 * See above for description, except that all addressing is in user space.
950 int copyinptr(src, dst, size)
956 bcopy(src, (char *)&ca, sizeof(ca));
957 bcopy(ca, dst, size);
963 * return the first IP Address associated with an interface
965 int fr_ifpaddr(v, atype, ifptr, inp, inpmask)
968 struct in_addr *inp, *inpmask;
970 struct ifnet *ifp = ifptr;
972 struct in_ifaddr *ifa;
977 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
978 ifa = ifp->if_addrlist.tqh_first;
981 ifa = (struct in_ifaddr *)ifp->in_ifaddr;
983 ifa = ifp->if_addrlist;
987 struct sockaddr_in *sin, mask;
989 mask.sin_addr.s_addr = 0xffffffff;
992 sin = (struct sockaddr_in *)&ifa->ia_addr;
994 sin = (struct sockaddr_in *)&ifa->ifa_addr;
997 return fr_ifpfillv4addr(atype, sin, &mask, inp, inpmask);