This patch affects both kernel and userland. Make sure you have both
kenel and userland sources before applying this patch.

Apply by doing:
	# cd /usr/src
	# patch -p0 < 023_ipf.patch

	now, build a kernel. Eg, for GENERIC:

	# cd sys/arch/i386/conf
	# config GENERIC
	# cd ../compile/GENERIC
	# make clean && make depend && make
	# cp /bsd /bsd.old
	# cp bsd /bsd

	Export headers to userland

	# cd /usr/src
	# make includes
	
	And now rebuild userland

	# cd /usr/src/sbin/ipf
	# make obj && make cleandir && make && make install
	# cd /usr/src/sbin/ipnat
	# make obj && make cleandir && make && make install
	# cd /usr/src/sbin/ipfstat
	# make obj && make cleandir && make && make install
	# cd /usr/src/usr.sbin/ipmon
	# make obj && make cleandir && make && make install
	# cd /usr/src/usr.sbin/ipftest
	# make obj && make cleandir && make && make install

Reboot to activate the new ipf. To check that all was successful, do:
	
	# ipf -V

You should see something like:

	ipf: IP Filter: v3.3.16 (184)
	Kernel: IP Filter: v3.3.16
	Running: yes
	Log Flags: 0 = none set
	Default: pass all, Logging: available
	Active list: 0

Index: sys/netinet/ipl.h
===================================================================
RCS file: ipl.h
diff -N ipl.h
--- /dev/null	Wed May 24 17:02:20 2000
+++ sys/netinet/ipl.h	Wed May 24 17:46:34 2000
@@ -0,0 +1,18 @@
+/*	$OpenBSD: ipl.h,v 1.11 2000/05/24 21:59:11 kjell Exp $	*/
+
+/*
+ * Copyright (C) 1993-1999 by Darren Reed.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and due credit is given
+ * to the original author and the contributors.
+ *
+ * @(#)ipl.h	1.21 6/5/96
+ */
+
+#ifndef	__IPL_H__
+#define	__IPL_H__
+
+#define	IPL_VERSION	"IP Filter: v3.3.16"
+
+#endif
Index: sys/netinet/fil.c
===================================================================
RCS file: /cvs/src/sys/netinet/fil.c,v
retrieving revision 1.15
retrieving revision 1.25
diff -u -r1.15 -r1.25
--- sys/netinet/fil.c	1999/02/19 20:52:22	1.15
+++ sys/netinet/fil.c	2000/05/24 21:59:10	1.25
@@ -1,4 +1,5 @@
-/*       $OpenBSD: fil.c,v 1.15 1999/02/19 20:52:22 kjell Exp $       */
+/*	$OpenBSD: fil.c,v 1.25 2000/05/24 21:59:10 kjell Exp $	*/
+
 /*
  * Copyright (C) 1993-1998 by Darren Reed.
  *
@@ -8,7 +9,7 @@
  */
 #if !defined(lint)
 static const char sccsid[] = "@(#)fil.c	1.36 6/5/96 (C) 1993-1996 Darren Reed";
-static const char rcsid[] = "@(#)$Id: fil.c,v 1.15 1999/02/19 20:52:22 kjell Exp $";
+static const char rcsid[] = "@(#)$IPFilter: fil.c,v 2.3.2.20 2000/05/22 06:57:42 darrenr Exp $";
 #endif
 
 #include <sys/errno.h>
@@ -16,7 +17,17 @@
 #include <sys/param.h>
 #include <sys/time.h>
 #include <sys/file.h>
-#include <sys/ioctl.h>
+#if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \
+    defined(_KERNEL)
+# include "opt_ipfilter_log.h"
+#endif
+#if (defined(KERNEL) || defined(_KERNEL)) && defined(__FreeBSD_version) && \
+    (__FreeBSD_version >= 220000)
+# include <sys/filio.h>
+# include <sys/fcntl.h>
+#else
+# include <sys/ioctl.h>
+#endif
 #if (defined(_KERNEL) || defined(KERNEL)) && !defined(linux)
 # include <sys/systm.h>
 #else
@@ -32,9 +43,9 @@
 #else
 # include <sys/byteorder.h>
 # if SOLARIS2 < 5
-# include <sys/dditypes.h>
+#  include <sys/dditypes.h>
 # endif
-# include <sys/stream.h>
+#  include <sys/stream.h>
 #endif
 #ifndef linux
 # include <sys/protosw.h>
@@ -51,14 +62,14 @@
 #ifndef linux
 # include <netinet/ip_var.h>
 #endif
+#if defined(__sgi) && defined(IFF_DRVRLOCK) /* IRIX 6 */
+# include <sys/hashing.h>
+# include <netinet/in_var.h>
+#endif
 #include <netinet/tcp.h>
 #include <netinet/udp.h>
 #include <netinet/ip_icmp.h>
-#if defined(__OpenBSD__)
-# include <netinet/ip_fil_compat.h>
-#else
-# include <netinet/ip_compat.h>
-#endif
+#include <netinet/ip_fil_compat.h>
 #include <netinet/tcpip.h>
 #include <netinet/ip_fil.h>
 #include <netinet/ip_proxy.h>
@@ -66,9 +77,16 @@
 #include <netinet/ip_frag.h>
 #include <netinet/ip_state.h>
 #include <netinet/ip_auth.h>
+# if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
+#  include <sys/malloc.h>
+#  if defined(_KERNEL) && !defined(IPFILTER_LKM)
+#   include "opt_ipfilter.h"
+#  endif
+# endif
 #ifndef	MIN
-#define	MIN(a,b)	(((a)<(b))?(a):(b))
+# define	MIN(a,b)	(((a)<(b))?(a):(b))
 #endif
+#include <netinet/ipl.h>
 
 #ifndef	_KERNEL
 # include "ipf.h"
@@ -81,14 +99,7 @@
 							  second; }
 # define	FR_VERBOSE(verb_pr)			verbose verb_pr
 # define	FR_DEBUG(verb_pr)			debug verb_pr
-# define	SEND_RESET(ip, qif, if, m)		send_reset(ip, if)
 # define	IPLLOG(a, c, d, e)		ipllog()
-# define	FR_NEWAUTH(m, fi, ip, qif)	fr_newauth((mb_t *)m, fi, ip)
-# if SOLARIS
-#  define	ICMP_ERROR(b, ip, t, c, if, src) 	icmp_error(ip)
-# else
-#  define	ICMP_ERROR(b, ip, t, c, if, src) 	icmp_error(b, ip, if)
-# endif
 #else /* #ifndef _KERNEL */
 # define	FR_IFVERBOSE(ex,second,verb_pr)	;
 # define	FR_IFDEBUG(ex,second,verb_pr)	;
@@ -96,39 +107,8 @@
 # define	FR_DEBUG(verb_pr)
 # define	IPLLOG(a, c, d, e)		ipflog(a, c, d, e)
 # if SOLARIS || defined(__sgi)
-extern	KRWLOCK_T	ipf_mutex, ipf_auth;
+extern	KRWLOCK_T	ipf_mutex, ipf_auth, ipf_nat;
 extern	kmutex_t	ipf_rw;
-# endif
-# if SOLARIS
-#  define	FR_NEWAUTH(m, fi, ip, qif)	fr_newauth((mb_t *)m, fi, \
-							   ip, qif)
-#  define	SEND_RESET(ip, qif, if)		send_reset(ip, qif)
-#  define	ICMP_ERROR(b, ip, t, c, if, src) \
-			icmp_error(ip, t, c, if, src)
-# else /* SOLARIS */
-#  define	FR_NEWAUTH(m, fi, ip, qif)	fr_newauth((mb_t *)m, fi, ip)
-#  ifdef linux
-#   define	SEND_RESET(ip, qif, if)		send_reset((tcpiphdr_t *)ip,\
-							   ifp)
-#  else
-#   define	SEND_RESET(ip, qif, if)		send_reset((tcpiphdr_t *)ip)
-#  endif
-#  ifdef __sgi
-#   define	ICMP_ERROR(b, ip, t, c, if, src) \
-			icmp_error(b, t, c, if, src, if)
-#  else
-#   if BSD < 199103
-#    ifdef linux
-#     define	ICMP_ERROR(b, ip, t, c, if, src) 	icmp_send(b,t,c,0,if)
-#    else
-#     define	ICMP_ERROR(b, ip, t, c, if, src) \
-			icmp_error(mtod(b, ip_t *), t, c, if, src)
-#    endif /* linux */
-#   else
-#    define	ICMP_ERROR(b, ip, t, c, if, src) \
-			icmp_error(b, t, c, (src).s_addr, if)
-#   endif /* BSD < 199103 */
-#  endif /* __sgi */
 # endif /* SOLARIS || __sgi */
 #endif /* _KERNEL */
 
@@ -143,12 +123,15 @@
 #else
 int	fr_pass = (IPF_DEFAULT_PASS|FR_NOMATCH);
 #endif
+char	ipfilter_version[] = IPL_VERSION;
 
 fr_info_t	frcache[2];
 
-static	void	fr_makefrip __P((int, ip_t *, fr_info_t *));
 static	int	fr_tcpudpchk __P((frentry_t *, fr_info_t *));
-static	int	frflushlist __P((int, int, int *, frentry_t *, frentry_t **));
+static	int	frflushlist __P((int, minor_t, int *, frentry_t **));
+#ifdef	_KERNEL
+static	void	frsynclist __P((frentry_t *));
+#endif
 
 
 /*
@@ -196,7 +179,7 @@
  * compact the IP header into a structure which contains just the info.
  * which is useful for comparing IP headers with.
  */
-static	void	fr_makefrip(hlen, ip, fin)
+void	fr_makefrip(hlen, ip, fin)
 int hlen;
 ip_t *ip;
 fr_info_t *fin;
@@ -208,6 +191,7 @@
 	int i, mv, ol, off;
 	u_char *s, opt;
 
+	fin->fin_rev = 0;
 	fin->fin_fr = NULL;
 	fin->fin_tcpf = 0;
 	fin->fin_data[0] = 0;
@@ -225,8 +209,8 @@
 	tcp = (tcphdr_t *)((char *)ip + hlen);
 	fin->fin_dp = (void *)tcp;
 	(*(((u_short *)fi) + 1)) = (*(((u_short *)ip) + 4));
-	(*(((u_32_t *)fi) + 1)) = (*(((u_32_t *)ip) + 3));
-	(*(((u_32_t *)fi) + 2)) = (*(((u_32_t *)ip) + 4));
+	fi->fi_src.s_addr = ip->ip_src.s_addr;
+	fi->fi_dst.s_addr = ip->ip_dst.s_addr;
 
 	fi->fi_fl = (hlen > sizeof(ip_t)) ? FI_OPTIONS : 0;
 	off = (ip->ip_off & IP_OFFMASK) << 3;
@@ -244,6 +228,17 @@
 		if (!off && (icmp->icmp_type == ICMP_ECHOREPLY ||
 		     icmp->icmp_type == ICMP_ECHO))
 			minicmpsz = ICMP_MINLEN;
+
+		if (!off && (icmp->icmp_type == ICMP_TSTAMP ||
+		     icmp->icmp_type == ICMP_TSTAMPREPLY))
+			minicmpsz = 20;
+/* type(1) + code(1) + cksum(2) + id(2) + seq(2) + 3*timestamp(3*4) */
+
+		if (!off && (icmp->icmp_type == ICMP_MASKREQ ||
+		     icmp->icmp_type == ICMP_MASKREPLY))
+			minicmpsz = 12;
+/* type(1) + code(1) + cksum(2) + id(2) + seq(2) + mask(4) */
+
 		if ((!(ip->ip_len >= hlen + minicmpsz) && !off) ||
 		    (off && off < sizeof(struct icmp)))
 			fi->fi_fl |= FI_SHORT;
@@ -275,12 +270,19 @@
 	}
 
 
-	for (s = (u_char *)(ip + 1), hlen -= sizeof(*ip); hlen; ) {
-		if (!(opt = *s))
-			break;
-		ol = (opt == IPOPT_NOP) ? 1 : (int)*(s+1);
-		if (opt > 1 && (ol < 2 || ol > hlen))
+	for (s = (u_char *)(ip + 1), hlen -= (int)sizeof(*ip); hlen > 0; ) {
+		opt = *s;
+		if (opt == '\0')
 			break;
+		else if (opt == IPOPT_NOP)
+			ol = 1;
+		else {
+			if (hlen < 2)
+				break;
+			ol = (int)*(s + 1);
+			if (ol < 2 || ol > hlen)
+				break;
+		}
 		for (i = 9, mv = 4; mv >= 0; ) {
 			op = ipopts + i;
 			if (opt == (u_char)op->ol_val) {
@@ -421,14 +423,15 @@
  * kernel sauce.
  */
 int fr_scanlist(pass, ip, fin, m)
-int pass;
+u_32_t pass;
 ip_t *ip;
 register fr_info_t *fin;
 void *m;
 {
 	register struct frentry *fr;
 	register fr_ip_t *fi = &fin->fin_fi;
-	int rulen, portcmp = 0, off, skip = 0;
+	int rulen, portcmp = 0, off, skip = 0, logged = 0;
+	u_32_t passt;
 
 	fr = fin->fin_fr;
 	fin->fin_fr = NULL;
@@ -452,8 +455,16 @@
 		 * check that we are working for the right interface
 		 */
 #ifdef	_KERNEL
-		if (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp)
-			continue;
+# if BSD >= 199306
+		if (fin->fin_out != 0) {
+			if ((fr->fr_oifa &&
+			     fr->fr_oifa != ((mb_t *)m)->m_pkthdr.rcvif) ||
+			    (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp))
+				continue;
+		} else
+# endif
+			if (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp)
+				continue;
 #else
 		if (opts & (OPT_VERBOSE|OPT_DEBUG))
 			printf("\n");
@@ -473,10 +484,12 @@
 			i = ((lip[0] & lm[0]) != ld[0]);
 			FR_IFDEBUG(i,continue,("0. %#08x & %#08x != %#08x\n",
 				   lip[0], lm[0], ld[0]));
-			i |= ((lip[1] & lm[1]) != ld[1]) << 21;
+			i |= ((lip[1] & lm[1]) != ld[1]) << 19;
+			i ^= (fr->fr_flags & FR_NOTSRCIP);
 			FR_IFDEBUG(i,continue,("1. %#08x & %#08x != %#08x\n",
 				   lip[1], lm[1], ld[1]));
-			i |= ((lip[2] & lm[2]) != ld[2]) << 22;
+			i |= ((lip[2] & lm[2]) != ld[2]) << 20;
+			i ^= (fr->fr_flags & FR_NOTDSTIP);
 			FR_IFDEBUG(i,continue,("2. %#08x & %#08x != %#08x\n",
 				   lip[2], lm[2], ld[2]));
 			i |= ((lip[3] & lm[3]) != ld[3]);
@@ -485,7 +498,6 @@
 			i |= ((lip[4] & lm[4]) != ld[4]);
 			FR_IFDEBUG(i,continue,("4. %#08x & %#08x != %#08x\n",
 				   lip[4], lm[4], ld[4]));
-			i ^= (fi->fi_fl & (FR_NOTSRCIP|FR_NOTDSTIP));
 			if (i)
 				continue;
 		}
@@ -515,18 +527,23 @@
 		/*
 		 * Just log this packet...
 		 */
-		if (!(skip = fr->fr_skip))
-			pass = fr->fr_flags;
-		if ((pass & FR_CALLNOW) && fr->fr_func)
-			pass = (*fr->fr_func)(pass, ip, fin);
+		passt = fr->fr_flags;
+		if ((passt & FR_CALLNOW) && fr->fr_func)
+			passt = (*fr->fr_func)(passt, ip, fin);
+		fin->fin_fr = fr;
 #ifdef  IPFILTER_LOG
-		if ((pass & FR_LOGMASK) == FR_LOG) {
-			if (!IPLLOG(fr->fr_flags, ip, fin, m)) {
+		if ((passt & FR_LOGMASK) == FR_LOG) {
+			if (!IPLLOG(passt, ip, fin, m)) {
+				if (passt & FR_LOGORBLOCK)
+					passt |= FR_BLOCK|FR_QUICK;
 				ATOMIC_INC(frstats[fin->fin_out].fr_skip);
 			}
 			ATOMIC_INC(frstats[fin->fin_out].fr_pkl);
+			logged = 1;
 		}
 #endif /* IPFILTER_LOG */
+		if (!(skip = fr->fr_skip) && (passt & FR_LOGMASK) != FR_LOG)
+			pass = passt;
 		FR_DEBUG(("pass %#x\n", pass));
 		ATOMIC_INC(fr->fr_hits);
 		if (pass & FR_ACCOUNT)
@@ -535,7 +552,6 @@
 			fin->fin_icode = fr->fr_icode;
 		fin->fin_rule = rulen;
 		fin->fin_group = fr->fr_group;
-		fin->fin_fr = fr;
 		if (fr->fr_grp) {
 			fin->fin_fr = fr->fr_grp;
 			pass = fr_scanlist(pass, ip, fin, m);
@@ -544,10 +560,14 @@
 				fin->fin_group = fr->fr_group;
 				fin->fin_fr = fr;
 			}
+			if (pass & FR_DONTCACHE)
+				logged = 1;
 		}
 		if (pass & FR_QUICK)
 			break;
 	}
+	if (logged)
+		pass |= FR_DONTCACHE;
 	return pass;
 }
 
@@ -576,7 +596,8 @@
 	fr_info_t frinfo, *fc;
 	register fr_info_t *fin = &frinfo;
 	frentry_t *fr = NULL;
-	int pass, changed, apass, error = EHOSTUNREACH;
+	int changed, error = EHOSTUNREACH;
+	u_32_t pass, apass;
 #if !SOLARIS || !defined(_KERNEL)
 	register mb_t *m = *mp;
 #endif
@@ -597,7 +618,17 @@
 	 */
 	m->m_flags &= ~M_CANFASTFWD;
 #  endif /* M_CANFASTFWD */
+#  ifdef CSUM_DELAY_DATA
+	/*
+	 * disable delayed checksums.
+	 */
+	if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
+		in_delayed_cksum(m);
+		m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
+	}
+#  endif /* CSUM_DELAY_DATA */
 
+
 	if ((ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP ||
 	     ip->ip_p == IPPROTO_ICMP)) {
 		int plen = 0;
@@ -611,8 +642,8 @@
 			case IPPROTO_UDP:
 				plen = sizeof(udphdr_t);
 				break;
+			/* 96 - enough for complete ICMP error IP header */
 			case IPPROTO_ICMP:
-			/* need enough for complete ICMP error IP header */
 				plen = ICMPERR_MAXPKTLEN - sizeof(ip_t);
 				break;
 			}
@@ -648,16 +679,30 @@
 # if SOLARIS
 	mb_t *m = qif->qf_m;
 
+	if ((u_int)ip & 0x3)
+		return 2;
 	fin->fin_qfm = m;
+	fin->fin_qif = qif;
 # endif
 #endif /* _KERNEL */
+
+	/*
+	 * Be careful here: ip_id is in network byte order when called
+	 * from ip_output()
+	 */
+	if (out)
+		ip->ip_id = ntohs(ip->ip_id);
 	fr_makefrip(hlen, ip, fin);
 	fin->fin_ifp = ifp;
 	fin->fin_out = out;
 	fin->fin_mp = mp;
+	pass = fr_pass;
 
 	READ_ENTER(&ipf_mutex);
 
+	if (fin->fin_fi.fi_fl & FI_SHORT)
+		ATOMIC_INC(frstats[out].fr_short);
+	
 	/*
 	 * Check auth now.  This, combined with the check below to see if apass
 	 * is 0 is to ensure that we don't count the packet twice, which can
@@ -668,15 +713,15 @@
 	apass = fr_checkauth(ip, fin);
 
 	if (!out) {
-		changed = ip_natin(ip, hlen, fin);
+		changed = ip_natin(ip, fin);
 		if (!apass && (fin->fin_fr = ipacct[0][fr_active]) &&
-		    (FR_SCANLIST(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) {
+		    (fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) {
 			ATOMIC_INC(frstats[0].fr_acct);
 		}
 	}
 
-	if (apass || (!(pass = ipfr_knownfrag(ip, fin)) &&
-	    !(pass = fr_checkstate(ip, fin)))) {
+	if (apass || (!(fr = ipfr_knownfrag(ip, fin)) &&
+	    !(fr = fr_checkstate(ip, fin)))) {
 		/*
 		 * If a packet is found in the auth table, then skip checking
 		 * the access lists for permission but we do need to consider
@@ -694,13 +739,13 @@
 				if ((fr = fin->fin_fr)) {
 					ATOMIC_INC(fr->fr_hits);
 					pass = fr->fr_flags;
-				} else
-					pass = fr_pass;
+				}
 			} else {
-				pass = fr_pass;
 				if ((fin->fin_fr = ipfilter[out][fr_active]))
-					pass = FR_SCANLIST(fr_pass, ip, fin, m);
-				bcopy((char *)fin, (char *)fc, FI_COPYSIZE);
+					pass = fr_scanlist(fr_pass, ip, fin, m);
+				if (!(pass & (FR_KEEPSTATE|FR_DONTCACHE)))
+					bcopy((char *)fin, (char *)fc,
+					      FI_COPYSIZE);
 				if (pass & FR_NOMATCH) {
 					ATOMIC_INC(frstats[out].fr_nom);
 				}
@@ -715,7 +760,7 @@
 		 * then pretend we've dropped it already.
 		 */
 		if ((pass & FR_AUTH))
-			if (FR_NEWAUTH(m, fin, ip, qif) != 0)
+			if (fr_newauth((mb_t *)m, fin, ip) != 0)
 #ifdef	_KERNEL
 				m = *mp = NULL;
 #else
@@ -725,7 +770,7 @@
 		if (pass & FR_PREAUTH) {
 			READ_ENTER(&ipf_auth);
 			if ((fin->fin_fr = ipauth) &&
-			    (pass = FR_SCANLIST(0, ip, fin, m))) {
+			    (pass = fr_scanlist(0, ip, fin, m))) {
 				ATOMIC_INC(fr_authstats.fas_hits);
 			} else {
 				ATOMIC_INC(fr_authstats.fas_miss);
@@ -733,7 +778,8 @@
 			RWLOCK_EXIT(&ipf_auth);
 		}
 
-		if (pass & FR_KEEPFRAG) {
+		fin->fin_fr = fr;
+		if ((pass & (FR_KEEPFRAG|FR_KEEPSTATE)) == FR_KEEPFRAG) {
 			if (fin->fin_fi.fi_fl & FI_FRAG) {
 				if (ipfr_newfrag(ip, fin, pass) == -1) {
 					ATOMIC_INC(frstats[out].fr_bnfr);
@@ -745,12 +791,16 @@
 			}
 		}
 		if (pass & FR_KEEPSTATE) {
-			if (fr_addstate(ip, fin, pass) == -1) {
+			if (fr_addstate(ip, fin, 0) == NULL) {
 				ATOMIC_INC(frstats[out].fr_bads);
 			} else {
 				ATOMIC_INC(frstats[out].fr_ads);
 			}
 		}
+	} else if (fr != NULL) {
+		pass = fr->fr_flags;
+		if (pass & FR_LOGFIRST)
+			pass &= ~(FR_LOGFIRST|FR_LOG);
 	}
 
 	if (fr && fr->fr_func && !(pass & FR_CALLNOW))
@@ -762,13 +812,13 @@
 	 */
 	if (out && (pass & FR_PASS)) {
 		if ((fin->fin_fr = ipacct[1][fr_active]) &&
-		    (FR_SCANLIST(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) {
+		    (fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) {
 			ATOMIC_INC(frstats[1].fr_acct);
 		}
-		fin->fin_fr = NULL;
-		changed = ip_natout(ip, hlen, fin);
-	}
-	fin->fin_fr = fr;
+		fin->fin_fr = fr;
+		changed = ip_natout(ip, fin);
+	} else
+		fin->fin_fr = fr;
 	RWLOCK_EXIT(&ipf_mutex);
 
 #ifdef	IPFILTER_LOG
@@ -798,6 +848,10 @@
 		}
 	}
 #endif /* IPFILTER_LOG */
+
+	if (out)
+		ip->ip_id = htons(ip->ip_id);
+
 #ifdef	_KERNEL
 	/*
 	 * Only allow FR_DUP to work if a rule matched - it makes no sense to
@@ -830,27 +884,28 @@
 		if (!out) {
 #ifdef	_KERNEL
 			if (pass & FR_RETICMP) {
-# if SOLARIS
-				ICMP_ERROR(q, ip, ICMP_UNREACH, fin->fin_icode,
-					   qif, ip->ip_src);
-# else
-				ICMP_ERROR(m, ip, ICMP_UNREACH, fin->fin_icode,
-					   ifp, ip->ip_src);
-				m = *mp = NULL;	/* freed by icmp_error() */
-# endif
+				struct in_addr dst;
 
+				if ((pass & FR_RETMASK) == FR_FAKEICMP)
+					dst = ip->ip_dst;
+				else
+					dst.s_addr = 0;
+				send_icmp_err(ip, ICMP_UNREACH, fin, dst);
 				ATOMIC_INC(frstats[0].fr_ret);
-			} else if ((pass & FR_RETRST) &&
+			} else if (((pass & FR_RETMASK) == FR_RETRST) &&
 				   !(fin->fin_fi.fi_fl & FI_SHORT)) {
-				if (SEND_RESET(ip, qif, ifp) == 0) {
+				if (send_reset(ip, fin) == 0) {
 					ATOMIC_INC(frstats[1].fr_ret);
 				}
 			}
 #else
-			if (pass & FR_RETICMP) {
+			if ((pass & FR_RETMASK) == FR_RETICMP) {
 				verbose("- ICMP unreachable sent\n");
 				ATOMIC_INC(frstats[0].fr_ret);
-			} else if ((pass & FR_RETRST) &&
+			} else if ((pass & FR_RETMASK) == FR_FAKEICMP) {
+				verbose("- forged ICMP unreachable sent\n");
+				ATOMIC_INC(frstats[0].fr_ret);
+			} else if (((pass & FR_RETMASK) == FR_RETRST) &&
 				   !(fin->fin_fi.fi_fl & FI_SHORT)) {
 				verbose("- TCP RST sent\n");
 				ATOMIC_INC(frstats[1].fr_ret);
@@ -875,10 +930,10 @@
 	if (fr) {
 		frdest_t *fdp = &fr->fr_tif;
 
-		if ((pass & FR_FASTROUTE) ||
+		if (((pass & FR_FASTROUTE) && !out) ||
 		    (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) {
-			ipfr_fastroute(m, fin, fdp);
-			m = *mp = NULL;
+			if (ipfr_fastroute(m, fin, fdp) == 0)
+				m = *mp = NULL;
 		}
 		if (mc)
 			ipfr_fastroute(mc, fin, &fr->fr_dif);
@@ -890,21 +945,20 @@
 		m_copyback(m, 0, up, hbuf);
 #   endif
 #  endif /* !linux */
-	return (pass & FR_PASS) ? 0 : error;
 # else /* !SOLARIS */
 	if (fr) {
 		frdest_t *fdp = &fr->fr_tif;
 
-		if ((pass & FR_FASTROUTE) ||
+		if (((pass & FR_FASTROUTE) && !out) ||
 		    (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) {
-			ipfr_fastroute(qif, ip, m, mp, fin, fdp);
-			m = *mp = NULL;
+			if (ipfr_fastroute(qif, ip, m, mp, fin, fdp) == 0)
+				m = *mp = NULL;
 		}
 		if (mc)
 			ipfr_fastroute(qif, ip, mc, mp, fin, &fr->fr_dif);
 	}
-	return (pass & FR_PASS) ? changed : error;
 # endif /* !SOLARIS */
+	return (pass & FR_PASS) ? 0 : error;
 #else /* _KERNEL */
 	if (pass & FR_NOMATCH)
 		return 1;
@@ -949,23 +1003,21 @@
  * and the TCP header.  We also assume that data blocks aren't allocated in
  * odd sizes.
  */
-u_short fr_tcpsum(m, ip, tcp, len)
+u_short fr_tcpsum(m, ip, tcp)
 mb_t *m;
 ip_t *ip;
 tcphdr_t *tcp;
-int len;
 {
 	u_short *sp, slen, ts;
 	u_int sum, sum2;
 	int hlen;
 
-
 	/*
 	 * Add up IP Header portion
 	 */
 	hlen = ip->ip_hl << 2;
 	slen = ip->ip_len - hlen;
-	sum = htons(ip->ip_p);
+	sum = htons((u_short)ip->ip_p);
 	sum += htons(slen);
 	sp = (u_short *)&ip->ip_src;
 	sum += *sp++;	/* ip_src */
@@ -976,7 +1028,7 @@
 	tcp->th_sum = 0;
 #ifdef	KERNEL
 # if SOLARIS
-	sum2 = ip_cksum(m, hlen, sum);
+	sum2 = ip_cksum(m, hlen, sum);	/* hlen == offset */
 	sum2 = (sum2 & 0xffff) + (sum2 >> 16);
 	sum2 = ~sum2 & 0xffff;
 # else /* SOLARIS */
@@ -1003,13 +1055,11 @@
 	sum2 = (sum2 & 0xffff) + (sum2 >> 16);
 #  else /* defined(BSD) || defined(sun) */
 {
-
 	union {
 		u_char	c[2];
 		u_short	s;
 	} bytes;
-	u_32_t sum;
-	u_short	*sp, slen;
+	u_short len = ip->ip_len;
 # if defined(__sgi)
 	int add;
 # endif
@@ -1020,7 +1070,7 @@
 	sp = (u_short *)&ip->ip_src;
 	len -= (ip->ip_hl << 2);
 	sum = ntohs(IPPROTO_TCP);
-	sum += htons((u_short)len);
+	sum += htons(len);
 	sum += *sp++;	/* ip_src */
 	sum += *sp++;
 	sum += *sp++;	/* ip_dst */
@@ -1034,8 +1084,8 @@
 	sum += *sp++;	/* ack */
 	sum += *sp++;
 	sum += *sp++;	/* off */
-	sum += *sp;	/* win */
-	sp += 2;	/* Skip over checksum */
+	sum += *sp++;	/* win */
+	sum += *sp++;	/* Skip over checksum */
 	sum += *sp++;	/* urp */
 
 # ifdef	__sgi
@@ -1093,7 +1143,7 @@
 		sum = (sum & 0xffff) + (sum >> 16);
 	sum2 = (u_short)(~sum & 0xffff);
 }
-#   endif /*  defined(BSD)  || defined(sun) */
+#  endif /*  defined(BSD) || defined(sun) */
 # endif /* SOLARIS */
 #else /* KERNEL */
 	sum2 = 0;
@@ -1137,7 +1187,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)uipc_mbuf.c	8.2 (Berkeley) 1/4/94
- * $Id: fil.c,v 1.15 1999/02/19 20:52:22 kjell Exp $
+ * $IPFilter: fil.c,v 2.3.2.20 2000/05/22 06:57:42 darrenr Exp $
  */
 /*
  * Copy data from an mbuf chain starting "off" bytes from the beginning,
@@ -1237,9 +1287,10 @@
 
 
 frgroup_t *fr_findgroup(num, flags, which, set, fgpp)
-u_short num;
+u_int num;
 u_32_t flags;
-int which, set;
+minor_t which;
+int set;
 frgroup_t ***fgpp;
 {
 	frgroup_t *fg, **fgp;
@@ -1252,6 +1303,7 @@
 		fgp = &ipfgroups[0][set];
 	else
 		return NULL;
+	num &= 0xffff;
 
 	while ((fg = *fgp))
 		if (fg->fg_num == num)
@@ -1265,18 +1317,19 @@
 
 
 frgroup_t *fr_addgroup(num, fp, which, set)
-u_short num;
+u_int num;
 frentry_t *fp;
-int which, set;
+minor_t which;
+int set;
 {
 	frgroup_t *fg, **fgp;
 
 	if ((fg = fr_findgroup(num, fp->fr_flags, which, set, &fgp)))
 		return fg;
 
-	KMALLOC(fg, frgroup_t *, sizeof(*fg));
+	KMALLOC(fg, frgroup_t *);
 	if (fg) {
-		fg->fg_num = num;
+		fg->fg_num = num & 0xffff;
 		fg->fg_next = *fgp;
 		fg->fg_head = fp;
 		fg->fg_start = &fp->fr_grp;
@@ -1287,9 +1340,10 @@
 
 
 void fr_delgroup(num, flags, which, set)
-u_short num;
+u_int num;
 u_32_t flags;
-int which, set;
+minor_t which;
+int set;
 {
 	frgroup_t *fg, **fgp;
  
@@ -1307,63 +1361,257 @@
  * encountered.  if a rule is the head of a group and it has lost all its
  * group members, then also delete the group reference.
  */
-static int frflushlist(set, unit, nfreedp, list, listp)
-int set, unit, *nfreedp;
-frentry_t *list, **listp;
+static int frflushlist(set, unit, nfreedp, listp)
+int set;
+minor_t unit;
+int *nfreedp;
+frentry_t **listp;
 {
-	register frentry_t *fp = list, *fpn;
-	register int freed = 0;
+	register int freed = 0, i;
+	register frentry_t *fp;
 
-	while (fp) {
-		fpn = fp->fr_next;
+	while ((fp = *listp)) {
+		*listp = fp->fr_next;
 		if (fp->fr_grp) {
-			fp->fr_ref -= frflushlist(set, unit, nfreedp,
-						  fp->fr_grp, &fp->fr_grp);
+			i = frflushlist(set, unit, nfreedp, &fp->fr_grp);
+			MUTEX_ENTER(&ipf_rw);
+			fp->fr_ref -= i;
+			MUTEX_EXIT(&ipf_rw);
 		}
 
-		if (fp->fr_ref == 1) {
-			if (fp->fr_grhead)
-				fr_delgroup(fp->fr_grhead, fp->fr_flags, unit,
-					    set);
+		ATOMIC_DEC(fp->fr_ref);
+		if (fp->fr_grhead) {
+			fr_delgroup((u_int)fp->fr_grhead, fp->fr_flags, 
+				    unit, set);
+			fp->fr_grhead = NULL;
+		}
+		if (fp->fr_ref == 0) {
 			KFREE(fp);
-			*listp = fpn;
 			freed++;
-		}
-		fp = fpn;
+		} else
+			fp->fr_next = NULL;
 	}
 	*nfreedp += freed;
 	return freed;
 }
 
 
-void frflush(unit, result)
-int unit;
-int *result;
+int frflush(unit, flags)
+minor_t unit;
+int flags;
 {
-	int flags = *result, flushed = 0, set = fr_active;
+	int flushed = 0, set;
 
+	if (unit != IPL_LOGIPF)
+		return 0;
 	WRITE_ENTER(&ipf_mutex);
 	bzero((char *)frcache, sizeof(frcache[0]) * 2);
 
+	set = fr_active;
 	if (flags & FR_INACTIVE)
 		set = 1 - set;
+
+	if (flags & FR_OUTQUE) {
+		(void) frflushlist(set, unit, &flushed, &ipfilter[1][set]);
+		(void) frflushlist(set, unit, &flushed, &ipacct[1][set]);
+	}
+	if (flags & FR_INQUE) {
+		(void) frflushlist(set, unit, &flushed, &ipfilter[0][set]);
+		(void) frflushlist(set, unit, &flushed, &ipacct[0][set]);
+	}
+	RWLOCK_EXIT(&ipf_mutex);
+	return flushed;
+}
 
-	if (unit == IPL_LOGIPF) {
-		if (flags & FR_OUTQUE) {
-			(void) frflushlist(set, unit, &flushed,
-					   ipfilter[1][set],
-					   &ipfilter[1][set]);
-			(void) frflushlist(set, unit, &flushed,
-					   ipacct[1][set], &ipacct[1][set]);
-		}
-		if (flags & FR_INQUE) {
-			(void) frflushlist(set, unit, &flushed,
-					   ipfilter[0][set],
-					   &ipfilter[0][set]);
-			(void) frflushlist(set, unit, &flushed,
-					   ipacct[0][set], &ipacct[0][set]);
+
+char *memstr(src, dst, slen, dlen)
+char *src, *dst;
+int slen, dlen;
+{
+	char *s = NULL;
+
+	while (dlen >= slen) {
+		if (bcmp(src, dst, slen) == 0) {
+			s = dst;
+			break;
+		}
+		dst++;
+		dlen--;
+	}
+	return s;
+}
+
+
+void fixskip(listp, rp, addremove)
+frentry_t **listp, *rp;
+int addremove;
+{
+	frentry_t *fp;
+	int rules = 0, rn = 0;
+
+	for (fp = *listp; fp && (fp != rp); fp = fp->fr_next, rules++)
+		;
+
+	if (!fp)
+		return;
+
+	for (fp = *listp; fp && (fp != rp); fp = fp->fr_next, rn++)
+		if (fp->fr_skip && (rn + fp->fr_skip >= rules))
+			fp->fr_skip += addremove;
+}
+
+
+#ifdef	_KERNEL
+/*
+ * count consecutive 1's in bit mask.  If the mask generated by counting
+ * consecutive 1's is different to that passed, return -1, else return #
+ * of bits.
+ */
+int	countbits(ip)
+u_32_t	ip;
+{
+	u_32_t	ipn;
+	int	cnt = 0, i, j;
+
+	ip = ipn = ntohl(ip);
+	for (i = 32; i; i--, ipn *= 2)
+		if (ipn & 0x80000000)
+			cnt++;
+		else
+			break;
+	ipn = 0;
+	for (i = 32, j = cnt; i; i--, j--) {
+		ipn *= 2;
+		if (j > 0)
+			ipn++;
+	}
+	if (ipn == ip)
+		return cnt;
+	return -1;
+}
+
+
+/*
+ * return the first IP Address associated with an interface
+ */
+int fr_ifpaddr(ifptr, inp)
+void *ifptr;
+struct in_addr *inp;
+{
+# if SOLARIS
+	ill_t *ill = ifptr;
+# else
+	struct ifnet *ifp = ifptr;
+# endif
+	struct in_addr in;
+
+# if SOLARIS
+	in.s_addr = ill->ill_ipif->ipif_local_addr;
+# else /* SOLARIS */
+#  if linux
+	;
+#  else /* linux */
+	struct ifaddr *ifa;
+	struct sockaddr_in *sin;
+
+#   if	(__FreeBSD_version >= 300000)
+	ifa = TAILQ_FIRST(&ifp->if_addrhead);
+#   else
+#    if defined(__NetBSD__) || defined(__OpenBSD__)
+	ifa = ifp->if_addrlist.tqh_first;
+#    else
+#     if defined(__sgi) && defined(IFF_DRVRLOCK) /* IRIX 6 */
+	ifa = &((struct in_ifaddr *)ifp->in_ifaddr)->ia_ifa;
+#     else
+	ifa = ifp->if_addrlist;
+#     endif
+#    endif /* __NetBSD__ || __OpenBSD__ */
+#   endif /* __FreeBSD_version >= 300000 */
+#   if (BSD < 199306) && !(/*IRIX6*/defined(__sgi) && defined(IFF_DRVRLOCK))
+	sin = (struct sockaddr_in *)&ifa->ifa_addr;
+#   else
+	sin = (struct sockaddr_in *)ifa->ifa_addr;
+	while (sin && ifa &&
+	       sin->sin_family != AF_INET) {
+#    if	(__FreeBSD_version >= 300000)
+		ifa = TAILQ_NEXT(ifa, ifa_link);
+#    else
+#     if defined(__NetBSD__) || defined(__OpenBSD__)
+		ifa = ifa->ifa_list.tqe_next;
+#     else
+		ifa = ifa->ifa_next;
+#     endif
+#    endif /* __FreeBSD_version >= 300000 */
+		if (ifa)
+			sin = (struct sockaddr_in *)ifa->ifa_addr;
+	}
+	if (ifa == NULL)
+		sin = NULL;
+	if (sin == NULL)
+		return -1;
+#   endif /* (BSD < 199306) && (!__sgi && IFF_DRVLOCK) */
+	in = sin->sin_addr;
+#  endif /* linux */
+# endif /* SOLARIS */
+	*inp = in;
+	return 0;
+}
+
+
+static void frsynclist(fr)
+register frentry_t *fr;
+{
+	for (; fr; fr = fr->fr_next) {
+		if (fr->fr_ifa != NULL) {
+			fr->fr_ifa = GETUNIT(fr->fr_ifname);
+			if (fr->fr_ifa == NULL)
+				fr->fr_ifa = (void *)-1;
 		}
+		if (fr->fr_grp)
+			frsynclist(fr->fr_grp);
+	}
+}
+
+
+void frsync()
+{
+	register struct ifnet *ifp;
+
+# if !SOLARIS
+#  if defined(__OpenBSD__) || ((NetBSD >= 199511) && (NetBSD < 1991011)) || \
+     (defined(__FreeBSD_version) && (__FreeBSD_version >= 300000))
+#   if (NetBSD >= 199905) || defined(__OpenBSD__)
+	for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next)
+#   else
+	for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next)
+#   endif
+#  else
+	for (ifp = ifnet; ifp; ifp = ifp->if_next)
+#  endif
+	{
+		ip_natsync(ifp);
+		ip_statesync(ifp);
 	}
+# endif
+
+	WRITE_ENTER(&ipf_mutex);
+	frsynclist(ipacct[0][fr_active]);
+	frsynclist(ipacct[1][fr_active]);
+	frsynclist(ipfilter[0][fr_active]);
+	frsynclist(ipfilter[1][fr_active]);
 	RWLOCK_EXIT(&ipf_mutex);
-	*result = flushed;
 }
+
+#else
+
+
+/*
+ * return the first IP Address associated with an interface
+ */
+int fr_ifpaddr(ifptr, inp)
+void *ifptr;
+struct in_addr *inp;
+{
+	return 0;
+}
+#endif       
Index: sys/netinet/ip_auth.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_auth.c,v
retrieving revision 1.5
retrieving revision 1.14
diff -u -r1.5 -r1.14
--- sys/netinet/ip_auth.c	1999/02/05 05:58:49	1.5
+++ sys/netinet/ip_auth.c	2000/05/24 21:59:10	1.14
@@ -1,4 +1,5 @@
-/*       $OpenBSD: ip_auth.c,v 1.5 1999/02/05 05:58:49 deraadt Exp $       */
+/*	$OpenBSD: ip_auth.c,v 1.14 2000/05/24 21:59:10 kjell Exp $	*/
+
 /*
  * Copyright (C) 1998 by Darren Reed & Guido van Rooij.
  *
@@ -7,7 +8,7 @@
  * to the original author and the contributors.
  */
 #if !defined(lint)
-static const char rcsid[] = "@(#)$Id: ip_auth.c,v 1.5 1999/02/05 05:58:49 deraadt Exp $";
+static const char rcsid[] = "@(#)$IPFilter: ip_auth.c,v 2.1.2.4 2000/05/22 06:57:45 darrenr Exp $";
 #endif
 
 #include <sys/errno.h>
@@ -20,7 +21,7 @@
 # include <stdlib.h>
 # include <string.h>
 #endif
-#if defined(KERNEL) && (__FreeBSD_version >= 220000)
+#if (defined(KERNEL) || defined(_KERNEL)) && (__FreeBSD_version >= 220000)
 # include <sys/filio.h>
 # include <sys/fcntl.h>
 #else
@@ -41,34 +42,39 @@
 #else
 # include <sys/filio.h>
 # include <sys/byteorder.h>
-# include <sys/dditypes.h>
+# ifdef _KERNEL
+#  include <sys/dditypes.h>
+# endif
 # include <sys/stream.h>
 # include <sys/kmem.h>
 #endif
+#if _BSDI_VERSION >= 199802
+# include <sys/queue.h>
+#endif
 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(bsdi)
 # include <machine/cpu.h>
 #endif
 #include <net/if.h>
 #ifdef sun
-#include <net/af.h>
+# include <net/af.h>
 #endif
 #include <net/route.h>
 #include <netinet/in.h>
 #include <netinet/in_systm.h>
 #include <netinet/ip.h>
 #ifndef	KERNEL
-#define	KERNEL
-#define	NOT_KERNEL
+# define	KERNEL
+# define	NOT_KERNEL
 #endif
 #ifndef linux
 # include <netinet/ip_var.h>
 #endif
 #ifdef	NOT_KERNEL
-#undef	KERNEL
+# undef	KERNEL
 #endif
 #ifdef __sgi
 # ifdef IFF_DRVRLOCK /* IRIX6 */
-#include <sys/hashing.h>
+#  include <sys/hashing.h>
 # endif
 #endif
 #include <netinet/tcp.h>
@@ -76,17 +82,16 @@
 extern struct ifqueue   ipintrq;                /* ip packet input queue */
 #else
 # ifndef linux
+#  if __FreeBSD_version >= 300000
+#   include <net/if_var.h>
+#  endif
 #  include <netinet/in_var.h>
 #  include <netinet/tcp_fsm.h>
 # endif
 #endif
 #include <netinet/udp.h>
 #include <netinet/ip_icmp.h>
-#if defined(__OpenBSD__)
-# include <netinet/ip_fil_compat.h>
-#else
-# include <netinet/ip_compat.h>
-#endif
+#include <netinet/ip_fil_compat.h>
 #include <netinet/tcpip.h>
 #include <netinet/ip_fil.h>
 #include <netinet/ip_auth.h>
@@ -96,6 +101,14 @@
 #  include <machine/cpufunc.h>
 # endif
 #endif
+#if (__FreeBSD_version >= 300000)
+# include <sys/malloc.h>
+# if (defined(_KERNEL) || defined(KERNEL)) && !defined(IPFILTER_LKM)
+#  include <sys/libkern.h>
+#  include <sys/systm.h>
+# endif
+#endif
+
 
 
 #if (SOLARIS || defined(__sgi)) && defined(_KERNEL)
@@ -125,7 +138,7 @@
  * authorization result and that would result in a feedback loop (i.e. it
  * will end up returning FR_AUTH) then return FR_BLOCK instead.
  */
-int fr_checkauth(ip, fin)
+u_32_t fr_checkauth(ip, fin)
 ip_t *ip;
 fr_info_t *fin;
 {
@@ -185,29 +198,27 @@
  * If we do, store it and wake up any user programs which are waiting to
  * hear about these events.
  */
-int fr_newauth(m, fin, ip
-#if defined(_KERNEL) && SOLARIS
-, qif)
-qif_t *qif;
-#else
-)
-#endif
+int fr_newauth(m, fin, ip)
 mb_t *m;
 fr_info_t *fin;
 ip_t *ip;
 {
+#if defined(_KERNEL) && SOLARIS
+	qif_t *qif = fin->fin_qif;
+#endif
 	int i;
 
 	WRITE_ENTER(&ipf_auth);
-	if ((fr_authstart > fr_authend) && (fr_authstart - fr_authend == -1)) {
-		fr_authstats.fas_nospace++;
-		RWLOCK_EXIT(&ipf_auth);
-		return 0;
-	}
-	if (fr_authend - fr_authstart == FR_NUMAUTH - 1) {
+	if (fr_authstart > fr_authend) {
 		fr_authstats.fas_nospace++;
 		RWLOCK_EXIT(&ipf_auth);
 		return 0;
+	} else {
+		if ((fr_authstart == 0) && (fr_authend == FR_NUMAUTH - 1)) {
+			fr_authstats.fas_nospace++;
+			RWLOCK_EXIT(&ipf_auth);
+			return 0;
+		}
 	}
 
 	fr_authstats.fas_added++;
@@ -304,24 +315,27 @@
 				KFREE(fae);
 			}
 		} else {
-			KMALLOC(fae, frauthent_t *, sizeof(*fae));
+			KMALLOC(fae, frauthent_t *);
 			if (fae != NULL) {
 				IRCOPY((char *)data, (char *)&fae->fae_fr,
 				       sizeof(fae->fae_fr));
 				WRITE_ENTER(&ipf_auth);
-				if (!fae->fae_age)
-					fae->fae_age = fr_defaultauthage;
+				fae->fae_age = fr_defaultauthage;
 				fae->fae_fr.fr_hits = 0;
 				fae->fae_fr.fr_next = *frptr;
 				*frptr = &fae->fae_fr;
 				fae->fae_next = *faep;
 				*faep = fae;
+				ipauth = &fae_list->fae_fr;
 				RWLOCK_EXIT(&ipf_auth);
 			} else
 				error = ENOMEM;
 		}
 		break;
 	case SIOCATHST:
+		READ_ENTER(&ipf_auth);
+		fr_authstats.fas_faelist = fae_list;
+		RWLOCK_EXIT(&ipf_auth);
 		IWCOPY((char *)&fr_authstats, data, sizeof(fr_authstats));
 		break;
 	case SIOCAUTHW:
@@ -381,7 +395,12 @@
 #  if SOLARIS
 			error = fr_qout(fr_auth[i].fra_q, m);
 #  else /* SOLARIS */
+#   if (_BSDI_VERSION >= 199802) || defined(__OpenBSD__)
+			error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL,
+					  NULL);
+#   else
 			error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL);
+#   endif
 #  endif /* SOLARIS */
 			if (error)
 				fr_authstats.fas_sendfail++;
@@ -471,6 +490,7 @@
 		*faep = fae->fae_next;
 		KFREE(fae);
 	}
+	ipauth = NULL;
 	RWLOCK_EXIT(&ipf_auth);
 }
 
@@ -502,13 +522,14 @@
 	}
 
 	for (faep = &fae_list; (fae = *faep); ) {
-		if (!--fra->fra_age) {
+		if (!--fae->fae_age) {
 			*faep = fae->fae_next;
 			KFREE(fae);
 			fr_authstats.fas_expire++;
 		} else
 			faep = &fae->fae_next;
 	}
+	ipauth = &fae_list->fae_fr;
 	RWLOCK_EXIT(&ipf_auth);
 	SPL_X(s);
 }
Index: sys/netinet/ip_auth.h
===================================================================
RCS file: /cvs/src/sys/netinet/ip_auth.h,v
retrieving revision 1.3
retrieving revision 1.8
diff -u -r1.3 -r1.8
--- sys/netinet/ip_auth.h	1999/02/05 05:58:50	1.3
+++ sys/netinet/ip_auth.h	2000/05/24 21:59:11	1.8
@@ -1,4 +1,5 @@
-/*       $OpenBSD: ip_auth.h,v 1.3 1999/02/05 05:58:50 deraadt Exp $       */
+/*	$OpenBSD: ip_auth.h,v 1.8 2000/05/24 21:59:11 kjell Exp $	*/
+
 /*
  * Copyright (C) 1997-1998 by Darren Reed & Guido Van Rooij.
  *
@@ -6,7 +7,7 @@
  * provided that this notice is preserved and due credit is given
  * to the original author and the contributors.
  *
- * $Id: ip_auth.h,v 1.3 1999/02/05 05:58:50 deraadt Exp $
+ * $IPFilter: ip_auth.h,v 2.1.2.1 2000/05/22 06:57:47 darrenr Exp $
  *
  */
 #ifndef	__IP_AUTH_H__
@@ -14,18 +15,6 @@
 
 #define FR_NUMAUTH      32
 
-typedef struct  fr_authstat {
-	U_QUAD_T	fas_hits;
-	U_QUAD_T	fas_miss;
-	u_long		fas_nospace;
-	u_long		fas_added;
-	u_long		fas_sendfail;
-	u_long		fas_sendok;
-	u_long		fas_queok;
-	u_long		fas_quefail;
-	u_long		fas_expire;
-} fr_authstat_t;
-
 typedef struct  frauth {
 	int	fra_age;
 	int	fra_index;
@@ -42,6 +31,19 @@
 	u_long	fae_age;
 } frauthent_t;
 
+typedef struct  fr_authstat {
+	U_QUAD_T	fas_hits;
+	U_QUAD_T	fas_miss;
+	u_long		fas_nospace;
+	u_long		fas_added;
+	u_long		fas_sendfail;
+	u_long		fas_sendok;
+	u_long		fas_queok;
+	u_long		fas_quefail;
+	u_long		fas_expire;
+	frauthent_t	*fas_faelist;
+} fr_authstat_t;
+
 
 extern	frentry_t	*ipauth;
 extern	struct fr_authstat	fr_authstats;
@@ -50,15 +52,11 @@
 extern	int	fr_authend;
 extern	int	fr_authsize;
 extern	int	fr_authused;
-extern	int	fr_checkauth __P((ip_t *, fr_info_t *));
+extern	u_32_t	fr_checkauth __P((ip_t *, fr_info_t *));
 extern	void	fr_authexpire __P((void));
 extern	void	fr_authunload __P((void));
 extern	mb_t	*fr_authpkts[];
-#if defined(_KERNEL) && SOLARIS
-extern	int	fr_newauth __P((mb_t *, fr_info_t *, ip_t *, qif_t *));
-#else
 extern	int	fr_newauth __P((mb_t *, fr_info_t *, ip_t *));
-#endif
 #if defined(__NetBSD__) || defined(__OpenBSD__)
 extern	int	fr_auth_ioctl __P((caddr_t, u_long, frentry_t *, frentry_t **));
 #else
Index: sys/netinet/ip_fil_compat.h
===================================================================
RCS file: /cvs/src/sys/netinet/ip_fil_compat.h,v
retrieving revision 1.10
retrieving revision 1.16
diff -u -r1.10 -r1.16
--- sys/netinet/ip_fil_compat.h	1999/02/05 05:58:51	1.10
+++ sys/netinet/ip_fil_compat.h	2000/05/01 06:16:47	1.16
@@ -1,4 +1,5 @@
-/*       $OpenBSD: ip_fil_compat.h,v 1.10 1999/02/05 05:58:51 deraadt Exp $ */
+/*	$OpenBSD: ip_fil_compat.h,v 1.16 2000/05/01 06:16:47 kjell Exp $	*/
+
 /*
  * Copyright (C) 1993-1998 by Darren Reed.
  *
@@ -7,7 +8,7 @@
  * to the original author and the contributors.
  *
  * @(#)ip_compat.h	1.8 1/14/96
- * $Id: ip_fil_compat.h,v 1.10 1999/02/05 05:58:51 deraadt Exp $
+ * $IPFilter: ip_compat.h,v 2.1.2.6 2000/04/25 16:21:11 darrenr Exp $
  */
 
 #ifndef	__IP_COMPAT_H__
@@ -18,9 +19,12 @@
 #  define	__P(x)  x
 # else
 #  define	__P(x)  ()
-#  define	const
 # endif
 #endif
+#ifndef	__STDC__
+# undef		const
+# define	const
+#endif
 
 #ifndef	SOLARIS
 #define	SOLARIS	(defined(sun) && (defined(__svr4__) || defined(__SVR4)))
@@ -73,6 +77,7 @@
 #endif
 #if	SOLARIS
 # define	MTYPE(m)	((m)->b_datap->db_type)
+# include	<sys/isa_defs.h>
 # include	<sys/ioccom.h>
 # include	<sys/sysmacros.h>
 # include	<sys/kmem.h>
@@ -87,15 +92,30 @@
 # ifndef	KERNEL
 #  define	_KERNEL
 #  undef	RES_INIT
+#  if SOLARIS2 >= 8
+#   include <netinet/ip6.h>
+#  endif
 #  include <inet/common.h>
 #  include <inet/ip.h>
 #  include <inet/ip_ire.h>
 #  undef	_KERNEL
 # else /* _KERNEL */
+#  if SOLARIS2 >= 8
+#   include <netinet/ip6.h>
+#  endif
 #  include <inet/common.h>
 #  include <inet/ip.h>
 #  include <inet/ip_ire.h>
 # endif /* _KERNEL */
+# if SOLARIS2 >= 8
+#  define	ipif_local_addr		ipif_lcl_addr
+/* Only defined in private include file */
+#  define	V4_PART_OF_V6(v6)	v6.s6_addr32[3]
+# endif
+#else
+# if !defined(__sgi)
+typedef	 int	minor_t;
+#endif
 #endif /* SOLARIS */
 #define	IPMINLEN(i, h)	((i)->ip_len >= ((i)->ip_hl * 4 + sizeof(struct h)))
 
@@ -122,7 +142,7 @@
 /*
  * Really, any arch where sizeof(long) != sizeof(int).
  */
-# if defined(__alpha__) || defined(__alpha)
+# if defined(__alpha__) || defined(__alpha) || defined(_LP64)
 typedef unsigned int    u_32_t;
 # else
 typedef unsigned long   u_32_t;
@@ -190,7 +210,7 @@
 #define	IPOPT_FINN	205	/* FINN */
 
 
-#if defined(__FreeBSD__) && defined(KERNEL)
+#if defined(__FreeBSD__) && (defined(KERNEL) || defined(_KERNEL))
 # if __FreeBSD__ < 3
 #  include <machine/spl.h>
 # endif
@@ -214,6 +234,10 @@
 #   define	KRWLOCK_T		krwlock_t
 #   define	READ_ENTER(x)		rw_enter(x, RW_READER)
 #   define	WRITE_ENTER(x)		rw_enter(x, RW_WRITER)
+#   define	RW_UPGRADE(x)		{ if (rw_tryupgrade(x) == 0) { \
+					      rw_exit(x); \
+					      rw_enter(x, RW_WRITER); } \
+					}
 #   define	MUTEX_DOWNGRADE(x)	rw_downgrade(x)
 #   define	RWLOCK_INIT(x, y, z)	rw_init((x), (y), RW_DRIVER, (z))
 #   define	RWLOCK_EXIT(x)		rw_exit(x)
@@ -242,7 +266,8 @@
 #   define	htons(x)	(x)
 #   define	htonl(x)	(x)
 #  endif /* sparc */
-#  define	KMALLOC(a,b,c)	(a) = (b)kmem_alloc((c), KM_NOSLEEP)
+#  define	KMALLOC(a,b)	(a) = (b)kmem_alloc(sizeof(*(a)), KM_NOSLEEP)
+#  define	KMALLOCS(a,b,c)	(a) = (b)kmem_alloc((c), KM_NOSLEEP)
 #  define	GET_MINOR(x)	getminor(x)
 typedef	struct	qif	{
 	struct	qif	*qf_next;
@@ -258,18 +283,20 @@
 	struct	qinit	qf_rqinit;
 	mblk_t	*qf_m;	/* These three fields are for passing data up from */
 	queue_t	*qf_q;	/* fr_qin and fr_qout to the packet processing. */
-	int	qf_off;
-	int	qf_len;	/* this field is used for in ipfr_fastroute */
+	size_t	qf_off;
+	size_t	qf_len;	/* this field is used for in ipfr_fastroute */
 	char	qf_name[8];
 	/*
 	 * in case the ILL has disappeared...
 	 */
-	int	qf_hl;	/* header length */
+	size_t	qf_hl;	/* header length */
 } qif_t;
 extern	ill_t	*get_unit __P((char *));
 #  define	GETUNIT(n)	get_unit((n))
+#  define	IFNAME(x)	((ill_t *)x)->ill_name
 # else /* SOLARIS */
 #  if defined(__sgi)
+#   define  hz HZ
 #   include <sys/ksynch.h>
 #   define	IPF_LOCK_PL	plhi
 #   include <sys/sema.h>
@@ -286,6 +313,7 @@
 #   define	KRWLOCK_T		kmutex_t
 #   define	READ_ENTER(x)		MUTEX_ENTER(x)
 #   define	WRITE_ENTER(x)		MUTEX_ENTER(x)
+#   define	RW_UPGRADE(x)		;
 #   define	MUTEX_DOWNGRADE(x)	;
 #   define	RWLOCK_EXIT(x)	MUTEX_EXIT(x)
 #   define	MUTEX_EXIT(x)	UNLOCK((x)->l, (x)->pl);
@@ -295,6 +323,7 @@
 #   define	MUTEX_ENTER(x)		;
 #   define	READ_ENTER(x)	;
 #   define	WRITE_ENTER(x)	;
+#   define	RW_UPGRADE(x)	;
 #   define	MUTEX_DOWNGRADE(x)	;
 #   define	RWLOCK_EXIT(x)	;
 #   define	MUTEX_EXIT(x)	;
@@ -311,10 +340,17 @@
 #  if !SOLARIS
 #   include	<sys/kmem_alloc.h>
 #   define	GETUNIT(n)	ifunit((n), IFNAMSIZ)
+#   define	IFNAME(x)	((struct ifnet *)x)->if_name
 #  endif
 # else
 #  ifndef	linux
 #   define	GETUNIT(n)	ifunit((n))
+#   if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
+	(defined(OpenBSD) && (OpenBSD >= 199603))
+#    define	IFNAME(x)	((struct ifnet *)x)->if_xname
+#   else
+#    define	IFNAME(x)	((struct ifnet *)x)->if_name
+#   endif
 #  endif
 # endif /* sun */
 
@@ -331,11 +367,14 @@
 #  ifdef __sgi
 #   include <sys/kmem.h>
 #   include <sys/ddi.h>
-#   define	KMALLOC(a,b,c)	(a) = (b)kmem_alloc((c), KM_NOSLEEP)
+#   define	KMALLOC(a,b)	(a) = (b)kmem_alloc(sizeof(*(a)), KM_NOSLEEP)
+#   define	KMALLOCS(a,b,c)	(a) = (b)kmem_alloc((c), KM_NOSLEEP)
 #   define	GET_MINOR(x)	getminor(x)
 #  else
 #   if !SOLARIS
-#    define	KMALLOC(a,b,c)	(a) = (b)new_kmem_alloc((c), KMEM_NOSLEEP)
+#    define	KMALLOC(a,b)	(a) = (b)new_kmem_alloc(sizeof(*(a)), \
+							KMEM_NOSLEEP)
+#    define	KMALLOCS(a,b,c)	(a) = (b)new_kmem_alloc((c), KMEM_NOSLEEP)
 #   endif /* SOLARIS */
 #  endif /* __sgi */
 # endif /* sun && !linux */
@@ -352,11 +391,13 @@
 #   include <vm/vm_kern.h>
 #  endif /* !__FreeBSD__ || (__FreeBSD__ && __FreeBSD__>=3) */
 #  ifdef	M_PFIL
-#   define	KMALLOC(a, b, c)	MALLOC((a), b, (c), M_PFIL, M_NOWAIT)
+#   define	KMALLOC(a, b)	MALLOC((a), b, sizeof(*(a)), M_PFIL, M_NOWAIT)
+#   define	KMALLOCS(a, b, c)	MALLOC((a), b, (c), M_PFIL, M_NOWAIT)
 #   define	KFREE(x)	FREE((x), M_PFIL)
 #   define	KFREES(x,s)	FREE((x), M_PFIL)
 #  else
-#   define	KMALLOC(a, b, c)	MALLOC((a), b, (c), M_TEMP, M_NOWAIT)
+#   define	KMALLOC(a, b)	MALLOC((a), b, sizeof(*(a)), M_TEMP, M_NOWAIT)
+#   define	KMALLOCS(a, b, c)	MALLOC((a), b, (c), M_TEMP, M_NOWAIT)
 #   define	KFREE(x)	FREE((x), M_TEMP)
 #   define	KFREES(x,s)	FREE((x), M_TEMP)
 #  endif /* M_PFIL */
@@ -384,6 +425,7 @@
 # define	MUTEX_ENTER(x)	;
 # define	READ_ENTER(x)	;
 # define	WRITE_ENTER(x)	;
+# define	RW_UPGRADE(x)	;
 # define	MUTEX_DOWNGRADE(x)	;
 # define	RWLOCK_EXIT(x)	;
 # define	MUTEX_EXIT(x)	;
@@ -391,7 +433,8 @@
 # define	SPL_IMP(x)	;
 # undef		SPL_X
 # define	SPL_X(x)	;
-# define	KMALLOC(a,b,c)	(a) = (b)malloc(c)
+# define	KMALLOC(a,b)	(a) = (b)malloc(sizeof(*a))
+# define	KMALLOCS(a,b,c)	(a) = (b)malloc(c)
 # define	KFREE(x)	free(x)
 # define	KFREES(x,s)	free(x)
 # define	GETUNIT(x)	get_unit(x)
@@ -401,6 +444,15 @@
 
 #if SOLARIS
 typedef mblk_t mb_t;
+# if SOLARIS2 >= 7
+#  ifdef lint
+#   define ALIGN32(ptr)    (ptr ? 0L : 0L)
+#   define ALIGN16(ptr)    (ptr ? 0L : 0L)
+#  else
+#   define ALIGN32(ptr)    (ptr)
+#   define ALIGN16(ptr)    (ptr)
+#  endif
+# endif
 #else
 # ifdef	linux
 #  ifndef kernel
@@ -619,8 +671,8 @@
 	__u8	ip_hl:4;
 	__u8	ip_v:4;
 # else
-	__u8	ip_hl:4;
 	__u8	ip_v:4;
+	__u8	ip_hl:4;
 # endif
 	__u8	ip_tos;
 	__u16	ip_len;
@@ -727,7 +779,8 @@
 
 #  define	UNITNAME(n)	dev_get((n))
 
-#  define	KMALLOC(a,b,c)	(a) = (b)kmalloc((c), GFP_ATOMIC)
+#  define	KMALLOC(a,b)	(a) = (b)kmalloc(sizeof(*(a)), GFP_ATOMIC)
+#  define	KMALLOCS(a,b,c)	(a) = (b)kmalloc((c), GFP_ATOMIC)
 #  define	KFREE(x)	kfree_s((x), sizeof(*(x)))
 #  define	KFREES(x,s)	kfree_s((x), (s))
 #  define	IRCOPY(a,b,c)	{ \
@@ -791,7 +844,9 @@
  * another IP header and then 64 bits of data, totalling 56.  Of course,
  * the last 64 bits is dependant on that being available.
  */
-#define       ICMPERR_MINPKTLEN       (20 + 8 + 20)
-#define       ICMPERR_MAXPKTLEN       (20 + 8 + 20 + 8)
+#define	ICMPERR_ICMPHLEN	8
+#define	ICMPERR_IPICMPHLEN	(20 + 8)
+#define	ICMPERR_MINPKTLEN	(20 + 8 + 20)
+#define	ICMPERR_MAXPKTLEN	(20 + 8 + 20 + 8)
 
 #endif	/* __IP_COMPAT_H__ */
Index: sys/netinet/ip_fil.h
===================================================================
RCS file: /cvs/src/sys/netinet/ip_fil.h,v
retrieving revision 1.12
retrieving revision 1.20
diff -u -r1.12 -r1.20
--- sys/netinet/ip_fil.h	1999/02/05 05:58:50	1.12
+++ sys/netinet/ip_fil.h	2000/05/24 21:59:11	1.20
@@ -1,4 +1,5 @@
-/*       $OpenBSD: ip_fil.h,v 1.12 1999/02/05 05:58:50 deraadt Exp $       */
+/*	$OpenBSD: ip_fil.h,v 1.20 2000/05/24 21:59:11 kjell Exp $	*/
+
 /*
  * Copyright (C) 1993-1998 by Darren Reed.
  *
@@ -7,16 +8,12 @@
  * to the original author and the contributors.
  *
  * @(#)ip_fil.h	1.35 6/5/96
- * $Id: ip_fil.h,v 1.12 1999/02/05 05:58:50 deraadt Exp $
+ * $IPFilter: ip_fil.h,v 2.3.2.11 2000/05/22 06:57:50 darrenr Exp $
  */
 
 #ifndef	__IP_FIL_H__
 #define	__IP_FIL_H__
 
-#if defined(__NetBSD__) && defined(PFIL_HOOKS)
-#include "opt_pfil_hooks.h"
-#endif
-
 /*
  * Pathnames for various IP Filter control devices.  Used by LKM
  * and userland, so defined here.
@@ -26,11 +23,11 @@
 #define	IPAUTH_NAME	"/dev/ipauth"
 
 #ifndef	SOLARIS
-#define	SOLARIS	(defined(sun) && (defined(__svr4__) || defined(__SVR4)))
+# define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
 #endif
 
 #if defined(KERNEL) && !defined(_KERNEL)
-#define	_KERNEL
+# define	_KERNEL
 #endif
 
 #ifndef	__P
@@ -42,45 +39,45 @@
 #endif
 
 #if defined(__STDC__) || defined(__GNUC__)
-#define	SIOCADAFR	_IOW('r', 60, struct frentry)
-#define	SIOCRMAFR	_IOW('r', 61, struct frentry)
-#define	SIOCSETFF	_IOW('r', 62, u_int)
-#define	SIOCGETFF	_IOR('r', 63, u_int)
-#define	SIOCGETFS	_IOR('r', 64, struct friostat)
-#define	SIOCIPFFL	_IOWR('r', 65, int)
-#define	SIOCIPFFB	_IOR('r', 66, int)
-#define	SIOCADIFR	_IOW('r', 67, struct frentry)
-#define	SIOCRMIFR	_IOW('r', 68, struct frentry)
-#define	SIOCSWAPA	_IOR('r', 69, u_int)
-#define	SIOCINAFR	_IOW('r', 70, struct frentry)
-#define	SIOCINIFR	_IOW('r', 71, struct frentry)
-#define	SIOCFRENB	_IOW('r', 72, u_int)
-#define	SIOCFRSYN	_IOW('r', 73, u_int)
-#define	SIOCFRZST	_IOWR('r', 74, struct friostat)
-#define	SIOCZRLST	_IOWR('r', 75, struct frentry)
-#define	SIOCAUTHW	_IOWR('r', 76, struct fr_info)
-#define	SIOCAUTHR	_IOWR('r', 77, struct fr_info)
-#define	SIOCATHST	_IOWR('r', 78, struct fr_authstat)
+# define	SIOCADAFR	_IOW('r', 60, struct frentry)
+# define	SIOCRMAFR	_IOW('r', 61, struct frentry)
+# define	SIOCSETFF	_IOW('r', 62, u_int)
+# define	SIOCGETFF	_IOR('r', 63, u_int)
+# define	SIOCGETFS	_IOR('r', 64, struct friostat)
+# define	SIOCIPFFL	_IOWR('r', 65, int)
+# define	SIOCIPFFB	_IOR('r', 66, int)
+# define	SIOCADIFR	_IOW('r', 67, struct frentry)
+# define	SIOCRMIFR	_IOW('r', 68, struct frentry)
+# define	SIOCSWAPA	_IOR('r', 69, u_int)
+# define	SIOCINAFR	_IOW('r', 70, struct frentry)
+# define	SIOCINIFR	_IOW('r', 71, struct frentry)
+# define	SIOCFRENB	_IOW('r', 72, u_int)
+# define	SIOCFRSYN	_IOW('r', 73, u_int)
+# define	SIOCFRZST	_IOWR('r', 74, struct friostat)
+# define	SIOCZRLST	_IOWR('r', 75, struct frentry)
+# define	SIOCAUTHW	_IOWR('r', 76, struct fr_info)
+# define	SIOCAUTHR	_IOWR('r', 77, struct fr_info)
+# define	SIOCATHST	_IOWR('r', 78, struct fr_authstat)
 #else
-#define	SIOCADAFR	_IOW(r, 60, struct frentry)
-#define	SIOCRMAFR	_IOW(r, 61, struct frentry)
-#define	SIOCSETFF	_IOW(r, 62, u_int)
-#define	SIOCGETFF	_IOR(r, 63, u_int)
-#define	SIOCGETFS	_IOR(r, 64, struct friostat)
-#define	SIOCIPFFL	_IOWR(r, 65, int)
-#define	SIOCIPFFB	_IOR(r, 66, int)
-#define	SIOCADIFR	_IOW(r, 67, struct frentry)
-#define	SIOCRMIFR	_IOW(r, 68, struct frentry)
-#define	SIOCSWAPA	_IOR(r, 69, u_int)
-#define	SIOCINAFR	_IOW(r, 70, struct frentry)
-#define	SIOCINIFR	_IOW(r, 71, struct frentry)
-#define SIOCFRENB	_IOW(r, 72, u_int)
-#define	SIOCFRSYN	_IOW(r, 73, u_int)
-#define	SIOCFRZST	_IOWR(r, 74, struct friostat)
-#define	SIOCZRLST	_IOWR(r, 75, struct frentry)
-#define	SIOCAUTHW	_IOWR(r, 76, struct fr_info)
-#define	SIOCAUTHR	_IOWR(r, 77, struct fr_info)
-#define	SIOCATHST	_IOWR(r, 78, struct fr_authstat)
+# define	SIOCADAFR	_IOW(r, 60, struct frentry)
+# define	SIOCRMAFR	_IOW(r, 61, struct frentry)
+# define	SIOCSETFF	_IOW(r, 62, u_int)
+# define	SIOCGETFF	_IOR(r, 63, u_int)
+# define	SIOCGETFS	_IOR(r, 64, struct friostat)
+# define	SIOCIPFFL	_IOWR(r, 65, int)
+# define	SIOCIPFFB	_IOR(r, 66, int)
+# define	SIOCADIFR	_IOW(r, 67, struct frentry)
+# define	SIOCRMIFR	_IOW(r, 68, struct frentry)
+# define	SIOCSWAPA	_IOR(r, 69, u_int)
+# define	SIOCINAFR	_IOW(r, 70, struct frentry)
+# define	SIOCINIFR	_IOW(r, 71, struct frentry)
+# define	SIOCFRENB	_IOW(r, 72, u_int)
+# define	SIOCFRSYN	_IOW(r, 73, u_int)
+# define	SIOCFRZST	_IOWR(r, 74, struct friostat)
+# define	SIOCZRLST	_IOWR(r, 75, struct frentry)
+# define	SIOCAUTHW	_IOWR(r, 76, struct fr_info)
+# define	SIOCAUTHR	_IOWR(r, 77, struct fr_info)
+# define	SIOCATHST	_IOWR(r, 78, struct fr_authstat)
 #endif
 #define	SIOCADDFR	SIOCADAFR
 #define	SIOCDELFR	SIOCRMAFR
@@ -103,32 +100,43 @@
 #define	FI_TCPUDP	(FF_TCPUDP >> 24)	/* TCP/UCP implied comparison*/
 #define	FI_FRAG		(FF_FRAG >> 24)
 #define	FI_SHORT	(FF_SHORT >> 24)
+#define	FI_CMP		(FI_OPTIONS|FI_TCPUDP|FI_SHORT)
+
+/*
+ * These are both used by the state and NAT code to indicate that one port or
+ * the other should be treated as a wildcard.
+ */
+#define	FI_W_SPORT	0x00000100
+#define	FI_W_DPORT	0x00000200
+#define	FI_WILD		(FI_W_SPORT|FI_W_DPORT)
 
 typedef	struct	fr_info	{
+	void	*fin_ifp;		/* interface packet is `on' */
 	struct	fr_ip	fin_fi;		/* IP Packet summary */
 	u_short	fin_data[2];		/* TCP/UDP ports, ICMP code/type */
-	u_short	fin_out;		/* in or out ? 1 == out, 0 == in */
+	u_char	fin_out;		/* in or out ? 1 == out, 0 == in */
+	u_char	fin_rev;		/* state only: 1 = reverse */
 	u_short	fin_hlen;		/* length of IP header in bytes */
 	u_char	fin_tcpf;		/* TCP header flags (SYN, ACK, etc) */
 	/* From here on is packet specific */
 	u_char	fin_icode;		/* ICMP error to return */
 	u_short	fin_rule;		/* rule # last matched */
 	u_short	fin_group;		/* group number, -1 for none */
-	u_short	fin_dlen;		/* length of data portion of packet */
-	u_short	fin_id;			/* IP packet id field */
-	void	*fin_ifp;		/* interface packet is `on' */
 	struct	frentry *fin_fr;	/* last matching rule */
 	char	*fin_dp;		/* start of data past IP header */
+	u_short	fin_dlen;		/* length of data portion of packet */
+	u_short	fin_id;			/* IP packet id field */
 	void	*fin_mp;		/* pointer to pointer to mbuf */
 #if SOLARIS && defined(_KERNEL)
 	void	*fin_qfm;		/* pointer to mblk where pkt starts */
+	void	*fin_qif;
 #endif
 } fr_info_t;
 
 /*
  * Size for compares on fr_info structures
  */
-#define       FI_CSIZE        offsetof(fr_info_t, fin_icode)
+#define	FI_CSIZE	offsetof(fr_info_t, fin_icode)
 
 /*
  * Size for copying cache fr_info structure
@@ -148,6 +156,9 @@
 	struct	frentry	*fr_grp;
 	int	fr_ref;		/* reference count - for grouping */
 	void	*fr_ifa;
+#if BSD >= 199306
+	void	*fr_oifa;
+#endif
 	/*
 	 * These are only incremented when a packet  matches this rule and
 	 * it is the last match
@@ -173,10 +184,14 @@
 	u_short	fr_stop;	/* top port for <> and >< */
 	u_short	fr_dtop;	/* top port for <> and >< */
 	u_32_t	fr_flags;	/* per-rule flags && options (see below) */
-	int	fr_skip;	/* # of rules to skip */
+	u_short	fr_skip;	/* # of rules to skip */
+	u_short	fr_loglevel;	/* syslog log facility + priority */
 	int	(*fr_func) __P((int, ip_t *, fr_info_t *));	/* call this function */
-	char	fr_icode;	/* return ICMP code */
+	u_char	fr_icode;	/* return ICMP code */
 	char	fr_ifname[IFNAMSIZ];
+#if BSD >= 199306
+	char	fr_oifname[IFNAMSIZ];
+#endif
 	struct	frdest	fr_tif;	/* "to" interface */
 	struct	frdest	fr_dif;	/* duplicate packet interfaces */
 } frentry_t;
@@ -208,6 +223,7 @@
 #define	FR_LOGFIRST	0x00040	/* Log the first byte if state held */
 #define	FR_RETRST	0x00080	/* Return TCP RST packet - reset connection */
 #define	FR_RETICMP	0x00100	/* Return ICMP unreachable packet */
+#define	FR_FAKEICMP	0x00180	/* Return ICMP unreachable with fake source */
 #define	FR_NOMATCH	0x00200	/* no match occured */
 #define	FR_ACCOUNT	0x00400	/* count packet bytes */
 #define	FR_KEEPFRAG	0x00800	/* keep fragment information */
@@ -222,8 +238,10 @@
 #define	FR_NOTDSTIP	0x100000	/* not the dst IP# */
 #define	FR_AUTH		0x200000	/* use authentication */
 #define	FR_PREAUTH	0x400000	/* require preauthentication */
+#define	FR_DONTCACHE	0x800000	/* don't cache the result */
 
 #define	FR_LOGMASK	(FR_LOG|FR_LOGP|FR_LOGB)
+#define	FR_RETMASK	(FR_RETICMP|FR_RETRST|FR_FAKEICMP)
 
 /*
  * These correspond to #define's for FI_* and are stored in fr_flags
@@ -255,6 +273,7 @@
 	u_long	fr_pass;	/* packets allowed */
 	u_long	fr_block;	/* packets denied */
 	u_long	fr_nom;		/* packets which don't match any rule */
+	u_long	fr_short;	/* packets which are short */
 	u_long	fr_ppkl;	/* packets allowed and logged */
 	u_long	fr_bpkl;	/* packets denied and logged */
 	u_long	fr_npkl;	/* packets unmatched and logged */
@@ -276,6 +295,7 @@
 	u_long	fr_bad;		/* bad IP packets to the filter */
 	u_long	fr_notip;	/* packets passed through no on ip queue */
 	u_long	fr_drop;	/* packets dropped - no info for them! */
+	u_long	fr_copy;	/* messages copied due to db_ref > 1 */
 #endif
 } filterstats_t;
 
@@ -289,8 +309,17 @@
 	struct	frentry		*f_acctin[2];
 	struct	frentry		*f_acctout[2];
 	struct	frentry		*f_auth;
+	struct	frgroup		*f_groups[3][2];
 	u_long	f_froute[2];
-	int	f_active;
+	int	f_defpass;	/* default pass - from fr_pass */
+	char	f_active;	/* 1 or 0 - active rule set */
+	char	f_running;	/* 1 if running, else 0 */
+	char	f_logging;	/* 1 if enabled, else 0 */
+#if !SOLARIS && defined(sun)
+	char	f_version[17];	/* version string */
+#else
+	char	f_version[32];	/* version string */
+#endif
 } friostat_t;
 
 typedef struct	optlist {
@@ -316,11 +345,10 @@
  * structure which is then followed by any packet data.
  */
 typedef	struct	iplog	{
-	u_long	ipl_magic;
+	u_32_t	ipl_magic;
+	u_int	ipl_count;
 	u_long	ipl_sec;
 	u_long	ipl_usec;
-	u_int	ipl_len;
-	u_int	ipl_count;
 	size_t	ipl_dsize;
 	struct	iplog	*ipl_next;
 } iplog_t;
@@ -339,7 +367,9 @@
 	u_char	fl_hlen;	/* length of IP headers saved */
 	u_short	fl_rule;	/* assume never more than 64k rules, total */
 	u_short	fl_group;
+	u_short	fl_loglevel;	/* syslog log level */
 	u_32_t	fl_flags;
+	u_32_t	fl_lflags;
 } ipflog_t;
 
 
@@ -352,7 +382,6 @@
 #ifndef	IPF_LOGGING
 # define	IPF_LOGGING	0
 #endif
-
 #ifndef	IPF_DEFAULT_PASS
 # define	IPF_DEFAULT_PASS	FR_PASS
 #endif
@@ -386,16 +415,32 @@
 # define	CDEV_MAJOR	79
 #endif
 
+/*
+ * Post NetBSD 1.2 has the PFIL interface for packet filters.  This turns
+ * on those hooks.  We don't need any special mods in non-IP Filter code
+ * with this!
+ */
+#if (defined(NetBSD) && (NetBSD > 199609) && (NetBSD <= 1991011)) || \
+    (defined(NetBSD1_2) && NetBSD1_2 > 1)
+# if (NetBSD >= 199905)
+#  define PFIL_HOOKS
+# endif
+# ifdef PFIL_HOOKS
+#  define NETBSD_PF
+# endif
+#endif
+
+
 #ifndef	_KERNEL
 extern	int	fr_check __P((ip_t *, int, void *, int, mb_t **));
 extern	int	(*fr_checkp) __P((ip_t *, int, void *, int, mb_t **));
 extern	int	send_reset __P((ip_t *, struct ifnet *));
 extern	int	icmp_error __P((ip_t *, struct ifnet *));
 extern	int	ipf_log __P((void));
-extern	void	ipfr_fastroute __P((ip_t *, fr_info_t *, frdest_t *));
+extern	int	ipfr_fastroute __P((ip_t *, fr_info_t *, frdest_t *));
 extern	struct	ifnet *get_unit __P((char *));
-# define	FR_SCANLIST(p, ip, fi, m)	fr_scanlist(p, ip, fi, m)
-# if defined(__NetBSD__) || defined(__OpenBSD__) || (_BSDI_VERSION >= 199701)
+# if defined(__NetBSD__) || defined(__OpenBSD__) || \
+	  (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000)
 extern	int	iplioctl __P((dev_t, u_long, caddr_t, int));
 # else
 extern	int	iplioctl __P((dev_t, int, caddr_t, int));
@@ -404,39 +449,34 @@
 extern	int	iplclose __P((dev_t, int));
 #else /* #ifndef _KERNEL */
 # if defined(__NetBSD__) && defined(PFIL_HOOKS)
-extern	int	ipfilterattach __P((int));
+extern	void	ipfilterattach __P((int));
 # endif
-
-#if !defined(__OpenBSD__)
-/*
- * OpenBSD has this call in the kernel but doesn't export it to userland.
- * See ip_fil.c for actual hook and more details.
- */
 extern	int	iplattach __P((void));
-#endif
-
 extern	int	ipl_enable __P((void));
 extern	int	ipl_disable __P((void));
 extern	void	ipflog_init __P((void));
-extern	int	ipflog_clear __P((int));
-extern	int	ipflog_read __P((int, struct uio *));
+extern	int	ipflog_clear __P((minor_t));
+extern	int	ipflog_read __P((minor_t, struct uio *));
 extern	int	ipflog __P((u_int, ip_t *, fr_info_t *, mb_t *));
-extern	int	ipllog __P((int, u_long, void **, size_t *, int *, int));
+extern	int	ipllog __P((int, fr_info_t *, void **, size_t *, int *, int));
+extern	int	send_icmp_err __P((ip_t *, int, fr_info_t *, struct in_addr));
+extern	int	send_reset __P((ip_t *, fr_info_t *));
 # if	SOLARIS
 extern	int	fr_check __P((ip_t *, int, void *, int, qif_t *, mb_t **));
 extern	int	(*fr_checkp) __P((ip_t *, int, void *,
 				  int, qif_t *, mb_t **));
-extern	int	icmp_error __P((ip_t *, int, int, qif_t *,
-				struct in_addr));
-extern	int	iplioctl __P((dev_t, int, int, int, cred_t *, int *));
+#  if SOLARIS2 >= 7
+extern	int	iplioctl __P((dev_t, int, intptr_t, int, cred_t *, int *));
+#  else
+extern	int	iplioctl __P((dev_t, int, int *, int, cred_t *, int *));
+#  endif
 extern	int	iplopen __P((dev_t *, int, int, cred_t *));
 extern	int	iplclose __P((dev_t, int, int, cred_t *));
 extern	int	ipfsync __P((void));
-extern	int	send_reset __P((ip_t *, qif_t *));
 extern	int	ipfr_fastroute __P((qif_t *, ip_t *, mblk_t *, mblk_t **,
 				   fr_info_t *, frdest_t *));
-extern	void	copyin_mblk __P((mblk_t *, int, int, char *));
-extern	void	copyout_mblk __P((mblk_t *, int, int, char *));
+extern	void	copyin_mblk __P((mblk_t *, size_t, size_t, char *));
+extern	void	copyout_mblk __P((mblk_t *, size_t, size_t, char *));
 extern	int	fr_qin __P((queue_t *, mblk_t *));
 extern	int	fr_qout __P((queue_t *, mblk_t *));
 #  ifdef	IPFILTER_LOG
@@ -445,12 +485,7 @@
 # else /* SOLARIS */
 extern	int	fr_check __P((ip_t *, int, void *, int, mb_t **));
 extern	int	(*fr_checkp) __P((ip_t *, int, void *, int, mb_t **));
-#  ifdef	linux
-extern	int	send_reset __P((tcpiphdr_t *, struct ifnet *));
-#  else
-extern	int	send_reset __P((tcpiphdr_t *));
-#  endif
-extern	void	ipfr_fastroute __P((mb_t *, fr_info_t *, frdest_t *));
+extern	int	ipfr_fastroute __P((mb_t *, fr_info_t *, frdest_t *));
 extern	size_t	mbufchainlen __P((mb_t *));
 #  ifdef	__sgi
 #   include <sys/cred.h>
@@ -468,67 +503,65 @@
 #   endif
 #   if (_BSDI_VERSION >= 199510) || (__FreeBSD_version >= 220000) || \
       (NetBSD >= 199511) || defined(__OpenBSD__)
-#    if defined(__NetBSD__) || (_BSDI_VERSION >= 199701) || defined(__OpenBSD__)
+#    if defined(__NetBSD__) || (_BSDI_VERSION >= 199701) || \
+       defined(__OpenBSD__) || (__FreeBSD_version >= 300000)
 extern	int	iplioctl __P((dev_t, u_long, caddr_t, int, struct proc *));
-#    else /* FreeBSD v2.2+ or BSDI >= 199510 and < 199701 */
+#    else
 extern	int	iplioctl __P((dev_t, int, caddr_t, int, struct proc *));
-#    endif /* NetBSD, modern BSDI and OpenBSD */
+#    endif
 extern	int	iplopen __P((dev_t, int, int, struct proc *));
 extern	int	iplclose __P((dev_t, int, int, struct proc *));
-#   else /* everybody else */
-#     ifdef	linux
-extern 	int	iplioctl(struct inode *, struct file *, u_int, u_long);
-extern	int	iplopen __P((struct inode *, struct file *));
-extern	void	iplclose __P((struct inode *, struct file *));
-      else
-extern	int	iplioctl __P((dev_t, int, caddr_t, int));
+#   else
+#    ifndef	linux
 extern	int	iplopen __P((dev_t, int));
 extern	int	iplclose __P((dev_t, int));
-#     endif /* linux */
+extern	int	iplioctl __P((dev_t, int, caddr_t, int));
+#    else
+extern	int	iplioctl(struct inode *, struct file *, u_int, u_long);
+extern	int	iplopen __P((struct inode *, struct file *));
+extern	void	iplclose __P((struct inode *, struct file *));
+#    endif /* !linux */
 #   endif /* (_BSDI_VERSION >= 199510) */
 #   if	BSD >= 199306
 extern	int	iplread __P((dev_t, struct uio *, int));
 #   else
-#    ifdef linux
-extern	int	iplread(struct inode *, struct file *, char *, int);
-     else
+#    ifndef linux
 extern	int	iplread __P((dev_t, struct uio *));
-#    endif /* linux */
+#    else
+extern	int	iplread(struct inode *, struct file *, char *, int);
+#    endif /* !linux */
 #   endif /* BSD >= 199306 */
 #  endif /* __ sgi */
 # endif /* SOLARIS */
 #endif /* #ifndef _KERNEL */
-
-/*
- * Post NetBSD 1.2 has the PFIL interface for packet filters.  This turns
- * on those hooks.  We don't need any special mods in non-IP Filter code
- * with this!
- */
-#if (defined(NetBSD) && (NetBSD > 199609) && (NetBSD <= 1991011)) || \
-    (defined(NetBSD1_2) && NetBSD1_2 > 1)
-# define NETBSD_PF
-#endif
 
+extern	void	fixskip __P((frentry_t **, frentry_t *, int));
+extern	int	countbits __P((u_32_t));
 extern	int	ipldetach __P((void));
-extern	u_short	fr_tcpsum __P((mb_t *, ip_t *, tcphdr_t *, int));
-#define	FR_SCANLIST(p, ip, fi, m)	fr_scanlist(p, ip, fi, m)
-extern	int	fr_scanlist __P((int, ip_t *, fr_info_t *, void *));
+extern	u_short	fr_tcpsum __P((mb_t *, ip_t *, tcphdr_t *));
+extern	int	fr_scanlist __P((u_32_t, ip_t *, fr_info_t *, void *));
 extern	u_short	ipf_cksum __P((u_short *, int));
 extern	int	fr_copytolog __P((int, char *, int));
-extern	void	frflush __P((int, int *));
-extern	frgroup_t *fr_addgroup __P((u_short, frentry_t *, int, int));
-extern	frgroup_t *fr_findgroup __P((u_short, u_32_t, int, int, frgroup_t ***));
-extern	void	fr_delgroup __P((u_short, u_32_t, int, int));
+extern	void	fr_forgetifp __P((void *));
+extern	int	frflush __P((minor_t, int));
+extern	void	frsync __P((void));
+extern	frgroup_t *fr_addgroup __P((u_int, frentry_t *, minor_t, int));
+extern	frgroup_t *fr_findgroup __P((u_int, u_32_t, minor_t, int, frgroup_t ***));
+extern	void	fr_delgroup __P((u_int, u_32_t, minor_t, int));
+extern  void	fr_makefrip __P((int, ip_t *, fr_info_t *));
+extern	int	fr_ifpaddr __P((void *, struct in_addr *));
+extern	char	*memstr __P((char *, char *, int, int));
 extern	int	ipl_unreach;
-extern	int	ipl_inited;
+extern	int	fr_running;
 extern	u_long	ipl_frouteok[2];
 extern	int	fr_pass;
 extern	int	fr_flags;
 extern	int	fr_active;
 extern	fr_info_t	frcache[2];
+extern	char	ipfilter_version[];
 #ifdef	IPFILTER_LOG
 extern	iplog_t	**iplh[IPL_LOGMAX+1], *iplt[IPL_LOGMAX+1];
-extern	int	iplused[IPL_LOGMAX + 1];
+extern	size_t	iplused[IPL_LOGMAX + 1];
 #endif
 extern	struct frentry *ipfilter[2][2], *ipacct[2][2];
 extern	struct frgroup *ipfgroups[3][2];
Index: sys/netinet/ip_fil.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_fil.c,v
retrieving revision 1.24
retrieving revision 1.35
diff -u -r1.24 -r1.35
--- sys/netinet/ip_fil.c	1999/06/07 22:00:32	1.24
+++ sys/netinet/ip_fil.c	2000/05/24 21:59:11	1.35
@@ -1,4 +1,5 @@
-/*    $OpenBSD: ip_fil.c,v 1.24 1999/06/07 22:00:32 deraadt Exp $    */
+/*	$OpenBSD: ip_fil.c,v 1.35 2000/05/24 21:59:11 kjell Exp $	*/
+
 /*
  * Copyright (C) 1993-1998 by Darren Reed.
  *
@@ -8,7 +9,7 @@
  */
 #if !defined(lint)
 static const char sccsid[] = "@(#)ip_fil.c	2.41 6/5/96 (C) 1993-1995 Darren Reed";
-static const char rcsid[] = "@(#)$Id: ip_fil.c,v 1.24 1999/06/07 22:00:32 deraadt Exp $";
+static const char rcsid[] = "@(#)$IPFilter: ip_fil.c,v 2.4.2.21 2000/05/22 06:57:47 darrenr Exp $";
 #endif
 
 #ifndef	SOLARIS
@@ -18,6 +19,11 @@
 #if defined(KERNEL) && !defined(_KERNEL)
 # define	_KERNEL
 #endif
+#include <sys/param.h>
+#if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \
+    defined(_KERNEL)
+# include "opt_ipfilter_log.h"
+#endif
 #ifdef	__FreeBSD__
 # if defined(_KERNEL) && !defined(IPFILTER_LKM)
 #  include <sys/osreldate.h>
@@ -30,10 +36,10 @@
 # include <string.h>
 # include <stdlib.h>
 # include <ctype.h>
+# include <fcntl.h>
 #endif
 #include <sys/errno.h>
 #include <sys/types.h>
-#include <sys/param.h>
 #include <sys/file.h>
 #if __FreeBSD_version >= 220000 && defined(_KERNEL)
 # include <sys/fcntl.h>
@@ -47,7 +53,7 @@
 #endif
 #include <sys/uio.h>
 #if !SOLARIS
-# if (NetBSD > 199609) || (OpenBSD > 199603)
+# if (NetBSD > 199609) || (OpenBSD > 199603) || (__FreeBSD_version >= 300000)
 #  include <sys/dirent.h>
 # else
 #  include <sys/dir.h>
@@ -65,6 +71,9 @@
 #endif
 #if __FreeBSD_version >= 300000
 # include <net/if_var.h>
+# if defined(_KERNEL) && !defined(IPFILTER_LKM)
+#  include "opt_ipfilter.h"
+# endif
 #endif
 #ifdef __sgi
 #include <sys/debug.h>
@@ -75,7 +84,7 @@
 #include <net/route.h>
 #include <netinet/in.h>
 #if !(defined(__sgi) && !defined(IFF_DRVRLOCK)) /* IRIX < 6 */
-#include <netinet/in_var.h>
+# include <netinet/in_var.h>
 #endif
 #include <netinet/in_systm.h>
 #include <netinet/ip.h>
@@ -85,23 +94,24 @@
 #include <netinet/tcpip.h>
 #include <netinet/ip_icmp.h>
 #ifndef	_KERNEL
+# include <unistd.h>
 # include <syslog.h>
 #endif
-#if defined(__OpenBSD__)
 #include <netinet/ip_fil_compat.h>
-#else
-#include <netinet/ip_compat.h>
-#endif
 #include <netinet/ip_fil.h>
 #include <netinet/ip_proxy.h>
 #include <netinet/ip_nat.h>
 #include <netinet/ip_frag.h>
 #include <netinet/ip_state.h>
 #include <netinet/ip_auth.h>
+#if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
+# include <sys/malloc.h>
+#endif
 #ifndef	MIN
-#define	MIN(a,b)	(((a)<(b))?(a):(b))
+# define	MIN(a,b)	(((a)<(b))?(a):(b))
 #endif
-#if	!SOLARIS && defined(_KERNEL)
+#if !SOLARIS && defined(_KERNEL) && !defined(__sgi)
+# include <sys/kernel.h>
 extern	int	ip_optcopy __P((struct ip *, struct ip *));
 #endif
 
@@ -113,27 +123,20 @@
 static	struct	ifnet **ifneta = NULL;
 static	int	nifs = 0;
 #else
-# if	(BSD < 199306) && !defined(__sgi)
-static	int	(*fr_saveslowtimo) __P((void));
-# else
-static	void	(*fr_saveslowtimo) __P((void));
-# endif
 # if	(BSD < 199306) || defined(__sgi)
 extern	int	tcp_ttl;
 # endif
 #endif
 
-int	ipl_inited = 0;
-#if defined(__OpenBSD__)
+# if defined (__OpenBSD__)
 int	ipl_unreach = ICMP_UNREACH_FILTER_PROHIB;
-#else
+# else
 int	ipl_unreach = ICMP_UNREACH_FILTER;
-#endif
+# endif
+
 u_long	ipl_frouteok[2] = {0, 0};
 
-static	void	fixskip __P((frentry_t **, frentry_t *, int));
 static	void	frzerostats __P((caddr_t));
-static	void	frsync __P((void));
 #if defined(__NetBSD__) || defined(__OpenBSD__)
 static	int	frrequest __P((int, u_long, caddr_t, int));
 #else
@@ -141,8 +144,10 @@
 #endif
 #ifdef	_KERNEL
 static	int	(*fr_savep) __P((ip_t *, int, void *, int, struct mbuf **));
+static	int	send_ip __P((ip_t *, fr_info_t *, struct mbuf *));
 # ifdef	__sgi
 extern  kmutex_t        ipf_rw;
+extern	KRWLOCK_T	ipf_mutex;
 # endif
 #else
 int	ipllog __P((void));
@@ -159,7 +164,12 @@
 				  struct sockaddr *, struct rtentry *));
 # endif
 #endif
+int	fr_running = 0;
 
+#if (__FreeBSD_version >= 300000) && defined(_KERNEL)
+struct callout_handle ipfr_slowtimer_ch;
+#endif
+
 #if (_BSDI_VERSION >= 199510) && defined(_KERNEL)
 # include <sys/device.h>
 # include <sys/conf.h>
@@ -207,61 +217,68 @@
 ipfilterattach(count)
 int count;
 {
-	iplattach();
+	if (iplattach() != 0)
+		printf("IP Filter failed to attach\n");
 }
 # endif
 
-#if defined( __OpenBSD__)
-/*
- * Since iplattach() is called by main() at boot time, we put in a 
- * fake stub so that none of the machinery is initialized till explicitly
- * enabled via ipf -E. Therefore we rename the real iplattach() to 
- * ipl_enable(). See also skeleton iplinit() later in this file. 
- */
-void iplattach __P((int));
-void iplattach(int dummy) {};
 
-int ipl_enable()
-# else
 int iplattach()
-# endif /* OpenBSD */
 {
 	char *defpass;
 	int s;
-# ifdef __sgi
-	int error;
+# if defined(__sgi) || (defined(NETBSD_PF) && (__NetBSD_Version__ >= 104200000))
+	int error = 0;
 # endif
 
 	SPL_NET(s);
-	if (ipl_inited || (fr_checkp == fr_check)) {
+	if (fr_running || (fr_checkp == fr_check)) {
 		printf("IP Filter: already initialized\n");
 		SPL_X(s);
 		return EBUSY;
 	}
 
+# ifdef	IPFILTER_LOG
+	ipflog_init();
+# endif
+	if (nat_init() == -1)
+		return -1;
+	if (fr_stateinit() == -1)
+		return -1;
+	if (appr_init() == -1)
+		return -1;
+
 # ifdef NETBSD_PF
+#  if __NetBSD_Version__ >= 104200000
+	error = pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT,
+			      &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
+	if (error) {
+		appr_unload();
+		ip_natunload();
+		fr_stateunload();
+		return error;
+	}
+#  else
 	pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT);
+#  endif
 # endif
 
 # ifdef __sgi
 	error = ipfilter_sgi_attach();
 	if (error) {
 		SPL_X(s);
+		appr_unload();
+		ip_natunload();
+		fr_stateunload();
 		return error;
 	}
 # endif
 
-	ipl_inited = 1;
 	bzero((char *)frcache, sizeof(frcache));
-	bzero((char *)nat_table, sizeof(nat_table));
 	fr_savep = fr_checkp;
 	fr_checkp = fr_check;
-	fr_saveslowtimo = inetsw[0].pr_slowtimo;
-	inetsw[0].pr_slowtimo = ipfr_slowtimer;
+	fr_running = 1;
 
-# ifdef	IPFILTER_LOG
-	ipflog_init();
-# endif
 	SPL_X(s);
 	if (fr_pass & FR_PASS)
 		defpass = "pass";
@@ -270,6 +287,7 @@
 	else
 		defpass = "no-match -> block";
 
+#if !defined(__OpenBSD__)
 	printf("IP Filter: initialized.  Default = %s all, Logging = %s\n",
 		defpass,
 # ifdef	IPFILTER_LOG
@@ -277,6 +295,16 @@
 # else
 		"disabled");
 # endif
+	printf("%s\n", ipfilter_version);
+#endif
+
+#ifdef	_KERNEL
+# if (__FreeBSD_version >= 300000) && defined(_KERNEL)
+	ipfr_slowtimer_ch = timeout(ipfr_slowtimer, NULL, hz/2);
+# else
+	timeout(ipfr_slowtimer, NULL, hz/2);
+# endif
+#endif
 	return 0;
 }
 
@@ -285,16 +313,26 @@
  * Disable the filter by removing the hooks from the IP input/output
  * stream.
  */
-# if defined(__OpenBSD__)
-int ipl_disable()
-# else
 int ipldetach()
-# endif
 {
 	int s, i = FR_INQUE|FR_OUTQUE;
+#if defined(NETBSD_PF) && (__NetBSD_Version__ >= 104200000)
+	int error = 0;
+#endif
 
+#ifdef	_KERNEL
+# if (__FreeBSD_version >= 300000)
+	untimeout(ipfr_slowtimer, NULL, ipfr_slowtimer_ch);
+# else
+#  ifdef __sgi
+	untimeout(ipfr_slowtimer);
+#  else
+	untimeout(ipfr_slowtimer, NULL);
+#  endif
+# endif
+#endif
 	SPL_NET(s);
-	if (!ipl_inited)
+	if (!fr_running)
 	{
 		printf("IP Filter: not initialized\n");
 		SPL_X(s);
@@ -302,18 +340,25 @@
 	}
 
 	fr_checkp = fr_savep;
-	inetsw[0].pr_slowtimo = fr_saveslowtimo;
-	frflush(IPL_LOGIPF, &i);
-	ipl_inited = 0;
+	i = frflush(IPL_LOGIPF, i);
+	fr_running = 0;
 
 # ifdef NETBSD_PF
+#  if __NetBSD_Version__ >= 104200000
+	error = pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT,
+			      &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
+	if (error)
+		return error;
+#  else
 	pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT);
+#  endif
 # endif
 
 # ifdef __sgi
 	ipfilter_sgi_detach();
 # endif
 
+	appr_unload();
 	ipfr_unload();
 	ip_natunload();
 	fr_stateunload();
@@ -328,7 +373,7 @@
 static	void	frzerostats(data)
 caddr_t	data;
 {
-	struct	friostat	fio;
+	friostat_t fio;
 
 	bcopy((char *)frstats, (char *)fio.f_st,
 		sizeof(struct filterstats) * 2);
@@ -367,7 +412,8 @@
 )
 #endif
 dev_t dev;
-#if defined(__NetBSD__) || defined(__OpenBSD__) || (_BSDI_VERSION >= 199701)
+#if defined(__NetBSD__) || defined(__OpenBSD__) || \
+	 (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000)
 u_long cmd;
 #else
 int cmd;
@@ -381,12 +427,17 @@
 #endif
 	int error = 0, unit = 0, tmp;
 
+#if (BSD >= 199306) && defined(_KERNEL)
+	if ((securelevel >= 2) && (mode & FWRITE))
+		return EPERM;
+#endif
 #ifdef	_KERNEL
 	unit = GET_MINOR(dev);
 	if ((IPL_LOGMAX < unit) || (unit < 0))
 		return ENXIO;
 
 # if defined(__OpenBSD__)
+       	/* Prevent IPF and NAT changes when securelevel > 1 */
 	if (securelevel > 1) {
 		switch (cmd) {
 #  ifndef IPFILTER_LKM
@@ -414,17 +465,26 @@
 		}
 	}
 # endif /* OpenBSD */
-#endif /* _KERNEL */
+#else /* _KERNEL */
+	unit = dev;
+#endif
 
 	SPL_NET(s);
 
 	if (unit == IPL_LOGNAT) {
-		error = nat_ioctl(data, cmd, mode);
+		if (fr_running)
+			error = nat_ioctl(data, cmd, mode);
+		else
+			error = EIO;
 		SPL_X(s);
 		return error;
 	}
+
 	if (unit == IPL_LOGSTATE) {
-		error = fr_state_ioctl(data, cmd, mode);
+		if (fr_running)
+			error = fr_state_ioctl(data, cmd, mode);
+		else
+			error = EIO;
 		SPL_X(s);
 		return error;
 	}
@@ -446,15 +506,9 @@
 		else {
 			IRCOPY(data, (caddr_t)&enable, sizeof(enable));
 			if (enable)
-# if defined(__OpenBSD__)
-				error = ipl_enable();
-			else
-				error = ipl_disable();
-# else
 				error = iplattach();
 			else
 				error = ipldetach();
-# endif /* OpenBSD */
 		}
 		break;
 	}
@@ -512,6 +566,21 @@
 		fio.f_active = fr_active;
 		fio.f_froute[0] = ipl_frouteok[0];
 		fio.f_froute[1] = ipl_frouteok[1];
+		fio.f_running = fr_running;
+		fio.f_groups[0][0] = ipfgroups[0][0];
+		fio.f_groups[0][1] = ipfgroups[0][1];
+		fio.f_groups[1][0] = ipfgroups[1][0];
+		fio.f_groups[1][1] = ipfgroups[1][1];
+		fio.f_groups[2][0] = ipfgroups[2][0];
+		fio.f_groups[2][1] = ipfgroups[2][1];
+#ifdef	IPFILTER_LOG
+		fio.f_logging = 1;
+#else
+		fio.f_logging = 0;
+#endif
+		fio.f_defpass = fr_pass;
+		strncpy(fio.f_version, ipfilter_version,
+			sizeof(fio.f_version));
 		IWCOPY((caddr_t)&fio, data, sizeof(fio));
 		break;
 	}
@@ -526,7 +595,7 @@
 			error = EPERM;
 		else {
 			IRCOPY(data, (caddr_t)&tmp, sizeof(tmp));
-			frflush(unit, &tmp);
+			tmp = frflush(unit, tmp);
 			IWCOPY((caddr_t)&tmp, data, sizeof(tmp));
 		}
 		break;
@@ -568,38 +637,27 @@
 	return error;
 }
 
-
-static void frsync()
-{
-#ifdef _KERNEL
-	struct ifnet *ifp;
-
-# if defined(__OpenBSD__) || (NetBSD >= 199511)
-	for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next)
-# else
-	for (ifp = ifnet; ifp; ifp = ifp->if_next)
-# endif
-		ip_natsync(ifp);
-#endif
-}
-
 
-static void fixskip(listp, rp, addremove)
-frentry_t **listp, *rp;
-int addremove;
+void fr_forgetifp(ifp)
+void *ifp;
 {
-	frentry_t *fp;
-	int rules = 0, rn = 0;
+	register frentry_t *f;
 
-	for (fp = *listp; fp && (fp != rp); fp = fp->fr_next, rules++)
-		;
-
-	if (!fp)
-		return;
-
-	for (fp = *listp; fp && (fp != rp); fp = fp->fr_next, rn++)
-		if (fp->fr_skip && (rn + fp->fr_skip >= rules))
-			fp->fr_skip += addremove;
+	WRITE_ENTER(&ipf_mutex);
+	for (f = ipacct[0][fr_active]; (f != NULL); f = f->fr_next)
+		if (f->fr_ifa == ifp)
+			f->fr_ifa = (void *)-1;
+	for (f = ipacct[1][fr_active]; (f != NULL); f = f->fr_next)
+		if (f->fr_ifa == ifp)
+			f->fr_ifa = (void *)-1;
+	for (f = ipfilter[0][fr_active]; (f != NULL); f = f->fr_next)
+		if (f->fr_ifa == ifp)
+			f->fr_ifa = (void *)-1;
+	for (f = ipfilter[1][fr_active]; (f != NULL); f = f->fr_next)
+		if (f->fr_ifa == ifp)
+			f->fr_ifa = (void *)-1;
+	RWLOCK_EXIT(&ipf_mutex);
+	ip_natsync(ifp);
 }
 
 
@@ -618,20 +676,22 @@
 	frentry_t frd;
 	frdest_t *fdp;
 	frgroup_t *fg = NULL;
-	int error = 0, in, group;
+	int error = 0, in;
+	u_int group;
 
 	fp = &frd;
 	IRCOPY(data, (caddr_t)fp, sizeof(*fp));
+	fp->fr_ref = 0;
 
 	/*
 	 * Check that the group number does exist and that if a head group
 	 * has been specified, doesn't exist.
 	 */
-	if (fp->fr_grhead &&
-	    fr_findgroup(fp->fr_grhead, fp->fr_flags, unit, set, NULL))
+	if ((req != SIOCZRLST) && fp->fr_grhead &&
+	    fr_findgroup((u_int)fp->fr_grhead, fp->fr_flags, unit, set, NULL))
 		return EEXIST;
-	if (fp->fr_group &&
-	    !fr_findgroup(fp->fr_group, fp->fr_flags, unit, set, NULL))
+	if ((req != SIOCZRLST) && fp->fr_group &&
+	    !fr_findgroup((u_int)fp->fr_group, fp->fr_flags, unit, set, NULL))
 		return ESRCH;
 
 	in = (fp->fr_flags & FR_INQUE) ? 0 : 1;
@@ -658,6 +718,13 @@
 		if (!fp->fr_ifa)
 			fp->fr_ifa = (void *)-1;
 	}
+#if BSD >= 199306
+	if (*fp->fr_oifname) {
+		fp->fr_oifa = GETUNIT(fp->fr_oifname);
+		if (!fp->fr_oifa)
+			fp->fr_oifa = (void *)-1;
+	}
+#endif
 
 	fdp = &fp->fr_dif;
 	fp->fr_flags &= ~FR_DUP;
@@ -698,14 +765,14 @@
 	}
 
 	if (!f) {
-		ftail = fprev;
-		if (req != SIOCINAFR && req != SIOCINIFR)
-			while ((f = *ftail))
-				ftail = &f->fr_next;
-		else if (fp->fr_hits)
-			while (--fp->fr_hits && (f = *ftail))
-				ftail = &f->fr_next;
-		f = NULL;
+		if (req == SIOCINAFR || req == SIOCINIFR) {
+			ftail = fprev;
+			if (fp->fr_hits) {
+				while (--fp->fr_hits && (f = *ftail))
+					ftail = &f->fr_next;
+			}
+			f = NULL;
+		}
 	}
 
 	if (req == SIOCDELFR || req == SIOCRMIFR) {
@@ -719,8 +786,8 @@
 			if (unit == IPL_LOGAUTH)
 				return fr_auth_ioctl(data, req, f, ftail);
 			if (f->fr_grhead)
-				fr_delgroup(f->fr_grhead, fp->fr_flags, unit,
-					    set);
+				fr_delgroup((u_int)f->fr_grhead, fp->fr_flags,
+					    unit, set);
 			fixskip(fprev, f, -1);
 			*ftail = f->fr_next;
 			KFREE(f);
@@ -730,8 +797,8 @@
 			error = EEXIST;
 		else {
 			if (unit == IPL_LOGAUTH)
-				return fr_auth_ioctl(data, req, f, ftail);
-			KMALLOC(f, frentry_t *, sizeof(*f));
+				return fr_auth_ioctl(data, req, fp, ftail);
+			KMALLOC(f, frentry_t *);
 			if (f != NULL) {
 				if (fg && fg->fg_head)
 					fg->fg_head->fr_ref++;
@@ -757,33 +824,33 @@
 /*
  * routines below for saving IP headers to buffer
  */
-#ifdef __sgi
-# ifdef _KERNEL
+# ifdef __sgi
+#  ifdef _KERNEL
 int IPL_EXTERN(open)(dev_t *pdev, int flags, int devtype, cred_t *cp)
-# else
+#  else
 int IPL_EXTERN(open)(dev_t dev, int flags)
-# endif
-#else
+#  endif
+# else
 int IPL_EXTERN(open)(dev, flags
-# if ((_BSDI_VERSION >= 199510) || (BSD >= 199506) || (NetBSD >= 199511) || \
+#  if ((_BSDI_VERSION >= 199510) || (BSD >= 199506) || (NetBSD >= 199511) || \
      (__FreeBSD_version >= 220000) || defined(__OpenBSD__)) && defined(_KERNEL)
 , devtype, p)
 int devtype;
 struct proc *p;
-# else
+#  else
 )
-# endif
+#  endif
 dev_t dev;
 int flags;
-#endif /* __sgi */
+# endif /* __sgi */
 {
-#if defined(__sgi) && defined(_KERNEL)
+# if defined(__sgi) && defined(_KERNEL)
 	u_int min = geteminor(*pdev);
-#else
+# else
 	u_int min = GET_MINOR(dev);
-#endif
+# endif
 
-	if (2 < min)
+	if (IPL_LOGMAX < min)
 		min = ENXIO;
 	else
 		min = 0;
@@ -791,25 +858,25 @@
 }
 
 
-#ifdef __sgi
+# ifdef __sgi
 int IPL_EXTERN(close)(dev_t dev, int flags, int devtype, cred_t *cp)
 #else
 int IPL_EXTERN(close)(dev, flags
-# if ((_BSDI_VERSION >= 199510) || (BSD >= 199506) || (NetBSD >= 199511) || \
+#  if ((_BSDI_VERSION >= 199510) || (BSD >= 199506) || (NetBSD >= 199511) || \
      (__FreeBSD_version >= 220000) || defined(__OpenBSD__)) && defined(_KERNEL)
 , devtype, p)
 int devtype;
 struct proc *p;
-# else
+#  else
 )
-# endif
+#  endif
 dev_t dev;
 int flags;
-#endif /* __sgi */
+# endif /* __sgi */
 {
 	u_int	min = GET_MINOR(dev);
 
-	if (2 < min)
+	if (IPL_LOGMAX < min)
 		min = ENXIO;
 	else
 		min = 0;
@@ -822,9 +889,9 @@
  * called during packet processing and cause an inconsistancy to appear in
  * the filter lists.
  */
-#ifdef __sgi
+# ifdef __sgi
 int IPL_EXTERN(read)(dev_t dev, uio_t *uio, cred_t *crp)
-#else
+# else
 #  if BSD >= 199306
 int IPL_EXTERN(read)(dev, uio, ioflag)
 int ioflag;
@@ -833,13 +900,13 @@
 #  endif
 dev_t dev;
 register struct uio *uio;
-#endif /* __sgi */
+# endif /* __sgi */
 {
-#  ifdef IPFILTER_LOG
+# ifdef IPFILTER_LOG
 	return ipflog_read(GET_MINOR(dev), uio);
-#  else
+# else
 	return ENXIO;
-#  endif
+# endif
 }
 
 
@@ -847,77 +914,155 @@
  * send_reset - this could conceivably be a call to tcp_respond(), but that
  * requires a large amount of setting up and isn't any more efficient.
  */
-int send_reset(ti)
-struct tcpiphdr *ti;
+int send_reset(oip, fin)
+struct ip *oip;
+fr_info_t *fin;
 {
-	struct tcpiphdr *tp;
-	struct tcphdr *tcp;
+	struct tcphdr *tcp, *tcp2;
 	struct mbuf *m;
-	int tlen = 0, err;
+	int tlen = 0;
 	ip_t *ip;
-# if defined(__FreeBSD_version) && (__FreeBSD_version >= 220000)
-	struct route ro;
-# endif
 
-	if (ti->ti_flags & TH_RST)
+	tcp = (struct tcphdr *)fin->fin_dp;
+	if (tcp->th_flags & TH_RST)
 		return -1;		/* feedback loop */
 # if	(BSD < 199306) || defined(__sgi)
 	m = m_get(M_DONTWAIT, MT_HEADER);
 # else
 	m = m_gethdr(M_DONTWAIT, MT_HEADER);
-	m->m_data += max_linkhdr;
 # endif
 	if (m == NULL)
+		return ENOBUFS;
+	if (m == NULL)
 		return -1;
 
-	if (ti->ti_flags & TH_SYN)
+	if (tcp->th_flags & TH_SYN)
 		tlen = 1;
-	m->m_len = sizeof (struct tcpiphdr);
+	m->m_len = sizeof(*tcp2) + sizeof(*ip);
 # if	BSD >= 199306
-	m->m_pkthdr.len = sizeof (struct tcpiphdr);
+	m->m_data += max_linkhdr;
+	m->m_pkthdr.len = sizeof(*tcp2) + sizeof(*ip);
 	m->m_pkthdr.rcvif = (struct ifnet *)0;
 # endif
-	bzero(mtod(m, char *), sizeof(struct tcpiphdr));
 	ip = mtod(m, struct ip *);
-	tp = mtod(m, struct tcpiphdr *);
-	tcp = (struct tcphdr *)((char *)ip + sizeof(struct ip));
+	bzero((char *)ip, sizeof(*tcp2) + sizeof(*ip));
+	tcp2 = (struct tcphdr *)(ip + 1);
+
+	ip->ip_src.s_addr = oip->ip_dst.s_addr;
+	ip->ip_dst.s_addr = oip->ip_src.s_addr;
+	tcp2->th_dport = tcp->th_sport;
+	tcp2->th_sport = tcp->th_dport;
+	tcp2->th_ack = ntohl(tcp->th_seq);
+	tcp2->th_ack += tlen;
+	tcp2->th_ack = htonl(tcp2->th_ack);
+	tcp2->th_off = sizeof(*tcp2) >> 2;
+	tcp2->th_flags = TH_RST|TH_ACK;
+	ip->ip_p = IPPROTO_TCP;
+	ip->ip_len = htons(sizeof(struct tcphdr));
+	tcp2->th_sum = in_cksum(m, sizeof(*ip) + sizeof(*tcp2));
+
+	ip->ip_id = oip->ip_id;
+	ip->ip_tos = oip->ip_tos;
+	ip->ip_len = sizeof(*ip) + sizeof(*tcp2);
+
+	return send_ip(ip, fin, m);
+}
+
 
-	ip->ip_src.s_addr = ti->ti_dst.s_addr;
-	ip->ip_dst.s_addr = ti->ti_src.s_addr;
-	tcp->th_dport = ti->ti_sport;
-	tcp->th_sport = ti->ti_dport;
-	tcp->th_ack = htonl(ntohl(ti->ti_seq) + tlen);
-	tcp->th_off = sizeof(struct tcphdr) >> 2;
-	tcp->th_flags = TH_RST|TH_ACK;
-	tp->ti_pr = ((struct ip *)ti)->ip_p;
-	tp->ti_len = htons(sizeof(struct tcphdr));
-	tcp->th_sum = in_cksum(m, sizeof(struct tcpiphdr));
-
-	ip->ip_tos = ((struct ip *)ti)->ip_tos;
-	ip->ip_p = ((struct ip *)ti)->ip_p;
-	ip->ip_len = sizeof (struct tcpiphdr);
+static int send_ip(ip, fin, m)
+fr_info_t *fin;
+struct mbuf *m;
+ip_t *ip;
+{
+	ip->ip_v = IPVERSION;
+	ip->ip_hl = (sizeof(*ip) >> 2);
 # if (BSD < 199306) || defined(__sgi)
 	ip->ip_ttl = tcp_ttl;
 # else
 	ip->ip_ttl = ip_defttl;
 # endif
+
+# ifdef	IPSEC
+	m->m_pkthdr.rcvif = NULL;
+# endif
+	return ipfr_fastroute(m, fin, NULL);
+}
+
+
+int send_icmp_err(oip, type, fin, dst)
+ip_t *oip;
+int type;
+fr_info_t *fin;
+struct in_addr dst;
+{
+	struct icmp *icmp;
+	struct mbuf *m;
+	ip_t *nip;
+	int code;
+
+	if ((oip->ip_p == IPPROTO_ICMP) && !(fin->fin_fi.fi_fl & FI_SHORT))
+		switch (ntohs(fin->fin_data[0]) >> 8)
+		{
+		case ICMP_ECHO :
+		case ICMP_TSTAMP :
+		case ICMP_IREQ :
+		case ICMP_MASKREQ :
+			break;
+		default :
+			return 0;
+		}
 
-# if defined(__FreeBSD_version) && (__FreeBSD_version >= 220000)
-	bzero((char *)&ro, sizeof(ro));
-	err = ip_output(m, (struct mbuf *)0, &ro, 0, 0);
-	if (ro.ro_rt)
-		RTFREE(ro.ro_rt);
+	code = fin->fin_icode;
+# if	(BSD < 199306) || defined(__sgi)
+	m = m_get(M_DONTWAIT, MT_HEADER);
 # else
-	/*
-	 * extra 0 in case of multicast
-	 */
-#  ifdef __OpenBSD__
-	err = ip_output(m, (struct mbuf *)0, 0, 0, 0, 0);
-#  else
-	err = ip_output(m, (struct mbuf *)0, 0, 0, 0);
-#  endif
+	m = m_gethdr(M_DONTWAIT, MT_HEADER);
+# endif
+	if (m == NULL)
+		return ENOBUFS;
+	m->m_len = sizeof(*nip) + sizeof(*icmp) + 8;
+# if	BSD >= 199306
+	m->m_data += max_linkhdr;
+	m->m_pkthdr.len = sizeof(*nip) + sizeof(*icmp) + 8;
+	m->m_pkthdr.rcvif = (struct ifnet *)0;
+# endif
+
+	bzero(mtod(m, char *), (size_t)sizeof(*nip) + sizeof(*icmp) + 8);
+	nip = mtod(m, ip_t *);
+	icmp = (struct icmp *)(nip + 1);
+
+	nip->ip_p = IPPROTO_ICMP;
+	nip->ip_id = oip->ip_id;
+	nip->ip_sum = 0;
+	nip->ip_ttl = 60;
+	nip->ip_tos = oip->ip_tos;
+	nip->ip_len = sizeof(*nip) + sizeof(*icmp) + 8;
+	if (dst.s_addr == 0) {
+		if (fr_ifpaddr(fin->fin_ifp, &dst) == -1)
+			return -1;
+	}
+	nip->ip_src = dst;
+	nip->ip_dst = oip->ip_src;
+
+	icmp->icmp_type = type;
+	icmp->icmp_code = code;
+	icmp->icmp_cksum = 0;
+	bcopy((char *)oip, (char *)&icmp->icmp_ip, sizeof(*oip));
+	bcopy((char *)oip + (oip->ip_hl << 2),
+	      (char *)&icmp->icmp_ip + sizeof(*oip), 8);	/* 64 bits */
+# ifndef	sparc
+	{
+	register u_short	__iplen, __ipoff;
+	ip_t *ip = &icmp->icmp_ip;
+
+	__iplen = ip->ip_len;
+	__ipoff = ip->ip_off;
+	ip->ip_len = htons(__iplen);
+	ip->ip_off = htons(__ipoff);
+	}
 # endif
-	return err;
+	icmp->icmp_cksum = ipf_cksum((u_short *)icmp, sizeof(*icmp) + 8);
+	return send_ip(nip, fin, m);
 }
 
 
@@ -933,15 +1078,11 @@
 #  endif
 iplinit()
 {
-#  if defined(__OpenBSD__)
-	/* must explicitly enable with 'ipf -E'
-	 * which invokes ipl_enable(); */
-#  else
-	(void) iplattach();
-#  endif
+	if (iplattach() != 0)
+		printf("IP Filter failed to attach\n");
 	ip_init();
 }
-# endif /* !LKM, !sgi, FreeBSD < 3 */
+# endif /* ! __NetBSD__ */
 
 
 size_t mbufchainlen(m0)
@@ -955,7 +1096,7 @@
 }
 
 
-void ipfr_fastroute(m0, fin, fdp)
+int ipfr_fastroute(m0, fin, fdp)
 struct mbuf *m0;
 fr_info_t *fin;
 frdest_t *fdp;
@@ -963,12 +1104,13 @@
 	register struct ip *ip, *mhip;
 	register struct mbuf *m = m0;
 	register struct route *ro;
-	struct ifnet *ifp = fdp->fd_ifp;
-	int len, off, error = 0;
-	int hlen = fin->fin_hlen;
-	struct route iproute;
+	int len, off, error = 0, hlen, code;
+	struct ifnet *ifp, *sifp;
 	struct sockaddr_in *dst;
+	struct route iproute;
+	frentry_t *fr;
 
+	hlen = fin->fin_hlen;
 	ip = mtod(m0, struct ip *);
 	/*
 	 * Route packet.
@@ -977,13 +1119,32 @@
 	bzero((caddr_t)ro, sizeof (*ro));
 	dst = (struct sockaddr_in *)&ro->ro_dst;
 	dst->sin_family = AF_INET;
-	dst->sin_addr = fdp->fd_ip.s_addr ? fdp->fd_ip : ip->ip_dst;
-# ifdef	__bsdi__
+
+	fr = fin->fin_fr;
+	if (fdp)
+		ifp = fdp->fd_ifp;
+	else {
+		ifp = fin->fin_ifp;
+		dst->sin_addr = ip->ip_dst;
+	}
+
+	/*
+	 * In case we're here due to "to <if>" being used with "keep state",
+	 * check that we're going in the correct direction.
+	 */
+	if ((fr != NULL) && (fin->fin_rev != 0)) {
+		if ((ifp != NULL) && (fdp == &fr->fr_tif))
+			return -1;
+		dst->sin_addr = ip->ip_dst;
+	} else if (fdp)
+		dst->sin_addr = fdp->fd_ip.s_addr ? fdp->fd_ip : ip->ip_dst;
+
+# if BSD >= 199306
 	dst->sin_len = sizeof(*dst);
 # endif
 # if	(BSD >= 199306) && !defined(__NetBSD__) && !defined(__bsdi__) && \
 	!defined(__OpenBSD__)
-# ifdef	RTF_CLONING
+#  ifdef	RTF_CLONING
 	rtalloc_ign(ro, RTF_CLONING);
 #  else
 	rtalloc_ign(ro, RTF_PRCLONING);
@@ -992,7 +1153,7 @@
 	rtalloc(ro);
 # endif
 	if (!ifp) {
-		if (!(fin->fin_fr->fr_flags & FR_FASTROUTE)) {
+		if (!fr || !(fr->fr_flags & FR_FASTROUTE)) {
 			error = -2;
 			goto bad;
 		}
@@ -1014,15 +1175,19 @@
 	 * go back through output filtering and miss their chance to get
 	 * NAT'd and counted.
 	 */
+	fin->fin_ifp = ifp;
 	if (fin->fin_out == 0) {
+		fin->fin_out = 1;
 		if ((fin->fin_fr = ipacct[1][fr_active]) &&
-		    (FR_SCANLIST(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) {
+		    (fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) {
 			ATOMIC_INC(frstats[1].fr_acct);
 		}
 		fin->fin_fr = NULL;
-		(void) ip_natout(ip, hlen, fin);
-	}
-	if (fin->fin_out)
+		if (!fr || !(fr->fr_flags & FR_RETMASK)) {
+			(void) fr_checkstate(ip, fin);
+			(void) ip_natout(ip, fin);
+		}
+	} else
 		ip->ip_sum = 0;
 	/*
 	 * If small enough for interface, can just send directly.
@@ -1066,7 +1231,11 @@
 	m0 = m;
 	mhlen = sizeof (struct ip);
 	for (off = hlen + len; off < ip->ip_len; off += len) {
+# ifdef	MGETHDR
+		MGETHDR(m, M_DONTWAIT, MT_HEADER);
+# else
 		MGET(m, M_DONTWAIT, MT_HEADER);
+# endif
 		if (m == 0) {
 			error = ENOBUFS;
 			goto bad;
@@ -1096,6 +1265,10 @@
 			error = ENOBUFS;	/* ??? */
 			goto sendorfree;
 		}
+# if BSD >= 199306
+		m->m_pkthdr.len = mhlen + len;
+		m->m_pkthdr.rcvif = NULL;
+# endif
 		mhip->ip_off = htons((u_short)mhip->ip_off);
 		mhip->ip_sum = 0;
 		mhip->ip_sum = in_cksum(m, mhlen);
@@ -1135,50 +1308,56 @@
 
 	if (ro->ro_rt)
 		RTFREE(ro->ro_rt);
-	return;
+	return 0;
 bad:
+	if (error == EMSGSIZE) {
+		sifp = fin->fin_ifp;
+		fin->fin_ifp = ifp;
+		code = fin->fin_icode;
+		fin->fin_icode = ICMP_UNREACH_NEEDFRAG;
+		(void) send_icmp_err(ip, ICMP_UNREACH, fin, ip->ip_dst);
+		fin->fin_ifp = sifp;
+		fin->fin_icode = code;
+	}
 	m_freem(m);
 	goto done;
 }
 #else /* #ifdef _KERNEL */
 
 
-#ifdef __sgi
+# ifdef __sgi
 static int no_output __P((struct ifnet *ifp, struct mbuf *m,
 			   struct sockaddr *s))
-#else
+# else
 static int no_output __P((struct ifnet *ifp, struct mbuf *m,
 			   struct sockaddr *s, struct rtentry *rt))
-#endif
+# endif
 {
 	return 0;
 }
 
 
 # ifdef __STDC__
-#ifdef __sgi
+#  ifdef __sgi
 static int write_output __P((struct ifnet *ifp, struct mbuf *m,
 			     struct sockaddr *s))
-#else
+#  else
 static int write_output __P((struct ifnet *ifp, struct mbuf *m,
 			     struct sockaddr *s, struct rtentry *rt))
-#endif
+#  endif
 {
-# if !(defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
-	(defined(OpenBSD) && (OpenBSD >= 199603))
 	ip_t *ip = (ip_t *)m;
-#  endif
 # else
 static int write_output(ifp, ip)
 struct ifnet *ifp;
 ip_t *ip;
 {
 # endif
-	FILE *fp;
 	char fname[32];
+	FILE *fp;
 
 # if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
-    (defined(OpenBSD) && (OpenBSD >= 199603))
+	(defined(OpenBSD) && (OpenBSD >= 199603))
 #    if defined __OpenBSD__
 	sprintf(fname, "/var/run/%s", ifp->if_xname);
 #    else
@@ -1258,7 +1437,6 @@
 
 void init_ifp()
 {
-
 	struct ifnet *ifp, **ifa;
 	char fname[32];
 	int fd;
@@ -1271,8 +1449,11 @@
 		sprintf(fname, "/var/run/%s", ifp->if_xname);
 #    else
 		sprintf(fname, "/tmp/%s", ifp->if_xname);
-#endif
-		if ((fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0600)) != -1)
+#    endif
+		fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
+		if (fd == -1)
+			perror("open");
+		else
 			close(fd);
 	}
 # else
@@ -1280,14 +1461,17 @@
 	for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) {
 		ifp->if_output = write_output;
 		sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
-		if ((fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0600)) != -1)
+		fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
+		if (fd == -1)
+			perror("open");
+		else
 			close(fd);
 	}
 # endif
 }
 
 
-void ipfr_fastroute(ip, fin, fdp)
+int ipfr_fastroute(ip, fin, fdp)
 ip_t *ip;
 fr_info_t *fin;
 frdest_t *fdp;
@@ -1295,7 +1479,7 @@
 	struct ifnet *ifp = fdp->fd_ifp;
 
 	if (!ifp)
-		return;	/* no routing table out here */
+		return 0;	/* no routing table out here */
 
 	ip->ip_len = htons((u_short)ip->ip_len);
 	ip->ip_off = htons((u_short)(ip->ip_off | IP_MF));
@@ -1305,6 +1489,7 @@
 #else
 	(*ifp->if_output)(ifp, (void *)ip, NULL, 0);
 #endif
+	return 0;
 }
 
 
@@ -1330,5 +1515,11 @@
 {
 	verbose("- TCP RST sent\n");
 	return 0;
+}
+
+
+void frsync()
+{
+	return;
 }
 #endif /* _KERNEL */
Index: sys/netinet/ip_frag.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_frag.c,v
retrieving revision 1.11
retrieving revision 1.17
diff -u -r1.11 -r1.17
--- sys/netinet/ip_frag.c	1999/02/05 05:58:51	1.11
+++ sys/netinet/ip_frag.c	2000/03/13 23:40:18	1.17
@@ -1,4 +1,5 @@
-/*       $OpenBSD: ip_frag.c,v 1.11 1999/02/05 05:58:51 deraadt Exp $       */
+/*	$OpenBSD: ip_frag.c,v 1.17 2000/03/13 23:40:18 kjell Exp $	*/
+
 /*
  * Copyright (C) 1993-1998 by Darren Reed.
  *
@@ -8,7 +9,11 @@
  */
 #if !defined(lint)
 static const char sccsid[] = "@(#)ip_frag.c	1.11 3/24/96 (C) 1993-1995 Darren Reed";
-static const char rcsid[] = "@(#)$Id: ip_frag.c,v 1.11 1999/02/05 05:58:51 deraadt Exp $";
+static const char rcsid[] = "@(#)$IPFilter: ip_frag.c,v 2.4.2.4 1999/11/28 04:52:10 darrenr Exp $";
+#endif
+
+#if defined(KERNEL) && !defined(_KERNEL)
+# define      _KERNEL
 #endif
 
 #include <sys/errno.h>
@@ -22,49 +27,49 @@
 # include <stdlib.h>
 #endif
 #if defined(KERNEL) && (__FreeBSD_version >= 220000)
-#include <sys/filio.h>
-#include <sys/fcntl.h>
+# include <sys/filio.h>
+# include <sys/fcntl.h>
 #else
-#include <sys/ioctl.h>
+# include <sys/ioctl.h>
 #endif
 #include <sys/uio.h>
 #ifndef linux
-#include <sys/protosw.h>
+# include <sys/protosw.h>
 #endif
 #include <sys/socket.h>
 #if defined(_KERNEL) && !defined(linux)
 # include <sys/systm.h>
 #endif
 #if !defined(__SVR4) && !defined(__svr4__)
+# if defined(_KERNEL) && !defined(__sgi)
+#  include <sys/kernel.h>
+# endif
 # ifndef linux
 #  include <sys/mbuf.h>
 # endif
 #else
 # include <sys/byteorder.h>
-# include <sys/dditypes.h>
+# ifdef _KERNEL
+#  include <sys/dditypes.h>
+# endif
 # include <sys/stream.h>
 # include <sys/kmem.h>
 #endif
-
 #include <net/if.h>
 #ifdef sun
-#include <net/af.h>
+# include <net/af.h>
 #endif
 #include <net/route.h>
 #include <netinet/in.h>
 #include <netinet/in_systm.h>
 #include <netinet/ip.h>
 #ifndef linux
-#include <netinet/ip_var.h>
+# include <netinet/ip_var.h>
 #endif
 #include <netinet/tcp.h>
 #include <netinet/udp.h>
 #include <netinet/ip_icmp.h>
-#if defined(__OpenBSD__)
-# include <netinet/ip_fil_compat.h>
-#else
-# include <netinet/ip_compat.h>
-#endif
+#include <netinet/ip_fil_compat.h>
 #include <netinet/tcpip.h>
 #include <netinet/ip_fil.h>
 #include <netinet/ip_proxy.h>
@@ -72,6 +77,17 @@
 #include <netinet/ip_frag.h>
 #include <netinet/ip_state.h>
 #include <netinet/ip_auth.h>
+#if (__FreeBSD_version >= 300000)
+# include <sys/malloc.h>
+# if (defined(KERNEL) || defined(_KERNEL))
+#  ifndef IPFILTER_LKM
+#   include <sys/libkern.h>
+#   include <sys/systm.h>
+# endif
+extern struct callout_handle ipfr_slowtimer_ch;
+# endif
+#endif
+
 
 ipfr_t	*ipfr_heads[IPFT_SIZE];
 ipfr_t	*ipfr_nattab[IPFT_SIZE];
@@ -79,16 +95,26 @@
 int	ipfr_inuse = 0,
 	fr_ipfrttl = 120;	/* 60 seconds */
 #ifdef _KERNEL
+# if SOLARIS2 >= 7
+extern	timeout_id_t	ipfr_timer_id;
+# else
 extern	int	ipfr_timer_id;
+# endif
 #endif
 #if	(SOLARIS || defined(__sgi)) && defined(_KERNEL)
-extern	KRWLOCK_T	ipf_frag, ipf_natfrag, ipf_nat;
+extern	KRWLOCK_T	ipf_frag, ipf_natfrag, ipf_nat, ipf_mutex;
+# if	SOLARIS
+extern	KRWLOCK_T	ipf_solaris;
+# else
+KRWLOCK_T	ipf_solaris;
+# endif
 extern	kmutex_t	ipf_rw;
 #endif
 
 
-static ipfr_t *ipfr_new __P((ip_t *, fr_info_t *, int, ipfr_t **));
+static ipfr_t *ipfr_new __P((ip_t *, fr_info_t *, u_int, ipfr_t **));
 static ipfr_t *ipfr_lookup __P((ip_t *, fr_info_t *, ipfr_t **));
+static void ipfr_delete __P((ipfr_t *));
 
 
 ipfrstat_t *ipfr_fragstats()
@@ -107,10 +133,10 @@
 static ipfr_t *ipfr_new(ip, fin, pass, table)
 ip_t *ip;
 fr_info_t *fin;
-int pass;
+u_int pass;
 ipfr_t *table[];
 {
-	ipfr_t	**fp, *fr, frag;
+	ipfr_t	**fp, *fra, frag;
 	u_int	idx;
 
 	frag.ipfr_p = ip->ip_p;
@@ -128,8 +154,8 @@
 	/*
 	 * first, make sure it isn't already there...
 	 */
-	for (fp = &table[idx]; (fr = *fp); fp = &fr->ipfr_next)
-		if (!bcmp((char *)&frag.ipfr_src, (char *)&fr->ipfr_src,
+	for (fp = &table[idx]; (fra = *fp); fp = &fra->ipfr_next)
+		if (!bcmp((char *)&frag.ipfr_src, (char *)&fra->ipfr_src,
 			  IPFR_CMPSZ)) {
 			ATOMIC_INC(ipfr_stats.ifs_exists);
 			return NULL;
@@ -139,39 +165,43 @@
 	 * allocate some memory, if possible, if not, just record that we
 	 * failed to do so.
 	 */
-	KMALLOC(fr, ipfr_t *, sizeof(*fr));
-	if (fr == NULL) {
+	KMALLOC(fra, ipfr_t *);
+	if (fra == NULL) {
 		ATOMIC_INC(ipfr_stats.ifs_nomem);
 		return NULL;
 	}
 
+	if ((fra->ipfr_rule = fin->fin_fr) != NULL) {
+		ATOMIC_INC(fin->fin_fr->fr_ref);
+	}
+
+
 	/*
 	 * Instert the fragment into the fragment table, copy the struct used
 	 * in the search using bcopy rather than reassign each field.
 	 * Set the ttl to the default and mask out logging from "pass"
 	 */
-	if ((fr->ipfr_next = table[idx]))
-		table[idx]->ipfr_prev = fr;
-	fr->ipfr_prev = NULL;
-	fr->ipfr_data = NULL;
-	table[idx] = fr;
-	bcopy((char *)&frag.ipfr_src, (char *)&fr->ipfr_src, IPFR_CMPSZ);
-	fr->ipfr_ttl = fr_ipfrttl;
-	fr->ipfr_pass = pass & ~(FR_LOGFIRST|FR_LOG);
+	if ((fra->ipfr_next = table[idx]))
+		table[idx]->ipfr_prev = fra;
+	fra->ipfr_prev = NULL;
+	fra->ipfr_data = NULL;
+	table[idx] = fra;
+	bcopy((char *)&frag.ipfr_src, (char *)&fra->ipfr_src, IPFR_CMPSZ);
+	fra->ipfr_ttl = fr_ipfrttl;
 	/*
 	 * Compute the offset of the expected start of the next packet.
 	 */
-	fr->ipfr_off = (ip->ip_off & IP_OFFMASK) + (fin->fin_dlen >> 3);
+	fra->ipfr_off = (ip->ip_off & IP_OFFMASK) + (fin->fin_dlen >> 3);
 	ATOMIC_INC(ipfr_stats.ifs_new);
 	ATOMIC_INC(ipfr_inuse);
-	return fr;
+	return fra;
 }
 
 
 int ipfr_newfrag(ip, fin, pass)
 ip_t *ip;
 fr_info_t *fin;
-int pass;
+u_int pass;
 {
 	ipfr_t	*ipf;
 
@@ -185,7 +215,7 @@
 int ipfr_nat_newfrag(ip, fin, pass, nat)
 ip_t *ip;
 fr_info_t *fin;
-int pass;
+u_int pass;
 nat_t *nat;
 {
 	ipfr_t	*ipf;
@@ -251,14 +281,14 @@
 				f->ipfr_prev = NULL;
 				table[idx] = f;
 			}
-			off = ip->ip_off;
+			off = ip->ip_off & IP_OFFMASK;
 			atoff = off + (fin->fin_dlen >> 3);
 			/*
 			 * If we've follwed the fragments, and this is the
 			 * last (in order), shrink expiration time.
 			 */
-			if ((off & IP_OFFMASK) == f->ipfr_off) {
-				if (!(off & IP_MF))
+			if (off == f->ipfr_off) {
+				if (!(ip->ip_off & IP_MF))
 					f->ipfr_ttl = 1;
 				else
 					f->ipfr_off = atoff;
@@ -301,18 +331,19 @@
 /*
  * functional interface for normal lookups of the fragment cache
  */
-int ipfr_knownfrag(ip, fin)
+frentry_t *ipfr_knownfrag(ip, fin)
 ip_t *ip;
 fr_info_t *fin;
 {
-	int	ret;
-	ipfr_t	*ipf;
+	frentry_t *fr = NULL;
+	ipfr_t	*fra;
 
 	READ_ENTER(&ipf_frag);
-	ipf = ipfr_lookup(ip, fin, ipfr_heads);
-	ret = ipf ? ipf->ipfr_pass : 0;
+	fra = ipfr_lookup(ip, fin, ipfr_heads);
+	if (fra != NULL)
+		fr = fra->ipfr_rule;
 	RWLOCK_EXIT(&ipf_frag);
-	return ret;
+	return fr;
 }
 
 
@@ -335,34 +366,53 @@
 }
 
 
+static void ipfr_delete(fra)
+ipfr_t *fra;
+{
+	frentry_t *fr;
+
+	fr = fra->ipfr_rule;
+	if (fr != NULL) {
+		ATOMIC_DEC(fr->fr_ref);
+		if (fr->fr_ref == 0)
+			KFREE(fr);
+	}
+	if (fra->ipfr_prev)
+		fra->ipfr_prev->ipfr_next = fra->ipfr_next;
+	if (fra->ipfr_next)
+		fra->ipfr_next->ipfr_prev = fra->ipfr_prev;
+	KFREE(fra);
+}
+
+
 /*
  * Free memory in use by fragment state info. kept.
  */
 void ipfr_unload()
 {
-	ipfr_t	**fp, *fr;
+	ipfr_t	**fp, *fra;
 	nat_t	*nat;
 	int	idx;
 
 	WRITE_ENTER(&ipf_frag);
 	for (idx = IPFT_SIZE - 1; idx >= 0; idx--)
-		for (fp = &ipfr_heads[idx]; (fr = *fp); ) {
-			*fp = fr->ipfr_next;
-			KFREE(fr);
+		for (fp = &ipfr_heads[idx]; (fra = *fp); ) {
+			*fp = fra->ipfr_next;
+			ipfr_delete(fra);
 		}
 	RWLOCK_EXIT(&ipf_frag);
 
 	WRITE_ENTER(&ipf_nat);
 	WRITE_ENTER(&ipf_natfrag);
 	for (idx = IPFT_SIZE - 1; idx >= 0; idx--)
-		for (fp = &ipfr_nattab[idx]; (fr = *fp); ) {
-			*fp = fr->ipfr_next;
-			nat = (nat_t *)fr->ipfr_data;
+		for (fp = &ipfr_nattab[idx]; (fra = *fp); ) {
+			*fp = fra->ipfr_next;
+			nat = fra->ipfr_data;
 			if (nat != NULL) {
-				if (nat->nat_data == fr)
+				if (nat->nat_data == fra)
 					nat->nat_data = NULL;
 			}
-			KFREE(fr);
+			ipfr_delete(fra);
 		}
 	RWLOCK_EXIT(&ipf_natfrag);
 	RWLOCK_EXIT(&ipf_nat);
@@ -375,15 +425,30 @@
  * of this being called twice per second.
  */
 # if (BSD >= 199306) || SOLARIS || defined(__sgi)
+#  if defined(SOLARIS2) && (SOLARIS2 < 7)
 void ipfr_slowtimer()
+#  else
+void ipfr_slowtimer __P((void *ptr))
+#  endif
 # else
 int ipfr_slowtimer()
 # endif
 {
-	ipfr_t	**fp, *fr;
+	ipfr_t	**fp, *fra;
 	nat_t	*nat;
-	int	s, idx;
+	int	idx;
+#if defined(_KERNEL)
+# if !SOLARIS
+	int	s;
+# else
+	extern	int	fr_running;
+
+	if (fr_running <= 0) 
+		return;
+# endif
+#endif
 
+	READ_ENTER(&ipf_solaris);
 #ifdef __sgi
 	ipfilter_sgi_intfsync();
 #endif
@@ -397,21 +462,15 @@
 	 * remove it from the chain and free it.
 	 */
 	for (idx = IPFT_SIZE - 1; idx >= 0; idx--)
-		for (fp = &ipfr_heads[idx]; (fr = *fp); ) {
-			--fr->ipfr_ttl;
-			if (fr->ipfr_ttl == 0) {
-				if (fr->ipfr_prev)
-					fr->ipfr_prev->ipfr_next =
-					     fr->ipfr_next;
-				if (fr->ipfr_next)
-					fr->ipfr_next->ipfr_prev =
-					     fr->ipfr_prev;
-				*fp = fr->ipfr_next;
+		for (fp = &ipfr_heads[idx]; (fra = *fp); ) {
+			--fra->ipfr_ttl;
+			if (fra->ipfr_ttl == 0) {
+				*fp = fra->ipfr_next;
+				ipfr_delete(fra);
 				ATOMIC_INC(ipfr_stats.ifs_expire);
 				ATOMIC_DEC(ipfr_inuse);
-				KFREE(fr);
 			} else
-				fp = &fr->ipfr_next;
+				fp = &fra->ipfr_next;
 		}
 	RWLOCK_EXIT(&ipf_frag);
 
@@ -425,26 +484,20 @@
 	WRITE_ENTER(&ipf_nat);
 	WRITE_ENTER(&ipf_natfrag);
 	for (idx = IPFT_SIZE - 1; idx >= 0; idx--)
-		for (fp = &ipfr_nattab[idx]; (fr = *fp); ) {
-			--fr->ipfr_ttl;
-			if (fr->ipfr_ttl == 0) {
-				if (fr->ipfr_prev)
-					fr->ipfr_prev->ipfr_next =
-					     fr->ipfr_next;
-				if (fr->ipfr_next)
-					fr->ipfr_next->ipfr_prev =
-					     fr->ipfr_prev;
-				*fp = fr->ipfr_next;
+		for (fp = &ipfr_nattab[idx]; (fra = *fp); ) {
+			--fra->ipfr_ttl;
+			if (fra->ipfr_ttl == 0) {
 				ATOMIC_INC(ipfr_stats.ifs_expire);
 				ATOMIC_DEC(ipfr_inuse);
-				nat = (nat_t *)fr->ipfr_data;
+				nat = fra->ipfr_data;
 				if (nat != NULL) {
-					if (nat->nat_data == fr)
+					if (nat->nat_data == fra)
 						nat->nat_data = NULL;
 				}
-				KFREE(fr);
+				*fp = fra->ipfr_next;
+				ipfr_delete(fra);
 			} else
-				fp = &fr->ipfr_next;
+				fp = &fra->ipfr_next;
 		}
 	RWLOCK_EXIT(&ipf_natfrag);
 	RWLOCK_EXIT(&ipf_nat);
@@ -456,11 +509,16 @@
 	ipfr_timer_id = timeout(ipfr_slowtimer, NULL, drv_usectohz(500000));
 # else
 #  ifndef linux
-	ip_slowtimo();
+#   if (__FreeBSD_version >= 300000)
+	ipfr_slowtimer_ch = timeout(ipfr_slowtimer, NULL, hz/2);
+#   else
+	timeout(ipfr_slowtimer, NULL, hz/2);
+#   endif
 #  endif
 #  if (BSD < 199306) && !defined(__sgi)
 	return 0;
 #  endif
 # endif
+	RWLOCK_EXIT(&ipf_solaris);
 }
 #endif /* defined(_KERNEL) */
Index: sys/netinet/ip_frag.h
===================================================================
RCS file: /cvs/src/sys/netinet/ip_frag.h,v
retrieving revision 1.8
retrieving revision 1.12
diff -u -r1.8 -r1.12
--- sys/netinet/ip_frag.h	1999/02/05 05:58:51	1.8
+++ sys/netinet/ip_frag.h	2000/03/13 23:40:18	1.12
@@ -1,4 +1,5 @@
-/*       $OpenBSD: ip_frag.h,v 1.8 1999/02/05 05:58:51 deraadt Exp $       */
+/*	$OpenBSD: ip_frag.h,v 1.12 2000/03/13 23:40:18 kjell Exp $	*/
+
 /*
  * Copyright (C) 1993-1998 by Darren Reed.
  *
@@ -7,7 +8,7 @@
  * to the original author and the contributors.
  *
  * @(#)ip_frag.h	1.5 3/24/96
- * $Id: ip_frag.h,v 1.8 1999/02/05 05:58:51 deraadt Exp $
+ * $IPFilter: ip_frag.h,v 2.2 1999/08/06 06:26:38 darrenr Exp $
  */
 
 #ifndef	__IP_FRAG_H__
@@ -25,7 +26,7 @@
 	u_char	ipfr_tos;
 	u_short	ipfr_off;
 	u_short	ipfr_ttl;
-	u_char	ipfr_pass;
+	frentry_t *ipfr_rule;
 } ipfr_t;
 
 
@@ -44,16 +45,21 @@
 
 extern	int	fr_ipfrttl;
 extern	ipfrstat_t	*ipfr_fragstats __P((void));
-extern	int	ipfr_newfrag __P((ip_t *, fr_info_t *, int));
-extern	int	ipfr_nat_newfrag __P((ip_t *, fr_info_t *, int, struct nat *));
+extern	int	ipfr_newfrag __P((ip_t *, fr_info_t *, u_int));
+extern	int	ipfr_nat_newfrag __P((ip_t *, fr_info_t *, u_int, struct nat *));
 extern	nat_t	*ipfr_nat_knownfrag __P((ip_t *, fr_info_t *));
-extern	int	ipfr_knownfrag __P((ip_t *, fr_info_t *));
+extern	frentry_t *ipfr_knownfrag __P((ip_t *, fr_info_t *));
 extern	void	ipfr_forget __P((void *));
 extern	void	ipfr_unload __P((void));
 
 #if     (BSD >= 199306) || SOLARIS || defined(__sgi)
+# if defined(SOLARIS2) && (SOLARIS2 < 7)
 extern	void	ipfr_slowtimer __P((void));
+# else
+extern	void	ipfr_slowtimer __P((void *));
+# endif
 #else
 extern	int	ipfr_slowtimer __P((void));
 #endif
+
 #endif	/* __IP_FIL_H__ */
Index: sys/netinet/ip_ftp_pxy.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_ftp_pxy.c,v
retrieving revision 1.4
retrieving revision 1.10
diff -u -r1.4 -r1.10
--- sys/netinet/ip_ftp_pxy.c	1999/02/05 05:58:52	1.4
+++ sys/netinet/ip_ftp_pxy.c	2000/04/12 21:32:39	1.10
@@ -1,5 +1,6 @@
-/*	$OpenBSD: ip_ftp_pxy.c,v 1.4 1999/02/05 05:58:52 deraadt Exp $
- * $Id: ip_ftp_pxy.c,v 1.4 1999/02/05 05:58:52 deraadt Exp $
+/*	$OpenBSD: ip_ftp_pxy.c,v 1.10 2000/04/12 21:32:39 kjell Exp $	*/
+
+/*
  * Simple FTP transparent proxy for in-kernel use.  For use with the NAT
  * code.
  */
@@ -8,6 +9,7 @@
 #endif
 
 #define	isdigit(x)	((x) >= '0' && (x) <= '9')
+#define	isupper(x)	((unsigned)((x) - 'A') <= 'Z' - 'A')
 
 #define	IPF_FTP_PROXY
 
@@ -15,29 +17,115 @@
 #define	IPF_MAXPORTLEN	30
 #define	IPF_MIN227LEN	39
 #define	IPF_MAX227LEN	51
+#define	IPF_FTPBUFSZ	MAX(96,IPF_MAX227LEN)	/* This *MUST* be >= 51! */
 
 
-int ippr_ftp_init __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *));
+int ippr_ftp_init __P((void));
+int ippr_ftp_new __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *));
 int ippr_ftp_out __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *));
 int ippr_ftp_in __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *));
-int ippr_ftp_portmsg __P((fr_info_t *, ip_t *, nat_t *nat));
-int ippr_ftp_pasvmsg __P((fr_info_t *, ip_t *, tcphdr_t *, nat_t *));
+int ippr_ftp_portmsg __P((fr_info_t *, ip_t *, nat_t *));
+int ippr_ftp_pasvmsg __P((fr_info_t *, ip_t *, nat_t *));
+int ippr_ftp_complete __P((char *, size_t));
+
 u_short ipf_ftp_atoi __P((char **));
 
+static	frentry_t	natfr;
+int	ippr_ftp_pasvonly = 0;
 
+
 /*
- * FTP application proxy initialization.
+ * Initialize local structures.
  */
-int ippr_ftp_init(fin, ip, aps, nat)
+int ippr_ftp_init()
+{
+	bzero((char *)&natfr, sizeof(natfr));
+	natfr.fr_ref = 1;
+	natfr.fr_flags = FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE;
+	return 0;
+}
+
+
+int ippr_ftp_complete(buf, len)
+char *buf;
+size_t len;
+{
+	register char *s, c;
+	register size_t i;
+
+	if (len < 5)
+		return -1;
+	s = buf;
+	c = *s++;
+	i = len - 1;
+
+	if (isdigit(c)) {
+		c = *s++;
+		i--;
+		if (isdigit(c)) {
+			c = *s++;
+			i--;
+			if (isdigit(c)) {
+				c = *s++;
+				i--;
+				if (c != '-' && c != ' ')
+					return -1;
+			} else
+				return -1;
+		} else
+			return -1;
+	} else if (isupper(c)) {
+		c = *s++;
+		i--;
+		if (isupper(c)) {
+			c = *s++;
+			i--;
+			if (isupper(c)) {
+				c = *s++;
+				i--;
+				if (isupper(c)) {
+					c = *s++;
+					i--;
+					if (c != ' ')
+						return -1;
+				} else
+					return -1;
+			} else
+				return -1;
+		} else
+			return -1;
+	} else
+		return -1;
+
+	for (; i && (c = *s); i--, s++) {
+		if ((c == '\r') && (i != 2))
+			return -1;
+		if ((c == '\n') && (i != 1))
+			return -1;
+		else if ((i == 2) && (c != '\r'))
+			return -1;
+		else if ((i == 1) && (c != '\n'))
+			return -1;
+	}
+	return i;
+}
+
+
+int ippr_ftp_new(fin, ip, aps, nat)
 fr_info_t *fin;
 ip_t *ip;
 ap_session_t *aps;
 nat_t *nat;
 {
-	tcphdr_t *tcp = (tcphdr_t *)fin->fin_dp;
+	ftpinfo_t *ftp;
+
+	KMALLOC(ftp, ftpinfo_t *);
+	if (ftp == NULL)
+		return -1;
+	aps->aps_data = ftp;
+	aps->aps_psiz = sizeof(ftpinfo_t);
 
-	aps->aps_sport = tcp->th_sport;
-	aps->aps_dport = tcp->th_dport;
+	ftp->ftp_passok = 0;
 	return 0;
 }
 
@@ -76,12 +164,14 @@
 ip_t *ip;
 nat_t *nat;
 {
-	char portbuf[IPF_MAXPORTLEN + 1], newbuf[IPF_MAXPORTLEN + 1], *s;
-	int off, olen, dlen, nlen = 0, inc = 0;
-	u_int a1, a2, a3, a4;
+	char portbuf[IPF_FTPBUFSZ], newbuf[IPF_FTPBUFSZ], *s;
 	tcphdr_t *tcp, tcph, *tcp2 = &tcph;
-	struct in_addr swip;
+	size_t nlen = 0, dlen, olen;
 	u_short a5, a6, sp, dp;
+	u_int a1, a2, a3, a4;
+	struct in_addr swip;
+	int off, inc = 0;
+	ftpinfo_t *ftp;
 	fr_info_t fi;
 	nat_t *ipn;
 	mb_t *m;
@@ -90,24 +180,51 @@
 #endif
 
 	tcp = (tcphdr_t *)fin->fin_dp;
+	bzero(portbuf, sizeof(portbuf));
 	off = (ip->ip_hl << 2) + (tcp->th_off << 2);
-	m = *(mb_t **)fin->fin_mp;
 
 #if	SOLARIS
 	m = fin->fin_qfm;
 
 	dlen = msgdsize(m) - off;
-	bzero(portbuf, sizeof(portbuf));
-	copyout_mblk(m, off, MIN(sizeof(portbuf), dlen), portbuf);
+	if (dlen > 0)
+		copyout_mblk(m, off, MIN(sizeof(portbuf), dlen), portbuf);
 #else
+	m = *(mb_t **)fin->fin_mp;
+
 	dlen = mbufchainlen(m) - off;
-	bzero(portbuf, sizeof(portbuf));
-	m_copydata(m, off, MIN(sizeof(portbuf), dlen), portbuf);
+	if (dlen > 0)
+		m_copydata(m, off, MIN(sizeof(portbuf), dlen), portbuf);
 #endif
+	if (dlen == 0)
+		return 0;
 	portbuf[sizeof(portbuf) - 1] = '\0';
 	*newbuf = '\0';
 
-	if (!strncmp(portbuf, "PORT ", 5)) { 
+	/*
+	 * Check that a user is progressing through the login ok.
+	 */
+	if (ippr_ftp_complete(portbuf, dlen))
+		return 0;
+
+	ftp = nat->nat_aps->aps_data;
+	switch (ftp->ftp_passok)
+	{
+	case 0 :
+		if (!strncmp(portbuf, "USER ", 5))
+			ftp->ftp_passok = 1;
+		break;
+	case 2 :
+		if (!strncmp(portbuf, "PASS ", 5))
+			ftp->ftp_passok = 3;
+		break;
+	}
+	if (ftp->ftp_passok != 4)
+		return 0;
+	/*
+	 * Check for client sending out PORT message.
+	 */
+	if (!ippr_ftp_pasvonly && !strncmp(portbuf, "PORT ", 5)) { 
 		if (dlen < IPF_MINPORTLEN)
 			return 0;
 	} else
@@ -128,9 +245,9 @@
 		return 0;
 
 	/*
-	* check that IP address in the PORT/PASV reply is the same as the
-	* sender of the command - prevents using PORT for port scanning.
-	*/
+	 * check that IP address in the PORT/PASV reply is the same as the
+	 * sender of the command - prevents using PORT for port scanning.
+	 */
 	a1 <<= 16;
 	a1 |= a2;
 	if (a1 != ntohl(nat->nat_inip.s_addr))
@@ -139,14 +256,18 @@
 	a5 = ipf_ftp_atoi(&s);
 	if (!s)
 		return 0;
+	if (*s == ')')
+		s++;
 
 	/*
 	 * check for CR-LF at the end.
 	 */
-	if (((*s == '\r') && (*(s + 1) == '\n')) ||
-	    ((*(s - 1) == '\r') && (*s == '\n')))
+	if (*s == '\n')
+		s--;
+	if ((*s == '\r') && (*(s + 1) == '\n')) {
+		s += 2;
 		a6 = a5 & 0xff;
-	else
+	} else
 		return 0;
 	a5 >>= 8;
 	/*
@@ -157,8 +278,9 @@
 	a3 = (a1 >> 8) & 0xff;
 	a4 = a1 & 0xff;
 	a1 >>= 24;
-	olen = s - portbuf + 1;
-	(void) sprintf(newbuf, "%s %d,%d,%d,%d,%d,%d\r\n",
+	olen = s - portbuf;
+	/* DO NOT change this to sprintf! */
+	(void) sprintf(newbuf, "%s %u,%u,%u,%u,%u,%u\r\n",
 		       "PORT", a1, a2, a3, a4, a5, a6);
 
 	nlen = strlen(newbuf);
@@ -182,6 +304,9 @@
 
 		linkb(m1, nm);
 	} else {
+		if (m1->b_datap->db_struiolim == m1->b_wptr)
+			m1->b_datap->db_struiolim += inc;
+		m1->b_datap->db_struioflag &= ~STRUIO_IP;
 		m1->b_wptr += inc;
 	}
 	copyin_mblk(m, off, nlen, newbuf);
@@ -191,7 +316,7 @@
 	/* the mbuf chain will be extended if necessary by m_copyback() */
 	m_copyback(m, off, nlen, newbuf);
 #endif
-	if (inc) {
+	if (inc != 0) {
 #if SOLARIS || defined(__sgi)
 		register u_32_t	sum1, sum2;
 
@@ -204,32 +329,46 @@
 		sum2 -= sum1;
 		sum2 = (sum2 & 0xffff) + (sum2 >> 16);
 
-		fix_outcksum(&ip->ip_sum, sum2);
+		fix_outcksum(&ip->ip_sum, sum2, 0);
 #endif
 		ip->ip_len += inc;
 	}
 
 	/*
-	* Add skeleton NAT entry for connection which will come back the
-	* other way.
-	*/
+	 * Add skeleton NAT entry for connection which will come back the
+	 * other way.
+	 */
 	sp = htons(a5 << 8 | a6);
+	/*
+	 * Don't allow the PORT command to specify a port < 1024 due to
+	 * security crap.
+	 */
+	if (ntohs(sp) < 1024)
+		return 0;
+	/*
+	 * The server may not make the connection back from port 20, but
+	 * it is the most likely so use it here to check for a conflicting
+	 * mapping.
+	 */
 	dp = htons(fin->fin_data[1] - 1);
-	ipn = nat_outlookup(fin->fin_ifp, IPN_TCP, nat->nat_inip, sp,
-			    ip->ip_dst, dp);
+	ipn = nat_outlookup(fin->fin_ifp, IPN_TCP, nat->nat_p, nat->nat_inip,
+			    ip->ip_dst, (dp << 16) | sp);
 	if (ipn == NULL) {
 		bcopy((char *)fin, (char *)&fi, sizeof(fi));
 		bzero((char *)tcp2, sizeof(*tcp2));
+		tcp2->th_win = htons(8192);
 		tcp2->th_sport = sp;
-		tcp2->th_dport = dp;
+		tcp2->th_dport = 0; /* XXX - don't specify remote port */
+		fi.fin_data[0] = ntohs(sp);
+		fi.fin_data[1] = 0;
 		fi.fin_dp = (char *)tcp2;
 		swip = ip->ip_src;
 		ip->ip_src = nat->nat_inip;
-		ipn = nat_new(nat->nat_ptr, ip, &fi, IPN_TCP, NAT_OUTBOUND);
+		ipn = nat_new(nat->nat_ptr, ip, &fi, IPN_TCP|FI_W_DPORT,
+			      NAT_OUTBOUND);
 		if (ipn != NULL) {
 			ipn->nat_age = fr_defnatage;
-			(void) fr_addstate(ip, &fi, FR_INQUE|FR_PASS|
-						    FR_QUICK|FR_KEEPSTATE);
+			(void) fr_addstate(ip, &fi, FI_W_DPORT);
 		}
 		ip->ip_src = swip;
 	}
@@ -247,18 +386,19 @@
 }
 
 
-int ippr_ftp_pasvmsg(fin, ip, tcp, nat)
+int ippr_ftp_pasvmsg(fin, ip, nat)
 fr_info_t *fin;
 ip_t *ip;
-tcphdr_t *tcp;
 nat_t *nat;
 {
-	char portbuf[IPF_MAX227LEN + 1], newbuf[IPF_MAX227LEN + 1], *s;
+	char portbuf[IPF_FTPBUFSZ], newbuf[IPF_FTPBUFSZ], *s;
 	int off, olen, dlen, nlen = 0, inc = 0;
-	u_int a1, a2, a3, a4;
 	tcphdr_t tcph, *tcp2 = &tcph;
-	struct in_addr swip;
-	u_short a5, a6;
+	struct in_addr swip, swip2;
+	u_short a5, a6, dp, sp;
+	u_int a1, a2, a3, a4;
+	ftpinfo_t *ftp;
+	tcphdr_t *tcp;
 	fr_info_t fi;
 	nat_t *ipn;
 	mb_t *m;
@@ -266,43 +406,72 @@
 	mb_t *m1;
 #endif
 
+	tcp = (tcphdr_t *)fin->fin_dp;
 	off = (ip->ip_hl << 2) + (tcp->th_off << 2);
 	m = *(mb_t **)fin->fin_mp;
+	bzero(portbuf, sizeof(portbuf));
 
 #if	SOLARIS
 	m = fin->fin_qfm;
 
 	dlen = msgdsize(m) - off;
-	bzero(portbuf, sizeof(portbuf));
-	copyout_mblk(m, off, MIN(sizeof(portbuf), dlen), portbuf);
+	if (dlen > 0)
+		copyout_mblk(m, off, MIN(sizeof(portbuf), dlen), portbuf);
 #else
 	dlen = mbufchainlen(m) - off;
-	bzero(portbuf, sizeof(portbuf));
-	m_copydata(m, off, MIN(sizeof(portbuf), dlen), portbuf);
+	if (dlen > 0)
+		m_copydata(m, off, MIN(sizeof(portbuf), dlen), portbuf);
 #endif
+	if (dlen == 0)
+		return 0;
 	portbuf[sizeof(portbuf) - 1] = '\0';
 	*newbuf = '\0';
 
+	/*
+	 * Check that a user is progressing through the login ok.
+	 * Don't put the switch in one common function because one side
+	 * should only see numeric responses and the other commands.
+	 */
+
+	ftp = nat->nat_aps->aps_data;
+	switch (ftp->ftp_passok)
+	{
+	case 1 :
+		if (!strncmp(portbuf, "331", 3))
+			ftp->ftp_passok = 2;
+		else if (!strncmp(portbuf, "530", 3))
+			ftp->ftp_passok = 0;
+		break;
+	case 3 :
+		if (!strncmp(portbuf, "230", 3))
+			ftp->ftp_passok = 4;
+		break;
+	default :
+		break;
+	}
+
+	if (ippr_ftp_complete(portbuf, dlen) || (ftp->ftp_passok != 4))
+		return 0;
+
+	/*
+	 * Check for PASV reply message.
+	 */
 	if (!strncmp(portbuf, "227 ", 4)) {
 		if (dlen < IPF_MIN227LEN)
 			return 0;
 		else if (strncmp(portbuf, "227 Entering Passive Mode", 25))
 			return 0;
-#ifndef notyet
-		return 0;
-#endif
 	} else
 		return 0;
-
 	/*
-	* Skip the PORT command + space
-	*/
+	 * Skip the PORT command + space
+	 */
 	s = portbuf + 25;
 	while (*s && !isdigit(*s))
 		s++;
 	/*
-	* Pick out the address components, two at a time.
-	*/
+	 * Pick out the address components, two at a time.
+	 */
 	a1 = ipf_ftp_atoi(&s);
 	if (!s)
 		return 0;
@@ -311,9 +480,9 @@
 		return 0;
 
 	/*
-	* check that IP address in the PORT/PASV reply is the same as the
-	* sender of the command - prevents using PORT for port scanning.
-	*/
+	 * check that IP address in the PORT/PASV reply is the same as the
+	 * sender of the command - prevents using PORT for port scanning.
+	 */
 	a1 <<= 16;
 	a1 |= a2;
 	if (a1 != ntohl(nat->nat_oip.s_addr))
@@ -323,25 +492,29 @@
 	if (!s)
 		return 0;
 
+	if (*s == ')')
+		s++;
+	if (*s == '\n')
+		s--;
 	/*
-	* check for CR-LF at the end.
-	*/
-	if (((*s == '\r') && (*(s + 1) == '\n')) ||
-	    ((*(s - 1) == '\r') && (*s == '\n')))
+	 * check for CR-LF at the end.
+	 */
+	if ((*s == '\r') && (*(s + 1) == '\n')) {
+		s += 2;
 		a6 = a5 & 0xff;
-	else
+	} else
 		return 0;
 	a5 >>= 8;
 	/*
-	* Calculate new address parts for 227 reply
-	*/
-	a1 = ntohl(nat->nat_inip.s_addr);
+	 * Calculate new address parts for 227 reply
+	 */
+	a1 = ntohl(ip->ip_src.s_addr);
 	a2 = (a1 >> 16) & 0xff;
 	a3 = (a1 >> 8) & 0xff;
 	a4 = a1 & 0xff;
 	a1 >>= 24;
-	olen = s - portbuf + 1;
-	(void) sprintf(newbuf, "%s %d,%d,%d,%d,%d,%d\r\n",
+	olen = s - portbuf;
+	(void) sprintf(newbuf, "%s %u,%u,%u,%u,%u,%u\r\n",
 		       "227 Entering Passive Mode", a1, a2, a3, a4, a5, a6);
 
 	nlen = strlen(newbuf);
@@ -374,7 +547,7 @@
 	/* the mbuf chain will be extended if necessary by m_copyback() */
 	m_copyback(m, off, nlen, newbuf);
 #endif
-	if (inc) {
+	if (inc != 0) {
 #if SOLARIS || defined(__sgi)
 		register u_32_t	sum1, sum2;
 
@@ -387,7 +560,7 @@
 		sum2 -= sum1;
 		sum2 = (sum2 & 0xffff) + (sum2 >> 16);
 
-		fix_outcksum(&ip->ip_sum, sum2);
+		fix_outcksum(&ip->ip_sum, sum2, 0);
 #endif
 		ip->ip_len += inc;
 	}
@@ -396,27 +569,42 @@
 	 * Add skeleton NAT entry for connection which will come back the
 	 * other way.
 	 */
-	bcopy((char *)fin, (char *)&fi, sizeof(fi));
-	bzero((char *)tcp2, sizeof(*tcp2));
-	tcp2->th_sport = htons(a5 << 8 | a6);
-	fi.fin_dp = (char *)tcp2;
-	swip = ip->ip_src;
-	ip->ip_src = nat->nat_oip;
-	ipn = nat_new(nat->nat_ptr, ip, &fi, IPN_TCP, NAT_INBOUND);
-	if (ipn != NULL)
-		ipn->nat_age = fr_defnatage;
-	(void) fr_addstate(ip, &fi, FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE);
-	ip->ip_src = swip;
+	sp = 0;
+	dp = htons(fin->fin_data[1] - 1);
+	ipn = nat_outlookup(fin->fin_ifp, IPN_TCP, nat->nat_p, nat->nat_inip,
+			    ip->ip_dst, (dp << 16) | sp);
+	if (ipn == NULL) {
+		bcopy((char *)fin, (char *)&fi, sizeof(fi));
+		bzero((char *)tcp2, sizeof(*tcp2));
+		tcp2->th_win = htons(8192);
+		tcp2->th_sport = 0;		/* XXX - fake it for nat_new */
+		fi.fin_data[0] = a5 << 8 | a6;
+		tcp2->th_dport = htons(fi.fin_data[0]);
+		fi.fin_data[1] = 0;
+		fi.fin_dp = (char *)tcp2;
+		swip = ip->ip_src;
+		swip2 = ip->ip_dst;
+		ip->ip_dst = ip->ip_src;
+		ip->ip_src = nat->nat_inip;
+		ipn = nat_new(nat->nat_ptr, ip, &fi, IPN_TCP|FI_W_SPORT,
+			      NAT_OUTBOUND);
+		if (ipn != NULL) {
+			ipn->nat_age = fr_defnatage;
+			(void) fr_addstate(ip, &fi, FI_W_SPORT);
+		}
+		ip->ip_src = swip;
+		ip->ip_dst = swip2;
+	}
 	return inc;
 }
 
+
 int ippr_ftp_in(fin, ip, aps, nat)
 fr_info_t *fin;
 ip_t *ip;
 ap_session_t *aps;
 nat_t *nat;
 {
-	tcphdr_t *tcp = (tcphdr_t *)fin->fin_dp;
 
-	return ippr_ftp_pasvmsg(fin, ip, tcp, nat);
+	return ippr_ftp_pasvmsg(fin, ip, nat);
 }
Index: sys/netinet/ip_log.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_log.c,v
retrieving revision 1.4
retrieving revision 1.8
diff -u -r1.4 -r1.8
--- sys/netinet/ip_log.c	1999/02/05 05:58:52	1.4
+++ sys/netinet/ip_log.c	2000/03/13 23:40:18	1.8
@@ -1,4 +1,5 @@
-/*       $OpenBSD: ip_log.c,v 1.4 1999/02/05 05:58:52 deraadt Exp $       */
+/*	$OpenBSD: ip_log.c,v 1.8 2000/03/13 23:40:18 kjell Exp $	*/
+
 /*
  * Copyright (C) 1997-1998 by Darren Reed.
  *
@@ -6,23 +7,29 @@
  * provided that this notice is preserved and due credit is given
  * to the original author and the contributors.
  *
- * $Id: ip_log.c,v 1.4 1999/02/05 05:58:52 deraadt Exp $
+ * $IPFilter: ip_log.c,v 2.1.2.2 1999/09/21 11:55:44 darrenr Exp $
  */
+#include <sys/param.h>
+#if defined(KERNEL) && !defined(_KERNEL)
+# define       _KERNEL
+#endif
+#if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM)
+# include "opt_ipfilter_log.h"
+#endif
+#ifdef  __FreeBSD__
+# if defined(_KERNEL) && !defined(IPFILTER_LKM)
+#  include <sys/osreldate.h>
+#  if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
+#   include "opt_ipfilter.h"
+#  endif
+# else
+#  include <osreldate.h>
+# endif
+#endif
 #ifdef	IPFILTER_LOG
 # ifndef SOLARIS
 #  define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
 # endif
-
-# if defined(KERNEL) && !defined(_KERNEL)
-#  define       _KERNEL
-# endif
-# ifdef  __FreeBSD__
-#  if defined(_KERNEL) && !defined(IPFILTER_LKM)
-#   include <sys/osreldate.h>
-#  else
-#   include <osreldate.h>
-#  endif
-# endif
 # ifndef _KERNEL
 #  include <stdio.h>
 #  include <string.h>
@@ -31,7 +38,6 @@
 # endif
 # include <sys/errno.h>
 # include <sys/types.h>
-# include <sys/param.h>
 # include <sys/file.h>
 # if __FreeBSD_version >= 220000 && defined(_KERNEL)
 #  include <sys/fcntl.h>
@@ -45,7 +51,7 @@
 # endif
 # include <sys/uio.h>
 # if !SOLARIS
-#  if (NetBSD > 199609) || (OpenBSD > 199603)
+#  if (NetBSD > 199609) || (OpenBSD > 199603) || (__FreeBSD_version >= 300000)
 #   include <sys/dirent.h>
 #  else
 #   include <sys/dir.h>
@@ -97,12 +103,8 @@
 # endif
 # ifndef _KERNEL
 #  include <syslog.h>
-# endif
-# if defined(__OpenBSD__)
-#  include <netinet/ip_fil_compat.h>
-# else
-#  include <netinet/ip_compat.h>
 # endif
+# include <netinet/ip_fil_compat.h>
 # include <netinet/tcpip.h>
 # include <netinet/ip_fil.h>
 # include <netinet/ip_proxy.h>
@@ -110,6 +112,10 @@
 # include <netinet/ip_frag.h>
 # include <netinet/ip_state.h>
 # include <netinet/ip_auth.h>
+# if (__FreeBSD_version >= 300000)
+#  include <sys/malloc.h>
+# endif
+
 # ifndef MIN
 #  define	MIN(a,b)	(((a)<(b))?(a):(b))
 # endif
@@ -122,10 +128,9 @@
 #  endif
 # endif
 
-iplog_t	**iplh[IPL_LOGMAX+1], *iplt[IPL_LOGMAX+1];
-int	iplused[IPL_LOGMAX+1];
-u_long	iplcrc[IPL_LOGMAX+1];
-u_long	iplcrcinit;
+iplog_t	**iplh[IPL_LOGMAX+1], *iplt[IPL_LOGMAX+1], *ipll[IPL_LOGMAX+1];
+size_t	iplused[IPL_LOGMAX+1];
+fr_info_t	iplcrc[IPL_LOGMAX+1];
 # ifdef	linux
 static struct wait_queue *iplwait[IPL_LOGMAX+1];
 # endif
@@ -137,20 +142,15 @@
  */
 void ipflog_init()
 {
-	struct	timeval	tv;
 	int	i;
 
 	for (i = IPL_LOGMAX; i >= 0; i--) {
 		iplt[i] = NULL;
+		ipll[i] = NULL;
 		iplh[i] = &iplt[i];
 		iplused[i] = 0;
+		bzero((char *)&iplcrc[i], sizeof(iplcrc[i]));
 	}
-# if BSD >= 199306 || defined(__FreeBSD__) || defined(__sgi)
-	microtime(&tv);
-# else
-	uniqtime(&tv);
-# endif
-	iplcrcinit = tv.tv_sec ^ (tv.tv_usec << 8) ^ tv.tv_usec;
 }
 
 
@@ -169,8 +169,7 @@
 mb_t *m;
 {
 	ipflog_t ipfl;
-	register int mlen, hlen;
-	u_long crc;
+	register size_t mlen, hlen;
 	size_t sizes[2];
 	void *ptrs[2];
 	int types[2];
@@ -193,12 +192,12 @@
 			struct	icmp	*icmp;
 
 			icmp = (struct icmp *)((char *)ip + hlen);
-	
+	 
 			/*
-			* For ICMP, if the packet is an error packet, also
-			* include the information about the packet which
-			* caused the error.
-			*/
+			 * For ICMP, if the packet is an error packet, also
+			 * include the information about the packet which
+			 * caused the error.
+			 */
 			switch (icmp->icmp_type)
 			{
 			case ICMP_UNREACH :
@@ -243,11 +242,15 @@
 	ipfl.fl_hlen = (u_char)hlen;
 	ipfl.fl_rule = fin->fin_rule;
 	ipfl.fl_group = fin->fin_group;
+	if (fin->fin_fr != NULL)
+		ipfl.fl_loglevel = fin->fin_fr->fr_loglevel;
+	else
+		ipfl.fl_loglevel = 0xffff;
 	ipfl.fl_flags = flags;
 	ptrs[0] = (void *)&ipfl;
 	sizes[0] = sizeof(ipfl);
 	types[0] = 0;
-#if SOLARIS
+# if SOLARIS
 	/*
 	 * Are we copied from the mblk or an aligned array ?
 	 */
@@ -260,45 +263,47 @@
 		sizes[1] = hlen + mlen;
 		types[1] = 0;
 	}
-#else
+# else
 	ptrs[1] = m;
 	sizes[1] = hlen + mlen;
 	types[1] = 1;
-#endif
-	crc = (ipf_cksum((u_short *)fin, FI_CSIZE) << 8) + iplcrcinit;
-	return ipllog(IPL_LOGIPF, crc, ptrs, sizes, types, 2);
+# endif
+	return ipllog(IPL_LOGIPF, fin, ptrs, sizes, types, 2);
 }
 
 
 /*
  * ipllog
  */
-int ipllog(dev, crc, items, itemsz, types, cnt)
+int ipllog(dev, fin, items, itemsz, types, cnt)
 int dev;
-u_long crc;
+fr_info_t *fin;
 void **items;
 size_t *itemsz;
 int *types, cnt;
 {
-	iplog_t *ipl;
 	caddr_t buf, s;
-	int len, i;
+	iplog_t *ipl;
+	size_t len;
+	int i;
  
 	/*
 	 * Check to see if this log record has a CRC which matches the last
 	 * record logged.  If it does, just up the count on the previous one
 	 * rather than create a new one.
 	 */
-	if (crc) {
-		MUTEX_ENTER(&ipl_mutex);
-		if ((iplcrc[dev] == crc) && *iplh[dev]) {
-			(*iplh[dev])->ipl_count++;
+	MUTEX_ENTER(&ipl_mutex);
+	if (fin != NULL) {
+		if ((ipll[dev] != NULL) &&
+		    bcmp((char *)fin, (char *)&iplcrc[dev], FI_CSIZE) == 0) {
+			ipll[dev]->ipl_count++;
 			MUTEX_EXIT(&ipl_mutex);
 			return 1;
 		}
-		iplcrc[dev] = crc;
-		MUTEX_EXIT(&ipl_mutex);
-	}
+		bcopy((char *)fin, (char *)&iplcrc[dev], FI_CSIZE);
+	} else
+		bzero((char *)&iplcrc[dev], FI_CSIZE);
+	MUTEX_EXIT(&ipl_mutex);
 
 	/*
 	 * Get the total amount of data to be logged.
@@ -310,7 +315,7 @@
 	 * check that we have space to record this information and can
 	 * allocate that much.
 	 */
-	KMALLOC(buf, caddr_t, len);
+	KMALLOCS(buf, caddr_t, len);
 	if (!buf)
 		return 0;
 	MUTEX_ENTER(&ipl_mutex);
@@ -356,6 +361,7 @@
 		s += itemsz[i];
 	}
 	MUTEX_ENTER(&ipl_mutex);
+	ipll[dev] = ipl;
 	*iplh[dev] = ipl;
 	iplh[dev] = &ipl->ipl_next;
 # if SOLARIS
@@ -374,11 +380,12 @@
 
 
 int ipflog_read(unit, uio)
-int unit;
+minor_t unit;
 struct uio *uio;
 {
+	size_t dlen, copied;
+	int error = 0;
 	iplog_t *ipl;
-	int error = 0, dlen, copied;
 # if defined(_KERNEL) && !SOLARIS
 	int s;
 # endif
@@ -387,7 +394,7 @@
 	 * Sanity checks.  Make sure the minor # is valid and we're copying
 	 * a valid chunk of data.
 	 */
-	if ((IPL_LOGMAX < unit) || (unit < 0))
+	if (IPL_LOGMAX < unit)
 		return ENXIO;
 	if (!uio->uio_resid)
 		return 0;
@@ -431,43 +438,48 @@
 
 	for (copied = 0; (ipl = iplt[unit]); copied += dlen) {
 		dlen = ipl->ipl_dsize;
-		if (dlen + sizeof(iplog_t) > uio->uio_resid)
+		if (dlen > uio->uio_resid)
 			break;
 		/*
 		 * Don't hold the mutex over the uiomove call.
 		 */
 		iplt[unit] = ipl->ipl_next;
+		iplused[unit] -= dlen;
 		MUTEX_EXIT(&ipl_mutex);
 		SPL_X(s);
-		error = UIOMOVE((caddr_t)ipl, ipl->ipl_dsize, UIO_READ, uio);
-		KFREES((caddr_t)ipl, ipl->ipl_dsize);
-		if (error)
+		error = UIOMOVE((caddr_t)ipl, dlen, UIO_READ, uio);
+		if (error) {
+			SPL_NET(s);
+			MUTEX_ENTER(&ipl_mutex);
+			ipl->ipl_next = iplt[unit];
+			iplt[unit] = ipl;
+			iplused[unit] += dlen;
 			break;
+		}
+		KFREES((caddr_t)ipl, dlen);
 		SPL_NET(s);
 		MUTEX_ENTER(&ipl_mutex);
-		iplused[unit] -= dlen;
 	}
-	if (!ipl) {
+	if (!iplt[unit]) {
 		iplused[unit] = 0;
 		iplh[unit] = &iplt[unit];
+		ipll[unit] = NULL;
 	}
 
-	if (!error) {
-		MUTEX_EXIT(&ipl_mutex);
-		SPL_X(s);
-	}
-#ifdef 	linux
+	MUTEX_EXIT(&ipl_mutex);
+	SPL_X(s);
+# ifdef 	linux
 	if (!error)
-		return copied;
+		return (int)copied;
 	return -error;
-#else
+# else
 	return error;
-#endif
+# endif
 }
 
 
 int ipflog_clear(unit)
-int unit;
+minor_t unit;
 {
 	iplog_t *ipl;
 	int used;
@@ -478,9 +490,10 @@
 		KFREES((caddr_t)ipl, ipl->ipl_dsize);
 	}
 	iplh[unit] = &iplt[unit];
+	ipll[unit] = NULL;
 	used = iplused[unit];
 	iplused[unit] = 0;
-	iplcrc[unit] = 0;
+	bzero((char *)&iplcrc[unit], FI_CSIZE);
 	MUTEX_EXIT(&ipl_mutex);
 	return used;
 }
Index: sys/netinet/ip_nat.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_nat.c,v
retrieving revision 1.22
retrieving revision 1.32
diff -u -r1.22 -r1.32
--- sys/netinet/ip_nat.c	1999/08/08 00:43:00	1.22
+++ sys/netinet/ip_nat.c	2000/05/24 21:59:11	1.32
@@ -1,4 +1,5 @@
-/*       $OpenBSD: ip_nat.c,v 1.22 1999/08/08 00:43:00 niklas Exp $       */
+/*	$OpenBSD: ip_nat.c,v 1.32 2000/05/24 21:59:11 kjell Exp $	*/
+
 /*
  * Copyright (C) 1995-1998 by Darren Reed.
  *
@@ -10,7 +11,7 @@
  */
 #if !defined(lint)
 static const char sccsid[] = "@(#)ip_nat.c	1.11 6/5/96 (C) 1995 Darren Reed";
-static const char rcsid[] = "@(#)$Id: ip_nat.c,v 1.22 1999/08/08 00:43:00 niklas Exp $";
+static const char rcsid[] = "@(#)$IPFilter: ip_nat.c,v 2.2.2.18 2000/05/19 15:52:29 darrenr Exp $";
 #endif
 
 #if defined(__FreeBSD__) && defined(KERNEL) && !defined(_KERNEL)
@@ -22,12 +23,16 @@
 #include <sys/param.h>
 #include <sys/time.h>
 #include <sys/file.h>
+#if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \
+    defined(_KERNEL)
+# include "opt_ipfilter_log.h"
+#endif
 #if !defined(_KERNEL) && !defined(KERNEL)
 # include <stdio.h>
 # include <string.h>
 # include <stdlib.h>
 #endif
-#if defined(KERNEL) && (__FreeBSD_version >= 220000)
+#if (defined(KERNEL) || defined(_KERNEL)) && (__FreeBSD_version >= 220000)
 # include <sys/filio.h>
 # include <sys/fcntl.h>
 #else
@@ -49,7 +54,9 @@
 #else
 # include <sys/filio.h>
 # include <sys/byteorder.h>
-# include <sys/dditypes.h>
+# ifdef _KERNEL
+#  include <sys/dditypes.h>
+# endif
 # include <sys/stream.h>
 # include <sys/kmem.h>
 #endif
@@ -59,9 +66,12 @@
 #include <net/if.h>
 #if __FreeBSD_version >= 300000
 # include <net/if_var.h>
+# if defined(_KERNEL) && !defined(IPFILTER_LKM)
+#  include "opt_ipfilter.h"
+# endif
 #endif
 #ifdef sun
-#include <net/af.h>
+# include <net/af.h>
 #endif
 #include <net/route.h>
 #include <netinet/in.h>
@@ -76,8 +86,8 @@
 #endif
 
 #ifdef RFC1825
-#include <vpn/md5.h>
-#include <vpn/ipsec.h>
+# include <vpn/md5.h>
+# include <vpn/ipsec.h>
 extern struct ifnet vpnif;
 #endif
 
@@ -87,27 +97,35 @@
 #include <netinet/tcp.h>
 #include <netinet/udp.h>
 #include <netinet/ip_icmp.h>
-#if defined(__OpenBSD__)
 #include <netinet/ip_fil_compat.h>
-#else
-#include <netinet/ip_compat.h>
-#endif
 #include <netinet/tcpip.h>
 #include <netinet/ip_fil.h>
 #include <netinet/ip_proxy.h>
 #include <netinet/ip_nat.h>
 #include <netinet/ip_frag.h>
 #include <netinet/ip_state.h>
+#if (__FreeBSD_version >= 300000)
+# include <sys/malloc.h>
+#endif
 #ifndef	MIN
-#define	MIN(a,b)	(((a)<(b))?(a):(b))
+# define	MIN(a,b)	(((a)<(b))?(a):(b))
 #endif
 #undef	SOCKADDR_IN
 #define	SOCKADDR_IN	struct sockaddr_in
 
-nat_t	*nat_table[2][NAT_SIZE], *nat_instances = NULL;
+nat_t	**nat_table[2] = { NULL, NULL },
+	*nat_instances = NULL;
 ipnat_t	*nat_list = NULL;
-u_long	fr_defnatage = 1200,	/* 10 minutes (600 seconds) */
-	fr_defnaticmpage = 6;	/* 3 seconds */
+u_int	ipf_nattable_sz = NAT_TABLE_SZ;
+u_int	ipf_natrules_sz = NAT_SIZE;
+u_int	ipf_rdrrules_sz = RDR_SIZE;
+u_32_t	nat_masks = 0;
+u_32_t	rdr_masks = 0;
+ipnat_t	**nat_rules = NULL;
+ipnat_t	**rdr_rules = NULL;
+
+u_long	fr_defnatage = DEF_NAT_AGE,
+	fr_defnaticmpage = 6;		/* 3 seconds */
 natstat_t nat_stats;
 #if	(SOLARIS || defined(__sgi)) && defined(_KERNEL)
 extern	kmutex_t	ipf_rw;
@@ -117,31 +135,87 @@
 static	int	nat_flushtable __P((void));
 static	int	nat_clearlist __P((void));
 static	void	nat_delete __P((struct nat *));
-static	int	nat_ifpaddr __P((nat_t *, void *, struct in_addr *));
+static	void	nat_delrdr __P((struct ipnat *));
+static	void	nat_delnat __P((struct ipnat *));
+
+
+int nat_init()
+{
+	KMALLOCS(nat_table[0], nat_t **, sizeof(nat_t *) * ipf_nattable