summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordarrenr <darrenr@FreeBSD.org>2000-10-26 12:45:54 +0000
committerdarrenr <darrenr@FreeBSD.org>2000-10-26 12:45:54 +0000
commit7595d5ffce4a14f32ac605d21cbd61fbe85057e2 (patch)
tree7098416027f8d3f0d9828794b9eb7a6e22f08d6a
parent54a215376523c9828e0092de33f29614fca24281 (diff)
downloadFreeBSD-src-7595d5ffce4a14f32ac605d21cbd61fbe85057e2.zip
FreeBSD-src-7595d5ffce4a14f32ac605d21cbd61fbe85057e2.tar.gz
Import IP Filter 3.4.12
-rw-r--r--contrib/ipfilter/BNF4
-rwxr-xr-xcontrib/ipfilter/FreeBSD-4.0/ipv6-patch-4.061
-rw-r--r--contrib/ipfilter/FreeBSD-4.0/ipv6-patch-4.163
-rwxr-xr-xcontrib/ipfilter/FreeBSD-4.0/kinstall8
-rwxr-xr-xcontrib/ipfilter/FreeBSD-4.0/unkinstall3
-rw-r--r--contrib/ipfilter/HISTORY52
-rw-r--r--contrib/ipfilter/Makefile16
-rw-r--r--contrib/ipfilter/common.c2
-rw-r--r--contrib/ipfilter/fil.c61
-rw-r--r--contrib/ipfilter/ip_auth.h4
-rw-r--r--contrib/ipfilter/ip_compat.h38
-rw-r--r--contrib/ipfilter/ip_fil.c39
-rw-r--r--contrib/ipfilter/ip_frag.c23
-rw-r--r--contrib/ipfilter/ip_frag.h4
-rw-r--r--contrib/ipfilter/ip_ftp_pxy.c24
-rw-r--r--contrib/ipfilter/ip_nat.c439
-rw-r--r--contrib/ipfilter/ip_nat.h14
-rw-r--r--contrib/ipfilter/ip_raudio_pxy.c4
-rw-r--r--contrib/ipfilter/ip_sfil.c30
-rw-r--r--contrib/ipfilter/ip_state.c144
-rw-r--r--contrib/ipfilter/ip_state.h3
-rw-r--r--contrib/ipfilter/ipf.c13
-rw-r--r--contrib/ipfilter/ipl.h4
-rw-r--r--contrib/ipfilter/ipmon.c4
-rw-r--r--contrib/ipfilter/ipsend/44arp.c2
-rw-r--r--contrib/ipfilter/man/ipf.430
-rw-r--r--contrib/ipfilter/man/ipf.54
-rw-r--r--contrib/ipfilter/man/ipmon.82
-rw-r--r--contrib/ipfilter/man/ipnat.46
-rw-r--r--contrib/ipfilter/mlf_ipl.c2
-rw-r--r--contrib/ipfilter/mlfk_ipl.c4
-rw-r--r--contrib/ipfilter/perl/plog998
-rw-r--r--contrib/ipfilter/rules/BASIC.NAT11
33 files changed, 1449 insertions, 667 deletions
diff --git a/contrib/ipfilter/BNF b/contrib/ipfilter/BNF
index cfa5423..556171d 100644
--- a/contrib/ipfilter/BNF
+++ b/contrib/ipfilter/BNF
@@ -11,7 +11,7 @@ proto = "proto" protocol .
ip = srcdst [ flags ] [ with withopt ] [ icmp ] [ keep ] .
group = [ "head" decnumber ] [ "group" decnumber ] .
-block = "block" [ icmp [return-code] | "return-rst" ] .
+block = "block" [ reutrn-icmp[return-code] | "return-rst" ] .
auth = "auth" | "preauth" .
log = "log" [ "body" ] [ "first" ] [ "or-block" ] [ "level" loglevel ] .
call = "call" [ "now" ] function-name .
@@ -22,7 +22,7 @@ protocol = "tcp/udp" | "udp" | "tcp" | "icmp" | decnumber .
srcdst = "all" | fromto .
fromto = "from" object "to" object .
-icmp = "return-icmp" | "return-icmp-as-dest" .
+reutrn-icmp = "return-icmp" | "return-icmp-as-dest" .
loglevel = facility"."priority | priority .
object = addr [ port-comp | port-range ] .
addr = "any" | nummask | host-name [ "mask" ipaddr | "mask" hexnumber ] .
diff --git a/contrib/ipfilter/FreeBSD-4.0/ipv6-patch-4.0 b/contrib/ipfilter/FreeBSD-4.0/ipv6-patch-4.0
new file mode 100755
index 0000000..c232b2c
--- /dev/null
+++ b/contrib/ipfilter/FreeBSD-4.0/ipv6-patch-4.0
@@ -0,0 +1,61 @@
+*** ip6_input.c.orig Sun Feb 13 14:32:01 2000
+--- ip6_input.c Wed Apr 26 22:31:34 2000
+***************
+*** 121,126 ****
+--- 121,127 ----
+
+ extern struct domain inet6domain;
+ extern struct ip6protosw inet6sw[];
++ extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **));
+
+ u_char ip6_protox[IPPROTO_MAX];
+ static int ip6qmaxlen = IFQ_MAXLEN;
+***************
+*** 302,307 ****
+--- 303,317 ----
+ ip6stat.ip6s_badvers++;
+ in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
+ goto bad;
++ }
++
++ if (fr_checkp) {
++ struct mbuf *m1 = m;
++
++ if ((*fr_checkp)(ip6, sizeof(*ip6), m->m_pkthdr.rcvif,
++ 0, &m1) || !m1)
++ return;
++ ip6 = mtod(m = m1, struct ip6_hdr *);
+ }
+
+ ip6stat.ip6s_nxthist[ip6->ip6_nxt]++;
+*** ip6_output.c.orig Fri Mar 10 01:57:16 2000
+--- ip6_output.c Wed Apr 26 22:34:34 2000
+***************
+*** 108,113 ****
+--- 108,115 ----
+ #include <netinet6/ip6_fw.h>
+ #endif
+
++ extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **));
++
+ static MALLOC_DEFINE(M_IPMOPTS, "ip6_moptions", "internet multicast options");
+
+ struct ip6_exthdrs {
+***************
+*** 754,759 ****
+--- 756,770 ----
+ ip6->ip6_src.s6_addr16[1] = 0;
+ if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
+ ip6->ip6_dst.s6_addr16[1] = 0;
++ }
++
++ if (fr_checkp) {
++ struct mbuf *m1 = m;
++
++ if ((error = (*fr_checkp)(ip6, sizeof(*ip6), ifp, 1, &m1)) ||
++ !m1)
++ goto done;
++ ip6 = mtod(m = m1, struct ip6_hdr *);
+ }
+
+ #ifdef IPV6FIREWALL
diff --git a/contrib/ipfilter/FreeBSD-4.0/ipv6-patch-4.1 b/contrib/ipfilter/FreeBSD-4.0/ipv6-patch-4.1
new file mode 100644
index 0000000..90dac19
--- /dev/null
+++ b/contrib/ipfilter/FreeBSD-4.0/ipv6-patch-4.1
@@ -0,0 +1,63 @@
+*** ip6_input.c.orig Sat Jul 15 07:14:34 2000
+--- ip6_input.c Thu Oct 19 17:14:37 2000
+***************
+*** 120,125 ****
+--- 120,127 ----
+
+ extern struct domain inet6domain;
+ extern struct ip6protosw inet6sw[];
++ extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int,
++ struct mbuf **));
+
+ u_char ip6_protox[IPPROTO_MAX];
+ static int ip6qmaxlen = IFQ_MAXLEN;
+***************
+*** 289,294 ****
+--- 291,305 ----
+ ip6stat.ip6s_badvers++;
+ in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
+ goto bad;
++ }
++
++ if (fr_checkp) {
++ struct mbuf *m1 = m;
++
++ if ((*fr_checkp)(ip6, sizeof(*ip6), m->m_pkthdr.rcvif,
++ 0, &m1) || !m1)
++ return;
++ ip6 = mtod(m = m1, struct ip6_hdr *);
+ }
+
+ ip6stat.ip6s_nxthist[ip6->ip6_nxt]++;
+
+*** ip6_output.c.orig Sat Jul 15 07:14:35 2000
+--- ip6_output.c Thu Oct 19 17:13:53 2000
+***************
+*** 106,111 ****
+--- 106,113 ----
+ #include <netinet6/ip6_fw.h>
+ #endif
+
++ extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **));
++
+ static MALLOC_DEFINE(M_IPMOPTS, "ip6_moptions", "internet multicast options");
+
+ struct ip6_exthdrs {
+***************
+*** 787,792 ****
+--- 789,803 ----
+ ip6->ip6_src.s6_addr16[1] = 0;
+ if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
+ ip6->ip6_dst.s6_addr16[1] = 0;
++ }
++
++ if (fr_checkp) {
++ struct mbuf *m1 = m;
++
++ if ((error = (*fr_checkp)(ip6, sizeof(*ip6), ifp, 1, &m1)) ||
++ !m1)
++ goto done;
++ ip6 = mtod(m = m1, struct ip6_hdr *);
+ }
+
+ #ifdef IPV6FIREWALL
diff --git a/contrib/ipfilter/FreeBSD-4.0/kinstall b/contrib/ipfilter/FreeBSD-4.0/kinstall
index cb3c3da..7e663d2 100755
--- a/contrib/ipfilter/FreeBSD-4.0/kinstall
+++ b/contrib/ipfilter/FreeBSD-4.0/kinstall
@@ -2,6 +2,7 @@
#
set dir=`pwd`
set karch=`uname -m`
+set krev=`uname -r|sed -e 's/\([0-9\.]*\)-.*/\1/'`
if ( -d /sys/arch/$karch ) set archdir="/sys/arch/$karch"
if ( -d /sys/$karch ) set archdir="/sys/$karch"
set confdir="$archdir/conf"
@@ -21,7 +22,7 @@ ln -s /usr/include/osreldate.h /sys/sys/osreldate.h
echo ""
echo "Patching ip6_input.c and ip6_output.c"
-cat FreeBSD-4.0/ipv6-patch | (cd /sys/netinet6; patch)
+cat FreeBSD-4.0/ipv6-patch-$krev | (cd /sys/netinet6; patch)
set config=`(cd $confdir; /bin/ls -1t [0-9A-Z_]*) | head -1`
echo -n "Kernel configuration to update [$config] "
@@ -31,6 +32,11 @@ if ( "$newconfig" != "" ) then
else
set newconfig=$config
endif
+grep -q IPFILTER $confdir/$newconfig
+if ($status == 0) then
+ echo "IPFilter already configured in kernel config file"
+ exit 0
+endif
echo "Rewriting $newconfig..."
if ( -f $confdir/$newconfig ) then
mv $confdir/$newconfig $confdir/$newconfig.bak
diff --git a/contrib/ipfilter/FreeBSD-4.0/unkinstall b/contrib/ipfilter/FreeBSD-4.0/unkinstall
index d43ac4a..4e9caaa 100755
--- a/contrib/ipfilter/FreeBSD-4.0/unkinstall
+++ b/contrib/ipfilter/FreeBSD-4.0/unkinstall
@@ -3,6 +3,7 @@
#
set dir=`pwd`
set karch=`uname -m`
+set krev=`uname -r|sed -e 's/\([0-9\.]*\)-.*/\1/'`
if ( -d /sys/arch/$karch ) set archdir="/sys/arch/$karch"
if ( -d /sys/$karch ) set archdir="/sys/$karch"
set confdir="$archdir/conf"
@@ -21,7 +22,7 @@ echo "Removing link from /usr/include/osreldate.h to /sys/sys/osreldate.h"
rm /sys/sys/osreldate.h
echo "Removing patch to ip6_input.c and ip6_output.c"
-cat FreeBSD-4.0/ipv6-patch | (cd /sys/netinet6; patch -R)
+cat FreeBSD-4.0/ipv6-patch-$krev | (cd /sys/netinet6; patch -R)
set config=`(cd $confdir; /bin/ls -1t [0-9A-Z_]*) | head -1`
echo -n "Kernel configuration to update [$config] "
diff --git a/contrib/ipfilter/HISTORY b/contrib/ipfilter/HISTORY
index da1594d..09f21ee 100644
--- a/contrib/ipfilter/HISTORY
+++ b/contrib/ipfilter/HISTORY
@@ -6,9 +6,11 @@
# in providing a very available location for the IP Filter home page and
# distribution center.
#
-# Thanks to Tel.Net Media for allowing me to maintain and further develop
-# IP Filter as part of my job and supplying Sun equipment for testing the
-# move to 64bits and Gigabit Ethernet.
+# Thanks to Hewlett Packard for making it possible to port IP Filter to
+# HP-UX 11.00.
+#
+# Thanks to Tel.Net Media for supplying me with equipment to ensure that
+# IP Filter continues to work on Solaris/sparc64.
#
# Thanks to BSDI for providing object files for BSD/OS 3.1 and the means
# to further support development of IP Filter under BSDI.
@@ -20,6 +22,50 @@
# and especially those who have found the time to port IP Filter to new
# platforms.
#
+3.4.12 26/10/2000 - Released
+
+fix installing into FreeBSD-4.1
+
+fix FTP proxy bug where it'd hang and make NAT slightly more efficient
+
+fix general compiling errors/warnings on various platforms
+
+don't access ICMP data fields that aren't there
+
+3.4.11 09/10/2000 - Released
+
+return NULL for IPv6 access control lists if it is disabled rather than
+random garbage.
+
+fix for getting protocol & packet length for IPv6 packets for pullup.
+
+update plog script from version 0.8 to version 0.10
+
+patch from Frank Volf adding fix_datacksum() to NAT code, enhancing the
+capabilities for "fixing" checksums.
+
+3.4.10 03/09/2000 - Released
+
+merge patch from Frank Volf for ICMP nat handling of TCP/UDP data `errors'
+
+getline() adjusts linenum now
+
+add tcphalfclosed timeout
+
+fill in icmp_nextmtu field if it is defined on the platform
+
+RST generation fix from guido
+
+force 32bit compile for gcc on solaris if it can't generate 64bit code
+
+encase logging when fr_chksrc == 2 in #ifdef IPFILTER_LOG
+
+fix up line wrap problems in plog script
+
+fix ICMP packet handling to not drop valid ICMP errors
+
+freebsd 5.0 compat changes
+
3.4.9 08/08/2000 - Released
implement new aging mechanism in fr_tcp_age()
diff --git a/contrib/ipfilter/Makefile b/contrib/ipfilter/Makefile
index 947c3b6..e79eb12 100644
--- a/contrib/ipfilter/Makefile
+++ b/contrib/ipfilter/Makefile
@@ -5,7 +5,7 @@
# provided that this notice is preserved and due credit is given
# to the original author and the contributors.
#
-# $Id: Makefile,v 2.11.2.3 2000/08/05 14:50:00 darrenr Exp $
+# $Id: Makefile,v 2.11.2.4 2000/10/19 15:42:56 darrenr Exp $
#
BINDEST=/usr/local/bin
SBINDEST=/sbin
@@ -16,7 +16,7 @@ CC=gcc -Wstrict-prototypes -Wmissing-prototypes
#CC=cc -Dconst=
DEBUG=-g
TOP=../..
-CFLAGS=-I$$(TOP) -g
+CFLAGS=-I$$(TOP)
CPU=`uname -m`
CPUDIR=`uname -s|sed -e 's@/@@g'`-`uname -r`-`uname -m`
#
@@ -169,8 +169,8 @@ bsdi bsdos: include
irix IRIX: include
make setup "TARGOS=IRIX" "CPUDIR=$(CPUDIR)"
- (cd IRIX/$(CPUDIR); smake build TOP=../.. $(DEST) $(MFLAGS); cd ..)
- (cd IRIX/$(CPUDIR); make -f Makefile.ipsend TOP=../.. $(DEST) $(MFLAGS); cd ..)
+ -(SMAKE=`which smake >/dev/null 2>&1; if [ $$? -ne 0 ] ; then echo make -f Makefile.std; else echo smake; fi`; cd IRIX/$(CPUDIR); $${SMAKE} build TOP=../.. $(DEST) $(MFLAGS); cd ..)
+ -(SMAKE=`which smake >/dev/null 2>&1; if [ $$? -ne 0 ] ; then echo make -f Makefile.ipsend.std; else echo smake -f Makefile.ipsend; fi`; cd IRIX/$(CPUDIR); $${SMAKE} TOP=../.. $(DEST) $(MFLAGS); cd ..)
linux: include
make setup "TARGOS=Linux" "CPUDIR=$(CPUDIR)"
@@ -184,6 +184,14 @@ setup:
-if [ ! -d $(TARGOS)/$(CPUDIR) ] ; then mkdir $(TARGOS)/$(CPUDIR); fi
-rm -f $(TARGOS)/$(CPUDIR)/Makefile $(TARGOS)/$(CPUDIR)/Makefile.ipsend
-ln -s ../Makefile $(TARGOS)/$(CPUDIR)/Makefile
+ -if [ ! -f $(TARGOS)/$(CPUDIR)/Makefile.std -a \
+ -f $(TARGOS)/Makefile.std ] ; then \
+ ln -s ../Makefile.std $(TARGOS)/$(CPUDIR)/Makefile.std; \
+ fi
+ -if [ ! -f $(TARGOS)/$(CPUDIR)/Makefile.ipsend.std -a \
+ -f $(TARGOS)/Makefile.ipsend.std ] ; then \
+ ln -s ../Makefile.ipsend.std $(TARGOS)/$(CPUDIR)/Makefile.ipsend.std; \
+ fi
-ln -s ../Makefile.ipsend $(TARGOS)/$(CPUDIR)/Makefile.ipsend
clean: clean-include
diff --git a/contrib/ipfilter/common.c b/contrib/ipfilter/common.c
index 935f3fb..d7706bd 100644
--- a/contrib/ipfilter/common.c
+++ b/contrib/ipfilter/common.c
@@ -274,7 +274,7 @@ int linenum;
return 0;
if (!strcasecmp(**seg, "port") && *(*seg + 1) && *(*seg + 2)) {
(*seg)++;
- if (isdigit(***seg) && *(*seg + 2)) {
+ if (isalnum(***seg) && *(*seg + 2)) {
if (portnum(**seg, pp, linenum) == 0)
return -1;
(*seg)++;
diff --git a/contrib/ipfilter/fil.c b/contrib/ipfilter/fil.c
index 91b5108..b85dcf4 100644
--- a/contrib/ipfilter/fil.c
+++ b/contrib/ipfilter/fil.c
@@ -7,7 +7,7 @@
*/
#if !defined(lint)
static const char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-2000 Darren Reed";
-static const char rcsid[] = "@(#)$Id: fil.c,v 2.35.2.20 2000/08/13 04:15:43 darrenr Exp $";
+static const char rcsid[] = "@(#)$Id: fil.c,v 2.35.2.26 2000/10/24 11:58:17 darrenr Exp $";
#endif
#include <sys/errno.h>
@@ -274,6 +274,16 @@ fr_info_t *fin;
int minicmpsz = sizeof(struct icmp);
icmphdr_t *icmp;
+ if (fin->fin_dlen > 1)
+ fin->fin_data[0] = *(u_short *)tcp;
+
+ if ((!(plen >= hlen + minicmpsz) && !off) ||
+ (off && off < sizeof(struct icmp))) {
+ fi->fi_fl |= FI_SHORT;
+ if (fin->fin_dlen < 2)
+ break;
+ }
+
icmp = (icmphdr_t *)tcp;
if (!off && (icmp->icmp_type == ICMP_ECHOREPLY ||
@@ -291,11 +301,6 @@ fr_info_t *fin;
icmp->icmp_type == ICMP_MASKREPLY))
minicmpsz = 12;
- if ((!(plen >= hlen + minicmpsz) && !off) ||
- (off && off < sizeof(struct icmp)))
- fi->fi_fl |= FI_SHORT;
- if (fin->fin_dlen > 1)
- fin->fin_data[0] = *(u_short *)tcp;
break;
}
case IPPROTO_TCP :
@@ -740,6 +745,7 @@ int out;
#ifdef _KERNEL
mb_t *mc = NULL;
+ int p, len;
# if !defined(__SVR4) && !defined(__svr4__)
# ifdef __sgi
char hbuf[(0xf << 2) + sizeof(struct icmp) + sizeof(ip_t) + 8];
@@ -764,13 +770,26 @@ int out;
}
# endif /* CSUM_DELAY_DATA */
+# ifdef USE_INET6
+ if (v == 6) {
+ len = ntohs(((ip6_t*)ip)->ip6_plen);
+ p = ((ip6_t *)ip)->ip6_nxt;
+ } else
+# endif
+ {
+ p = ip->ip_p;
+ len = ip->ip_len;
+ }
- if ((ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP ||
- ip->ip_p == IPPROTO_ICMP)) {
+ if ((p == IPPROTO_TCP || p == IPPROTO_UDP || p == IPPROTO_ICMP
+# ifdef USE_INET6
+ || (v == 6 && p == IPPROTO_ICMPV6)
+# endif
+ )) {
int plen = 0;
- if ((ip->ip_off & IP_OFFMASK) == 0)
- switch(ip->ip_p)
+ if ((v == 6) || (ip->ip_off & IP_OFFMASK) == 0)
+ switch(p)
{
case IPPROTO_TCP:
plen = sizeof(tcphdr_t);
@@ -780,10 +799,13 @@ int out;
break;
/* 96 - enough for complete ICMP error IP header */
case IPPROTO_ICMP:
+# ifdef USE_INET6
+ case IPPROTO_ICMPV6 :
+# endif
plen = ICMPERR_MAXPKTLEN - sizeof(ip_t);
break;
}
- up = MIN(hlen + plen, ip->ip_len);
+ up = MIN(hlen + plen, len);
if (up > m->m_len) {
# ifdef __sgi
@@ -830,8 +852,8 @@ int out;
ip->ip_id = ntohs(ip->ip_id);
changed = 0;
- fin->fin_v = v;
fin->fin_ifp = ifp;
+ fin->fin_v = v;
fin->fin_out = out;
fin->fin_mp = mp;
fr_makefrip(hlen, ip, fin);
@@ -1376,7 +1398,7 @@ nodata:
* SUCH DAMAGE.
*
* @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94
- * $Id: fil.c,v 2.35.2.20 2000/08/13 04:15:43 darrenr Exp $
+ * $Id: fil.c,v 2.35.2.26 2000/10/24 11:58:17 darrenr Exp $
*/
/*
* Copy data from an mbuf chain starting "off" bytes from the beginning,
@@ -1855,7 +1877,7 @@ size_t c;
int err;
#if SOLARIS
- if (copyin(a, &ca, sizeof(ca)))
+ if (copyin(a, (char *)&ca, sizeof(ca)))
return EFAULT;
#else
bcopy(a, &ca, sizeof(ca));
@@ -1875,7 +1897,7 @@ size_t c;
int err;
#if SOLARIS
- if (copyin(b, &ca, sizeof(ca)))
+ if (copyin(b, (char *)&ca, sizeof(ca)))
return EFAULT;
#else
bcopy(b, &ca, sizeof(ca));
@@ -1969,6 +1991,15 @@ friostat_t *fiop;
fiop->f_acctin6[1] = ipacct6[0][1];
fiop->f_acctout6[0] = ipacct6[1][0];
fiop->f_acctout6[1] = ipacct6[1][1];
+#else
+ fiop->f_fin6[0] = NULL;
+ fiop->f_fin6[1] = NULL;
+ fiop->f_fout6[0] = NULL;
+ fiop->f_fout6[1] = NULL;
+ fiop->f_acctin6[0] = NULL;
+ fiop->f_acctin6[1] = NULL;
+ fiop->f_acctout6[0] = NULL;
+ fiop->f_acctout6[1] = NULL;
#endif
fiop->f_active = fr_active;
fiop->f_froute[0] = ipl_frouteok[0];
diff --git a/contrib/ipfilter/ip_auth.h b/contrib/ipfilter/ip_auth.h
index b543318..681a6e5 100644
--- a/contrib/ipfilter/ip_auth.h
+++ b/contrib/ipfilter/ip_auth.h
@@ -5,7 +5,7 @@
* provided that this notice is preserved and due credit is given
* to the original author and the contributors.
*
- * $Id: ip_auth.h,v 2.3.2.1 2000/05/22 10:26:11 darrenr Exp $
+ * $Id: ip_auth.h,v 2.3.2.2 2000/10/19 15:38:44 darrenr Exp $
*
*/
#ifndef __IP_AUTH_H__
@@ -46,8 +46,6 @@ typedef struct fr_authstat {
extern frentry_t *ipauth;
extern struct fr_authstat fr_authstats;
extern int fr_defaultauthage;
-extern int fr_authstart;
-extern int fr_authend;
extern int fr_authsize;
extern int fr_authused;
extern int fr_auth_lock;
diff --git a/contrib/ipfilter/ip_compat.h b/contrib/ipfilter/ip_compat.h
index ba9e014..2369cf0 100644
--- a/contrib/ipfilter/ip_compat.h
+++ b/contrib/ipfilter/ip_compat.h
@@ -6,7 +6,7 @@
* to the original author and the contributors.
*
* @(#)ip_compat.h 1.8 1/14/96
- * $Id: ip_compat.h,v 2.26.2.4 2000/08/13 03:51:03 darrenr Exp $
+ * $Id: ip_compat.h,v 2.26.2.6 2000/10/19 15:39:05 darrenr Exp $
*/
#ifndef __IP_COMPAT_H__
@@ -263,6 +263,12 @@ union i6addr {
#if defined(__FreeBSD__) && (defined(KERNEL) || defined(_KERNEL))
+# ifdef IPFILTER_LKM
+# include <osreldate.h>
+# define ACTUALLY_LKM_NOT_KERNEL
+# else
+# include <sys/osreldate.h>
+# endif
# if __FreeBSD__ < 3
# include <machine/spl.h>
# else
@@ -288,6 +294,19 @@ union i6addr {
# define ATOMIC_DEC32 ATOMIC_DEC
# define ATOMIC_DEC16 ATOMIC_DEC
#endif
+#ifdef __sgi
+# define hz HZ
+# include <sys/ksynch.h>
+# define IPF_LOCK_PL plhi
+# include <sys/sema.h>
+#undef kmutex_t
+typedef struct {
+ lock_t *l;
+ int pl;
+} kmutex_t;
+# undef MUTEX_INIT
+# undef MUTEX_DESTROY
+#endif
#ifdef KERNEL
# if SOLARIS
# if SOLARIS2 >= 6
@@ -337,8 +356,8 @@ union i6addr {
# define MUTEX_DESTROY(x) mutex_destroy(x)
# define MUTEX_EXIT(x) mutex_exit(x)
# define MTOD(m,t) (t)((m)->b_rptr)
-# define IRCOPY(a,b,c) copyin((a), (b), (c))
-# define IWCOPY(a,b,c) copyout((a), (b), (c))
+# define IRCOPY(a,b,c) copyin((caddr_t)(a), (caddr_t)(b), (c))
+# define IWCOPY(a,b,c) copyout((caddr_t)(a), (caddr_t)(b), (c))
# define IRCOPYPTR ircopyptr
# define IWCOPYPTR iwcopyptr
# define FREE_MB_T(m) freemsg(m)
@@ -383,15 +402,6 @@ extern ill_t *get_unit __P((char *, int));
# 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>
-#undef kmutex_t
-typedef struct {
- lock_t *l;
- int pl;
-} kmutex_t;
# define ATOMIC_INC(x) { MUTEX_ENTER(&ipf_rw); \
(x)++; MUTEX_EXIT(&ipf_rw); }
# define ATOMIC_DEC(x) { MUTEX_ENTER(&ipf_rw); \
@@ -404,8 +414,8 @@ typedef struct {
# define MUTEX_DOWNGRADE(x) ;
# define RWLOCK_EXIT(x) MUTEX_EXIT(x)
# define MUTEX_EXIT(x) UNLOCK((x)->l, (x)->pl);
-# define MUTEX_INIT(x,y,z) (x).l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP)
-# define MUTEX_DESTROY(x) LOCK_DEALLOC((x).l)
+# define MUTEX_INIT(x,y,z) (x)->l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP)
+# define MUTEX_DESTROY(x) LOCK_DEALLOC((x)->l)
# else /* __sgi */
# define ATOMIC_INC(x) (x)++
# define ATOMIC_DEC(x) (x)--
diff --git a/contrib/ipfilter/ip_fil.c b/contrib/ipfilter/ip_fil.c
index 2e8af26..9253775 100644
--- a/contrib/ipfilter/ip_fil.c
+++ b/contrib/ipfilter/ip_fil.c
@@ -7,7 +7,7 @@
*/
#if !defined(lint)
static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed";
-static const char rcsid[] = "@(#)$Id: ip_fil.c,v 2.42.2.15 2000/08/05 14:49:08 darrenr Exp $";
+static const char rcsid[] = "@(#)$Id: ip_fil.c,v 2.42.2.17 2000/10/19 15:39:42 darrenr Exp $";
#endif
#ifndef SOLARIS
@@ -171,6 +171,9 @@ struct callout_handle ipfr_slowtimer_ch;
# include <sys/callout.h>
struct callout ipfr_slowtimer_ch;
#endif
+#if defined(__sgi) && defined(_KERNEL)
+toid_t ipfr_slowtimer_ch;
+#endif
#if (_BSDI_VERSION >= 199510) && defined(_KERNEL)
# include <sys/device.h>
@@ -318,7 +321,7 @@ pfil_error:
callout_init(&ipfr_slowtimer_ch);
callout_reset(&ipfr_slowtimer_ch, hz / 2, ipfr_slowtimer, NULL);
# else
-# if (__FreeBSD_version >= 300000) && defined(_KERNEL)
+# if (__FreeBSD_version >= 300000) || defined(__sgi)
ipfr_slowtimer_ch = timeout(ipfr_slowtimer, NULL, hz/2);
# else
timeout(ipfr_slowtimer, NULL, hz/2);
@@ -348,7 +351,7 @@ int ipldetach()
untimeout(ipfr_slowtimer, NULL, ipfr_slowtimer_ch);
# else
# ifdef __sgi
- untimeout(ipfr_slowtimer);
+ untimeout(ipfr_slowtimer_ch);
# else
untimeout(ipfr_slowtimer, NULL);
# endif
@@ -975,8 +978,10 @@ fr_info_t *fin;
if (m == NULL)
return -1;
- if (tcp->th_flags & TH_SYN)
- tlen = 1;
+ tlen = oip->ip_len - fin->fin_hlen - (tcp->th_off << 2) +
+ ((tcp->th_flags & TH_SYN) ? 1 : 0) +
+ ((tcp->th_flags & TH_FIN) ? 1 : 0);
+
#ifdef USE_INET6
hlen = (fin->fin_v == 6) ? sizeof(ip6_t) : sizeof(ip_t);
#else
@@ -997,11 +1002,16 @@ fr_info_t *fin;
tcp2->th_sport = tcp->th_dport;
tcp2->th_dport = tcp->th_sport;
- tcp2->th_ack = ntohl(tcp->th_seq);
- tcp2->th_ack += tlen;
- tcp2->th_ack = htonl(tcp2->th_ack);
+ if (tcp->th_flags & TH_ACK) {
+ tcp2->th_seq = tcp->th_ack;
+ tcp2->th_flags = TH_RST;
+ } else {
+ tcp2->th_ack = ntohl(tcp->th_seq);
+ tcp2->th_ack += tlen;
+ tcp2->th_ack = htonl(tcp2->th_ack);
+ tcp2->th_flags = TH_RST|TH_ACK;
+ }
tcp2->th_off = sizeof(*tcp2) >> 2;
- tcp2->th_flags = TH_RST|TH_ACK;
# ifdef USE_INET6
if (fin->fin_v == 6) {
ip6->ip6_plen = htons(sizeof(struct tcphdr));
@@ -1143,7 +1153,12 @@ int dst;
m_freem(m);
return ENOBUFS;
}
+# ifdef M_TRAILINGSPACE
+ m->m_len = 0;
+ avail = M_TRAILINGSPACE(m);
+# else
avail = (m->m_flags & M_EXT) ? MCLBYTES : MHLEN;
+# endif
xtra = MIN(ntohs(oip6->ip6_plen) + sizeof(ip6_t),
avail - hlen - sizeof(*icmp) - max_linkhdr);
if (dst == 0) {
@@ -1177,6 +1192,12 @@ int dst;
icmp->icmp_type = type;
icmp->icmp_code = fin->fin_icode;
icmp->icmp_cksum = 0;
+#ifdef icmp_nextmtu
+ if (type == ICMP_UNREACH &&
+ fin->fin_icode == ICMP_UNREACH_NEEDFRAG && ifp)
+ icmp->icmp_nextmtu = htons(((struct ifnet *) ifp)->if_mtu);
+#endif
+
if (avail) {
bcopy((char *)oip, (char *)&icmp->icmp_ip, MIN(ohlen, avail));
avail -= MIN(ohlen, avail);
diff --git a/contrib/ipfilter/ip_frag.c b/contrib/ipfilter/ip_frag.c
index 5019c60..1cb86c1 100644
--- a/contrib/ipfilter/ip_frag.c
+++ b/contrib/ipfilter/ip_frag.c
@@ -7,7 +7,7 @@
*/
#if !defined(lint)
static const char sccsid[] = "@(#)ip_frag.c 1.11 3/24/96 (C) 1993-2000 Darren Reed";
-static const char rcsid[] = "@(#)$Id: ip_frag.c,v 2.10.2.4 2000/06/06 15:49:15 darrenr Exp $";
+static const char rcsid[] = "@(#)$Id: ip_frag.c,v 2.10.2.5 2000/10/19 15:39:58 darrenr Exp $";
#endif
#if defined(KERNEL) && !defined(_KERNEL)
@@ -214,7 +214,7 @@ u_int pass;
ipfr_t *ipf;
if ((ip->ip_v != 4) || (fr_frag_lock))
- return NULL;
+ return -1;
WRITE_ENTER(&ipf_frag);
ipf = ipfr_new(ip, fin, pass, ipfr_heads);
RWLOCK_EXIT(&ipf_frag);
@@ -231,7 +231,7 @@ nat_t *nat;
ipfr_t *ipf;
if ((ip->ip_v != 4) || (fr_frag_lock))
- return NULL;
+ return -1;
WRITE_ENTER(&ipf_natfrag);
ipf = ipfr_new(ip, fin, pass, ipfr_nattab);
if (ipf != NULL) {
@@ -328,13 +328,16 @@ fr_info_t *fin;
ipf = ipfr_lookup(ip, fin, ipfr_nattab);
if (ipf != NULL) {
nat = ipf->ipfr_data;
- /*
- * This is the last fragment for this packet.
- */
- if ((ipf->ipfr_ttl == 1) && (nat != NULL)) {
- nat->nat_data = NULL;
- ipf->ipfr_data = NULL;
- }
+ if (nat->nat_ifp == fin->fin_ifp) {
+ /*
+ * This is the last fragment for this packet.
+ */
+ if ((ipf->ipfr_ttl == 1) && (nat != NULL)) {
+ nat->nat_data = NULL;
+ ipf->ipfr_data = NULL;
+ }
+ } else
+ nat = NULL;
} else
nat = NULL;
RWLOCK_EXIT(&ipf_natfrag);
diff --git a/contrib/ipfilter/ip_frag.h b/contrib/ipfilter/ip_frag.h
index 6a3bd2c..61b88aa 100644
--- a/contrib/ipfilter/ip_frag.h
+++ b/contrib/ipfilter/ip_frag.h
@@ -6,7 +6,7 @@
* to the original author and the contributors.
*
* @(#)ip_frag.h 1.5 3/24/96
- * $Id: ip_frag.h,v 2.4 2000/03/13 22:10:21 darrenr Exp $
+ * $Id: ip_frag.h,v 2.4.2.1 2000/10/19 15:40:13 darrenr Exp $
*/
#ifndef __IP_FRAG_H__
@@ -60,6 +60,6 @@ extern void ipfr_slowtimer __P((void *));
# endif
#else
extern int ipfr_slowtimer __P((void));
-#endif
+#endif /* (BSD >= 199306) || SOLARIS */
#endif /* __IP_FIL_H__ */
diff --git a/contrib/ipfilter/ip_ftp_pxy.c b/contrib/ipfilter/ip_ftp_pxy.c
index 84dc8b9..ffa7c1b 100644
--- a/contrib/ipfilter/ip_ftp_pxy.c
+++ b/contrib/ipfilter/ip_ftp_pxy.c
@@ -2,7 +2,7 @@
* Simple FTP transparent proxy for in-kernel use. For use with the NAT
* code.
*
- * $Id: ip_ftp_pxy.c,v 2.7.2.13 2000/08/07 12:35:27 darrenr Exp $
+ * $Id: ip_ftp_pxy.c,v 2.7.2.17 2000/10/19 15:40:40 darrenr Exp $
*/
#if SOLARIS && defined(_KERNEL)
extern kmutex_t ipf_rw;
@@ -146,6 +146,7 @@ int dlen;
} else
return 0;
a5 >>= 8;
+ a5 &= 0xff;
/*
* Calculate new address parts for PORT command
*/
@@ -214,7 +215,7 @@ int dlen;
sum2 -= sum1;
sum2 = (sum2 & 0xffff) + (sum2 >> 16);
- fix_outcksum(&ip->ip_sum, sum2, 0);
+ fix_outcksum(&ip->ip_sum, sum2);
#endif
ip->ip_len += inc;
}
@@ -441,7 +442,7 @@ int dlen;
sum2 -= sum1;
sum2 = (sum2 & 0xffff) + (sum2 >> 16);
- fix_outcksum(&ip->ip_sum, sum2, 0);
+ fix_outcksum(&ip->ip_sum, sum2);
#endif /* SOLARIS || defined(__sgi) */
ip->ip_len += inc;
}
@@ -670,15 +671,18 @@ int rv;
while ((rptr < wptr) && (*rptr != '\r'))
rptr++;
- if ((*rptr == '\r') && (rptr + 1 < wptr)) {
- if (*(rptr + 1) == '\n') {
- rptr += 2;
- f->ftps_junk = 0;
+ if (*rptr == '\r') {
+ if (rptr + 1 < wptr) {
+ if (*(rptr + 1) == '\n') {
+ rptr += 2;
+ f->ftps_junk = 0;
+ } else
+ rptr++;
} else
- rptr++;
+ break;
}
- f->ftps_rptr = rptr;
}
+ f->ftps_rptr = rptr;
if (rptr == wptr) {
rptr = wptr = f->ftps_buf;
@@ -762,5 +766,7 @@ char **ptr;
j += c - '0';
}
*ptr = s;
+ i &= 0xff;
+ j &= 0xff;
return (i << 8) | j;
}
diff --git a/contrib/ipfilter/ip_nat.c b/contrib/ipfilter/ip_nat.c
index bbcff77..d52f48d 100644
--- a/contrib/ipfilter/ip_nat.c
+++ b/contrib/ipfilter/ip_nat.c
@@ -9,7 +9,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 2.37.2.21 2000/08/12 07:32:40 darrenr Exp $";
+static const char rcsid[] = "@(#)$Id: ip_nat.c,v 2.37.2.25 2000/10/25 10:38:47 darrenr Exp $";
#endif
#if defined(__FreeBSD__) && defined(KERNEL) && !defined(_KERNEL)
@@ -118,6 +118,7 @@ u_int ipf_nattable_sz = NAT_TABLE_SZ;
u_int ipf_natrules_sz = NAT_SIZE;
u_int ipf_rdrrules_sz = RDR_SIZE;
u_int ipf_hostmap_sz = HOSTMAP_SIZE;
+int nat_wilds = 0;
u_32_t nat_masks = 0;
u_32_t rdr_masks = 0;
ipnat_t **nat_rules = NULL;
@@ -143,6 +144,7 @@ static void nat_delnat __P((struct ipnat *));
static int fr_natgetent __P((caddr_t));
static int fr_natgetsz __P((caddr_t));
static int fr_natputent __P((caddr_t));
+static void nat_tabmove __P((nat_t *, u_int));
static int nat_match __P((fr_info_t *, ipnat_t *, ip_t *));
static hostmap_t *nat_hostmap __P((ipnat_t *, struct in_addr,
struct in_addr));
@@ -300,10 +302,9 @@ struct hostmap *hm;
}
-void fix_outcksum(sp, n , len)
+void fix_outcksum(sp, n)
u_short *sp;
u_32_t n;
-int len;
{
register u_short sumshort;
register u_32_t sum1;
@@ -326,10 +327,9 @@ int len;
}
-void fix_incksum(sp, n , len)
+void fix_incksum(sp, n)
u_short *sp;
u_32_t n;
-int len;
{
register u_short sumshort;
register u_32_t sum1;
@@ -357,6 +357,38 @@ int len;
/*
+ * fix_datacksum is used *only* for the adjustments of checksums in the data
+ * section of an IP packet.
+ *
+ * The only situation in which you need to do this is when NAT'ing an
+ * ICMP error message. Such a message, contains in its body the IP header
+ * of the original IP packet, that causes the error.
+ *
+ * You can't use fix_incksum or fix_outcksum in that case, because for the
+ * kernel the data section of the ICMP error is just data, and no special
+ * processing like hardware cksum or ntohs processing have been done by the
+ * kernel on the data section.
+ */
+void fix_datacksum(sp, n)
+u_short *sp;
+u_32_t n;
+{
+ register u_short sumshort;
+ register u_32_t sum1;
+
+ if (!n)
+ return;
+
+ sum1 = (~ntohs(*sp)) & 0xffff;
+ sum1 += (n);
+ sum1 = (sum1 >> 16) + (sum1 & 0xffff);
+ /* Again */
+ sum1 = (sum1 >> 16) + (sum1 & 0xffff);
+ sumshort = ~(u_short)sum1;
+ *(sp) = htons(sumshort);
+}
+
+/*
* How the NAT is organised and works.
*
* Inside (interface y) NAT Outside (interface x)
@@ -856,8 +888,8 @@ caddr_t data;
/*
* Initialize all these so that nat_delete() doesn't cause a crash.
*/
- nat->nat_hstart[0] = NULL;
- nat->nat_hstart[1] = NULL;
+ nat->nat_phnext[0] = NULL;
+ nat->nat_phnext[1] = NULL;
fr = nat->nat_fr;
nat->nat_fr = NULL;
aps = nat->nat_aps;
@@ -969,22 +1001,16 @@ junkput:
static void nat_delete(natd)
struct nat *natd;
{
- register struct nat **natp, *nat;
struct ipnat *ipn;
- for (natp = natd->nat_hstart[0]; natp && (nat = *natp);
- natp = &nat->nat_hnext[0])
- if (nat == natd) {
- *natp = nat->nat_hnext[0];
- break;
- }
-
- for (natp = natd->nat_hstart[1]; natp && (nat = *natp);
- natp = &nat->nat_hnext[1])
- if (nat == natd) {
- *natp = nat->nat_hnext[1];
- break;
- }
+ if (natd->nat_flags & FI_WILDP)
+ nat_wilds--;
+ if (natd->nat_hnext[0])
+ natd->nat_hnext[0]->nat_phnext[0] = natd->nat_phnext[0];
+ *natd->nat_phnext[0] = natd->nat_hnext[0];
+ if (natd->nat_hnext[1])
+ natd->nat_hnext[1]->nat_phnext[1] = natd->nat_phnext[1];
+ *natd->nat_phnext[1] = natd->nat_hnext[1];
if (natd->nat_fr != NULL) {
ATOMIC_DEC32(natd->nat_fr->fr_ref);
@@ -1029,7 +1055,7 @@ static int nat_flushtable()
{
register nat_t *nat, **natp;
register int j = 0;
-
+
/*
* ALL NAT mappings deleted, so lets just make the deletions
* quicker.
@@ -1121,6 +1147,8 @@ int direction;
bzero((char *)nat, sizeof(*nat));
nat->nat_flags = flags;
+ if (flags & FI_WILDP)
+ nat_wilds++;
/*
* Search the current table for a match.
*/
@@ -1443,16 +1471,22 @@ nat_t *nat;
nat->nat_next = nat_instances;
nat_instances = nat;
+
hv = NAT_HASH_FN(nat->nat_inip.s_addr, nat->nat_inport,
ipf_nattable_sz);
natp = &nat_table[0][hv];
- nat->nat_hstart[0] = natp;
+ if (*natp)
+ (*natp)->nat_phnext[0] = &nat->nat_hnext[0];
+ nat->nat_phnext[0] = natp;
nat->nat_hnext[0] = *natp;
*natp = nat;
+
hv = NAT_HASH_FN(nat->nat_outip.s_addr, nat->nat_outport,
ipf_nattable_sz);
natp = &nat_table[1][hv];
- nat->nat_hstart[1] = natp;
+ if (*natp)
+ (*natp)->nat_phnext[1] = &nat->nat_hnext[1];
+ nat->nat_phnext[1] = natp;
nat->nat_hnext[1] = *natp;
*natp = nat;
@@ -1560,12 +1594,16 @@ int dir;
u_32_t sum1, sum2, sumd;
struct in_addr in;
icmphdr_t *icmp;
+ udphdr_t *udp;
nat_t *nat;
ip_t *oip;
int flags = 0;
if ((fin->fin_fi.fi_fl & FI_SHORT) || (ip->ip_off & IP_OFFMASK))
return NULL;
+ /*
+ * nat_icmplookup() will return NULL for `defective' packets.
+ */
if ((ip->ip_v != 4) || !(nat = nat_icmplookup(ip, fin, dir)))
return NULL;
*nflags = IPN_ICMPERR;
@@ -1575,16 +1613,33 @@ int dir;
flags = IPN_TCP;
else if (oip->ip_p == IPPROTO_UDP)
flags = IPN_UDP;
+ udp = (udphdr_t *)((((char *)oip) + (oip->ip_hl << 2)));
/*
* Need to adjust ICMP header to include the real IP#'s and
* port #'s. Only apply a checksum change relative to the
- * IP address change is it will be modified again in ip_natout
+ * IP address change as it will be modified again in ip_natout
* for both address and port. Two checksum changes are
* necessary for the two header address changes. Be careful
* to only modify the checksum once for the port # and twice
* for the IP#.
*/
+ /*
+ * Step 1
+ * Fix the IP addresses in the offending IP packet. You also need
+ * to adjust the IP header checksum of that offending IP packet
+ * and the ICMP checksum of the ICMP error message itself.
+ *
+ * Unfortunately, for UDP and TCP, the IP addresses are also contained
+ * in the pseudo header that is used to compute the UDP resp. TCP
+ * checksum. So, we must compensate that as well. Even worse, the
+ * change in the UDP and TCP checksums require yet another
+ * adjustment of the ICMP checksum of the ICMP error message.
+ *
+ * For the moment we forget about TCP, because that checksum is not
+ * in the first 8 bytes, so it will not be available in most cases.
+ */
+
if (nat->nat_dir == NAT_OUTBOUND) {
sum1 = LONG_SUM(ntohl(oip->ip_src.s_addr));
in = nat->nat_inip;
@@ -1600,19 +1655,117 @@ int dir;
CALC_SUMD(sum1, sum2, sumd);
if (nat->nat_dir == NAT_OUTBOUND) {
- fix_incksum(&oip->ip_sum, sumd, 0);
+ /*
+ * Fix IP checksum of the offending IP packet to adjust for
+ * the change in the IP address.
+ *
+ * Normally, you would expect that the ICMP checksum of the
+ * ICMP error message needs to be adjusted as well for the
+ * IP address change in oip.
+ * However, this is a NOP, because the ICMP checksum is
+ * calculated over the complete ICMP packet, which includes the
+ * changed oip IP addresses and oip->ip_sum. However, these
+ * two changes cancel each other out (if the delta for
+ * the IP address is x, then the delta for ip_sum is minus x),
+ * so no change in the icmp_cksum is necessary.
+ *
+ * Be careful that nat_dir refers to the direction of the
+ * offending IP packet (oip), not to its ICMP response (icmp)
+ */
+ fix_datacksum(&oip->ip_sum, sumd);
- sumd += (sumd & 0xffff);
- while (sumd > 0xffff)
- sumd = (sumd & 0xffff) + (sumd >> 16);
- fix_outcksum(&icmp->icmp_cksum, sumd, 0);
+ /*
+ * Fix UDP pseudo header checksum to compensate for the
+ * IP address change.
+ */
+ if (oip->ip_p == IPPROTO_UDP && udp->uh_sum) {
+ /*
+ * The UDP checksum is optional, only adjust it
+ * if it has been set.
+ */
+ sum1 = ntohs(udp->uh_sum);
+ fix_datacksum(&udp->uh_sum, sumd);
+ sum2 = ntohs(udp->uh_sum);
+
+ /*
+ * Fix ICMP checksum to compensate the UDP
+ * checksum adjustment.
+ */
+ CALC_SUMD(sum1, sum2, sumd);
+ fix_outcksum(&icmp->icmp_cksum, sumd);
+ }
+
+#if 0
+ /*
+ * Fix TCP pseudo header checksum to compensate for the
+ * IP address change. Before we can do the change, we
+ * must make sure that oip is sufficient large to hold
+ * the TCP checksum (normally it does not!).
+ */
+ if (oip->ip_p == IPPROTO_TCP) {
+
+ }
+#endif
} else {
- fix_outcksum(&oip->ip_sum, sumd, 0);
+
+ /*
+ * Fix IP checksum of the offending IP packet to adjust for
+ * the change in the IP address.
+ *
+ * Normally, you would expect that the ICMP checksum of the
+ * ICMP error message needs to be adjusted as well for the
+ * IP address change in oip.
+ * However, this is a NOP, because the ICMP checksum is
+ * calculated over the complete ICMP packet, which includes the
+ * changed oip IP addresses and oip->ip_sum. However, these
+ * two changes cancel each other out (if the delta for
+ * the IP address is x, then the delta for ip_sum is minus x),
+ * so no change in the icmp_cksum is necessary.
+ *
+ * Be careful that nat_dir refers to the direction of the
+ * offending IP packet (oip), not to its ICMP response (icmp)
+ */
+ fix_datacksum(&oip->ip_sum, sumd);
+
+/* XXX FV : without having looked at Solaris source code, it seems unlikely
+ * that SOLARIS would compensate this in the kernel (a body of an IP packet
+ * in the data section of an ICMP packet). I have the feeling that this should
+ * be unconditional, but I'm not in a position to check.
+ */
#if !SOLARIS && !defined(__sgi)
- sumd += (sumd & 0xffff);
- while (sumd > 0xffff)
- sumd = (sumd & 0xffff) + (sumd >> 16);
- fix_incksum(&icmp->icmp_cksum, sumd, 0);
+ /*
+ * Fix UDP pseudo header checksum to compensate for the
+ * IP address change.
+ */
+ if (oip->ip_p == IPPROTO_UDP && udp->uh_sum) {
+ /*
+ * The UDP checksum is optional, only adjust it
+ * if it has been set
+ */
+ sum1 = ntohs(udp->uh_sum);
+ fix_datacksum(&udp->uh_sum, sumd);
+ sum2 = ntohs(udp->uh_sum);
+
+ /*
+ * Fix ICMP checksum to compensate the UDP
+ * checksum adjustment.
+ */
+ CALC_SUMD(sum1, sum2, sumd);
+ fix_incksum(&icmp->icmp_cksum, sumd);
+ }
+
+#if 0
+ /*
+ * Fix TCP pseudo header checksum to compensate for the
+ * IP address change. Before we can do the change, we
+ * must make sure that oip is sufficient large to hold
+ * the TCP checksum (normally it does not!).
+ */
+ if (oip->ip_p == IPPROTO_TCP) {
+
+ };
+#endif
+
#endif
}
@@ -1623,23 +1776,98 @@ int dir;
* XXX - what if this is bogus hl and we go off the end ?
* In this case, nat_icmpinlookup() will have returned NULL.
*/
- tcp = (tcphdr_t *)((((char *)oip) + (oip->ip_hl << 2)));
+ tcp = (tcphdr_t *)udp;
+
+ /*
+ * Step 2 :
+ * For offending TCP/UDP IP packets, translate the ports as
+ * well, based on the NAT specification. Of course such
+ * a change must be reflected in the ICMP checksum as well.
+ *
+ * Advance notice : Now it becomes complicated :-)
+ *
+ * Since the port fields are part of the TCP/UDP checksum
+ * of the offending IP packet, you need to adjust that checksum
+ * as well... but, if you change, you must change the icmp
+ * checksum *again*, to reflect that change.
+ *
+ * To further complicate: the TCP checksum is not in the first
+ * 8 bytes of the offending ip packet, so it most likely is not
+ * available (we might have to fix that if the encounter a
+ * device that returns more than 8 data bytes on icmp error)
+ */
if (nat->nat_dir == NAT_OUTBOUND) {
if (tcp->th_sport != nat->nat_inport) {
+ /*
+ * Fix ICMP checksum to compensate port
+ * adjustment.
+ */
sum1 = ntohs(tcp->th_sport);
sum2 = ntohs(nat->nat_inport);
CALC_SUMD(sum1, sum2, sumd);
tcp->th_sport = nat->nat_inport;
- fix_outcksum(&icmp->icmp_cksum, sumd, 0);
+ fix_outcksum(&icmp->icmp_cksum, sumd);
+
+ /*
+ * Fix udp checksum to compensate port
+ * adjustment. NOTE : the offending IP packet
+ * flows the other direction compared to the
+ * ICMP message.
+ *
+ * The UDP checksum is optional, only adjust
+ * it if it has been set.
+ */
+ if (oip->ip_p == IPPROTO_UDP && udp->uh_sum) {
+
+ sum1 = ntohs(udp->uh_sum);
+ fix_datacksum(&udp->uh_sum, sumd);
+ sum2 = ntohs(udp->uh_sum);
+
+ /*
+ * Fix ICMP checksum to
+ * compensate UDP checksum
+ * adjustment.
+ */
+ CALC_SUMD(sum1, sum2, sumd);
+ fix_outcksum(&icmp->icmp_cksum, sumd);
+ }
}
} else {
+
if (tcp->th_dport != nat->nat_outport) {
+ /*
+ * Fix ICMP checksum to compensate port
+ * adjustment.
+ */
sum1 = ntohs(tcp->th_dport);
sum2 = ntohs(nat->nat_outport);
CALC_SUMD(sum1, sum2, sumd);
tcp->th_dport = nat->nat_outport;
- fix_incksum(&icmp->icmp_cksum, sumd, 0);
+ fix_incksum(&icmp->icmp_cksum, sumd);
+
+ /*
+ * Fix udp checksum to compensate port
+ * adjustment. NOTE : the offending IP
+ * packet flows the other direction compared
+ * to the ICMP message.
+ *
+ * The UDP checksum is optional, only adjust
+ * it if it has been set.
+ */
+ if (oip->ip_p == IPPROTO_UDP && udp->uh_sum) {
+
+ sum1 = ntohs(udp->uh_sum);
+ fix_datacksum(&udp->uh_sum, sumd);
+ sum2 = ntohs(udp->uh_sum);
+
+ /*
+ * Fix ICMP checksum to compensate
+ * UDP checksum adjustment.
+ */
+ CALC_SUMD(sum1, sum2, sumd);
+ fix_incksum(&icmp->icmp_cksum, sumd);
+ }
}
}
}
@@ -1664,30 +1892,92 @@ register u_int flags, p;
struct in_addr src , mapdst;
u_32_t ports;
{
- register u_short sport, mapdport;
+ register u_short sport, dport;
register nat_t *nat;
register int nflags;
+ register u_32_t dst;
u_int hv;
- mapdport = ports >> 16;
+ dst = mapdst.s_addr;
+ dport = ports >> 16;
sport = ports & 0xffff;
flags &= IPN_TCPUDP;
- hv = NAT_HASH_FN(mapdst.s_addr, mapdport, ipf_nattable_sz);
+ hv = NAT_HASH_FN(dst, dport, ipf_nattable_sz);
nat = nat_table[1][hv];
for (; nat; nat = nat->nat_hnext[1]) {
nflags = nat->nat_flags;
if ((!ifp || ifp == nat->nat_ifp) &&
nat->nat_oip.s_addr == src.s_addr &&
- nat->nat_outip.s_addr == mapdst.s_addr &&
+ nat->nat_outip.s_addr == dst &&
(((p == 0) && (flags == (nat->nat_flags & IPN_TCPUDP)))
|| (p == nat->nat_p)) && (!flags ||
(((nat->nat_oport == sport) || (nflags & FI_W_DPORT)) &&
- ((nat->nat_outport == mapdport) ||
- (nflags & FI_W_SPORT)))))
+ ((nat->nat_outport == dport) || (nflags & FI_W_SPORT)))))
return nat;
}
- return NULL;
+ if (!nat_wilds || !(flags & IPN_TCPUDP))
+ return NULL;
+ RWLOCK_EXIT(&ipf_nat);
+ hv = NAT_HASH_FN(dst, 0, ipf_nattable_sz);
+ WRITE_ENTER(&ipf_nat);
+ nat = nat_table[1][hv];
+ for (; nat; nat = nat->nat_hnext[1]) {
+ nflags = nat->nat_flags;
+ if (ifp && ifp != nat->nat_ifp)
+ continue;
+ if (!(nflags & IPN_TCPUDP))
+ continue;
+ if (!(nflags & FI_WILDP))
+ continue;
+ if (nat->nat_oip.s_addr != src.s_addr ||
+ nat->nat_outip.s_addr != dst)
+ continue;
+ if (((nat->nat_oport == sport) || (nflags & FI_W_DPORT)) &&
+ ((nat->nat_outport == dport) || (nflags & FI_W_SPORT))) {
+ hv = NAT_HASH_FN(dst, dport, ipf_nattable_sz);
+ nat_tabmove(nat, hv);
+ break;
+ }
+ }
+ MUTEX_DOWNGRADE(&ipf_nat);
+ return nat;
+}
+
+
+static void nat_tabmove(nat, hv)
+nat_t *nat;
+u_int hv;
+{
+ nat_t **natp;
+
+ /*
+ * Remove the NAT entry from the old location
+ */
+ if (nat->nat_hnext[0])
+ nat->nat_hnext[0]->nat_phnext[0] = nat->nat_phnext[0];
+ *nat->nat_phnext[0] = nat->nat_hnext[0];
+
+ if (nat->nat_hnext[1])
+ nat->nat_hnext[0]->nat_phnext[1] = nat->nat_phnext[1];
+ *nat->nat_phnext[1] = nat->nat_hnext[1];
+
+ natp = &nat_table[0][hv];
+ if (*natp)
+ (*natp)->nat_phnext[0] = &nat->nat_hnext[0];
+ nat->nat_phnext[0] = natp;
+ nat->nat_hnext[0] = *natp;
+ *natp = nat;
+
+ /*
+ * Add into the NAT table in the new position
+ */
+ natp = &nat_table[1][hv];
+ if (*natp)
+ (*natp)->nat_phnext[1] = &nat->nat_hnext[1];
+ nat->nat_phnext[1] = natp;
+ nat->nat_hnext[1] = *natp;
+ *natp = nat;
}
@@ -1706,19 +1996,21 @@ u_32_t ports;
register u_short sport, dport;
register nat_t *nat;
register int nflags;
+ u_32_t srcip;
u_int hv;
sport = ports & 0xffff;
dport = ports >> 16;
flags &= IPN_TCPUDP;
+ srcip = src.s_addr;
- hv = NAT_HASH_FN(src.s_addr, sport, ipf_nattable_sz);
+ hv = NAT_HASH_FN(srcip, sport, ipf_nattable_sz);
nat = nat_table[0][hv];
for (; nat; nat = nat->nat_hnext[0]) {
nflags = nat->nat_flags;
if ((!ifp || ifp == nat->nat_ifp) &&
- nat->nat_inip.s_addr == src.s_addr &&
+ nat->nat_inip.s_addr == srcip &&
nat->nat_oip.s_addr == dst.s_addr &&
(((p == 0) && (flags == (nat->nat_flags & IPN_TCPUDP)))
|| (p == nat->nat_p)) && (!flags ||
@@ -1726,7 +2018,32 @@ u_32_t ports;
(nat->nat_oport == dport || nflags & FI_W_DPORT))))
return nat;
}
- return NULL;
+ if (!nat_wilds || !(flags & IPN_TCPUDP))
+ return NULL;
+ RWLOCK_EXIT(&ipf_nat);
+ hv = NAT_HASH_FN(srcip, 0, ipf_nattable_sz);
+ WRITE_ENTER(&ipf_nat);
+ nat = nat_table[0][hv];
+ for (; nat; nat = nat->nat_hnext[0]) {
+ nflags = nat->nat_flags;
+ if (ifp && ifp != nat->nat_ifp)
+ continue;
+ if (!(nflags & IPN_TCPUDP))
+ continue;
+ if (!(nflags & FI_WILDP))
+ continue;
+ if ((nat->nat_inip.s_addr != srcip) ||
+ (nat->nat_oip.s_addr != dst.s_addr))
+ continue;
+ if (((nat->nat_inport == sport) || (nflags & FI_W_DPORT)) &&
+ ((nat->nat_oport == dport) || (nflags & FI_W_SPORT))) {
+ hv = NAT_HASH_FN(srcip, sport, ipf_nattable_sz);
+ nat_tabmove(nat, hv);
+ break;
+ }
+ }
+ MUTEX_DOWNGRADE(&ipf_nat);
+ return nat;
}
@@ -1862,6 +2179,7 @@ fr_info_t *fin;
nat->nat_outport = sport;
nat->nat_flags &= ~(FI_W_DPORT|FI_W_SPORT);
nflags = nat->nat_flags;
+ nat_wilds--;
}
} else {
RWLOCK_EXIT(&ipf_nat);
@@ -1942,16 +2260,16 @@ maskloop:
CALC_SUMD(s1, s2, sumd);
if (nat->nat_dir == NAT_OUTBOUND)
- fix_incksum(&ip->ip_sum, sumd, 0);
+ fix_incksum(&ip->ip_sum, sumd);
else
- fix_outcksum(&ip->ip_sum, sumd, 0);
+ fix_outcksum(&ip->ip_sum, sumd);
}
#if SOLARIS || defined(__sgi)
else {
if (nat->nat_dir == NAT_OUTBOUND)
- fix_outcksum(&ip->ip_sum, nat->nat_ipsumd, 0);
+ fix_outcksum(&ip->ip_sum, nat->nat_ipsumd);
else
- fix_incksum(&ip->ip_sum, nat->nat_ipsumd, 0);
+ fix_incksum(&ip->ip_sum, nat->nat_ipsumd);
}
#endif
ip->ip_src = nat->nat_outip;
@@ -1995,11 +2313,9 @@ maskloop:
if (csump) {
if (nat->nat_dir == NAT_OUTBOUND)
- fix_outcksum(csump, nat->nat_sumd[1],
- ip->ip_len);
+ fix_outcksum(csump, nat->nat_sumd[1]);
else
- fix_incksum(csump, nat->nat_sumd[1],
- ip->ip_len);
+ fix_incksum(csump, nat->nat_sumd[1]);
}
}
@@ -2076,6 +2392,7 @@ fr_info_t *fin;
nat->nat_outport = dport;
nat->nat_flags &= ~(FI_W_SPORT|FI_W_DPORT);
nflags = nat->nat_flags;
+ nat_wilds--;
}
} else {
RWLOCK_EXIT(&ipf_nat);
@@ -2153,9 +2470,9 @@ maskloop:
*/
#if SOLARIS || defined(__sgi)
if (nat->nat_dir == NAT_OUTBOUND)
- fix_incksum(&ip->ip_sum, nat->nat_ipsumd, 0);
+ fix_incksum(&ip->ip_sum, nat->nat_ipsumd);
else
- fix_outcksum(&ip->ip_sum, nat->nat_ipsumd, 0);
+ fix_outcksum(&ip->ip_sum, nat->nat_ipsumd);
#endif
if (!(ip->ip_off & IP_OFFMASK) &&
!(fin->fin_fi.fi_fl & FI_SHORT)) {
@@ -2196,11 +2513,9 @@ maskloop:
if (csump) {
if (nat->nat_dir == NAT_OUTBOUND)
- fix_incksum(csump, nat->nat_sumd[0],
- 0);
+ fix_incksum(csump, nat->nat_sumd[0]);
else
- fix_outcksum(csump, nat->nat_sumd[0],
- 0);
+ fix_outcksum(csump, nat->nat_sumd[0]);
}
}
ATOMIC_INCL(nat_stats.ns_mapped[0]);
diff --git a/contrib/ipfilter/ip_nat.h b/contrib/ipfilter/ip_nat.h
index 26fed25..c2ff100 100644
--- a/contrib/ipfilter/ip_nat.h
+++ b/contrib/ipfilter/ip_nat.h
@@ -6,7 +6,7 @@
* to the original author and the contributors.
*
* @(#)ip_nat.h 1.5 2/4/96
- * $Id: ip_nat.h,v 2.17.2.6 2000/07/15 14:50:06 darrenr Exp $
+ * $Id: ip_nat.h,v 2.17.2.9 2000/10/19 15:44:04 darrenr Exp $
*/
#ifndef __IP_NAT_H__
@@ -81,7 +81,7 @@ typedef struct nat {
struct hostmap *nat_hm;
struct nat *nat_next;
struct nat *nat_hnext[2];
- struct nat **nat_hstart[2];
+ struct nat **nat_phnext[2];
void *nat_ifp;
int nat_dir;
char nat_ifname[IFNAMSIZ];
@@ -141,6 +141,11 @@ typedef struct ipnat {
#define NAT_REDIRECT 0x02
#define NAT_BIMAP (NAT_MAP|NAT_REDIRECT)
#define NAT_MAPBLK 0x04
+/* 0x100 reserved for FI_W_SPORT */
+/* 0x200 reserved for FI_W_DPORT */
+/* 0x400 reserved for FI_W_SADDR */
+/* 0x800 reserved for FI_W_DADDR */
+/* 0x1000 reserved for FI_W_NEWFR */
#define MAPBLK_MINPORT 1024 /* don't use reserved ports for src port */
#define USABLE_PORTS (65536 - MAPBLK_MINPORT)
@@ -293,7 +298,8 @@ extern int ip_natout __P((ip_t *, fr_info_t *));
extern int ip_natin __P((ip_t *, fr_info_t *));
extern void ip_natunload __P((void)), ip_natexpire __P((void));
extern void nat_log __P((struct nat *, u_int));
-extern void fix_incksum __P((u_short *, u_32_t, int));
-extern void fix_outcksum __P((u_short *, u_32_t, int));
+extern void fix_incksum __P((u_short *, u_32_t));
+extern void fix_outcksum __P((u_short *, u_32_t));
+extern void fix_datacksum __P((u_short *, u_32_t));
#endif /* __IP_NAT_H__ */
diff --git a/contrib/ipfilter/ip_raudio_pxy.c b/contrib/ipfilter/ip_raudio_pxy.c
index 18ca474..d801410 100644
--- a/contrib/ipfilter/ip_raudio_pxy.c
+++ b/contrib/ipfilter/ip_raudio_pxy.c
@@ -1,5 +1,5 @@
/*
- * $Id: ip_raudio_pxy.c,v 1.7.2.1 2000/05/06 11:19:33 darrenr Exp $
+ * $Id: ip_raudio_pxy.c,v 1.7.2.2 2000/09/03 00:23:12 darrenr Exp $
*/
#if SOLARIS && defined(_KERNEL)
extern kmutex_t ipf_rw;
@@ -171,8 +171,8 @@ nat_t *nat;
tcphdr_t *tcp, tcph, *tcp2 = &tcph;
raudio_t *rap = aps->aps_data;
struct in_addr swa, swb;
- u_int a1, a2, a3, a4;
int off, dlen, slen;
+ int a1, a2, a3, a4;
u_short sp, dp;
fr_info_t fi;
tcp_seq seq;
diff --git a/contrib/ipfilter/ip_sfil.c b/contrib/ipfilter/ip_sfil.c
index 38e5e3e..7d4ea2d 100644
--- a/contrib/ipfilter/ip_sfil.c
+++ b/contrib/ipfilter/ip_sfil.c
@@ -9,7 +9,7 @@
*/
#if !defined(lint)
static const char sccsid[] = "%W% %G% (C) 1993-2000 Darren Reed";
-static const char rcsid[] = "@(#)$Id: ip_sfil.c,v 2.23.2.6 2000/08/07 12:36:19 darrenr Exp $";
+static const char rcsid[] = "@(#)$Id: ip_sfil.c,v 2.23.2.8 2000/10/19 15:42:10 darrenr Exp $";
#endif
#include <sys/types.h>
@@ -441,7 +441,7 @@ caddr_t data;
}
group = fp->fr_group;
- if (group != NULL) {
+ if (group != 0) {
fg = fr_findgroup(group, fp->fr_flags, unit, set, NULL);
if (fg == NULL) {
error = ESRCH;
@@ -613,7 +613,7 @@ caddr_t data;
fixskip(fprev, f, 1);
f->fr_grp = NULL;
group = f->fr_grhead;
- if (group != NULL)
+ if (group != 0)
fg = fr_addgroup(group, f, unit, set);
} else
error = ENOMEM;
@@ -688,7 +688,7 @@ ip_t *oip;
fr_info_t *fin;
{
tcphdr_t *tcp, *tcp2;
- int tlen = 0, hlen;
+ int tlen, hlen;
mblk_t *m;
#ifdef USE_INET6
ip6_t *ip6, *oip6 = (ip6_t *)oip;
@@ -698,8 +698,7 @@ fr_info_t *fin;
tcp = (struct tcphdr *)fin->fin_dp;
if (tcp->th_flags & TH_RST)
return -1;
- if (tcp->th_flags & TH_SYN)
- tlen = 1;
+ tlen = (tcp->th_flags & (TH_SYN|TH_FIN)) ? 1 : 0;
#ifdef USE_INET6
if (fin->fin_v == 6)
hlen = sizeof(ip6_t);
@@ -717,8 +716,15 @@ fr_info_t *fin;
tcp2 = (struct tcphdr *)(m->b_rptr + hlen - sizeof(*tcp2));
tcp2->th_dport = tcp->th_sport;
tcp2->th_sport = tcp->th_dport;
- tcp2->th_ack = htonl(ntohl(tcp->th_seq) + tlen);
- tcp2->th_seq = tcp->th_ack;
+ if (tcp->th_flags & TH_ACK) {
+ tcp2->th_seq = tcp->th_ack;
+ tcp2->th_flags = TH_RST|TH_ACK;
+ } else {
+ tcp2->th_ack = ntohl(tcp->th_seq);
+ tcp2->th_ack += tlen;
+ tcp2->th_ack = htonl(tcp2->th_ack);
+ tcp2->th_flags = TH_RST;
+ }
tcp2->th_off = sizeof(struct tcphdr) >> 2;
tcp2->th_flags = TH_RST|TH_ACK;
@@ -791,8 +797,9 @@ int dst;
struct icmp *icmp;
mblk_t *m, *mb;
int hlen, code;
- qif_t *qif;
+ qif_t *qif;
u_short sz;
+ ill_t *il;
#ifdef USE_INET6
ip6_t *ip6, *oip6;
#endif
@@ -851,6 +858,11 @@ int dst;
icmp->icmp_type = type;
icmp->icmp_code = code;
icmp->icmp_cksum = 0;
+#ifdef icmp_nextmtu
+ if (type == ICMP_UNREACH && (il = qif->qf_ill) &&
+ fin->fin_icode == ICMP_UNREACH_NEEDFRAG)
+ icmp->icmp_nextmtu = htons(il->ill_max_frag);
+#endif
#ifdef USE_INET6
if (oip->ip_v == 6) {
diff --git a/contrib/ipfilter/ip_state.c b/contrib/ipfilter/ip_state.c
index f05c887..4f7460e 100644
--- a/contrib/ipfilter/ip_state.c
+++ b/contrib/ipfilter/ip_state.c
@@ -7,7 +7,7 @@
*/
#if !defined(lint)
static const char sccsid[] = "@(#)ip_state.c 1.8 6/5/96 (C) 1993-2000 Darren Reed";
-static const char rcsid[] = "@(#)$Id: ip_state.c,v 2.30.2.17 2000/08/08 16:01:03 darrenr Exp $";
+static const char rcsid[] = "@(#)$Id: ip_state.c,v 2.30.2.22 2000/10/26 10:41:29 darrenr Exp $";
#endif
#include <sys/errno.h>
@@ -106,6 +106,7 @@ static const char rcsid[] = "@(#)$Id: ip_state.c,v 2.30.2.17 2000/08/08 16:01:03
static ipstate_t **ips_table = NULL;
static ipstate_t *ips_list = NULL;
static int ips_num = 0;
+static int ips_wild = 0;
static ips_stat_t ips_stats;
#if (SOLARIS || defined(__sgi)) && defined(_KERNEL)
extern KRWLOCK_T ipf_state, ipf_mutex;
@@ -123,6 +124,7 @@ static int fr_state_flush __P((int));
static ips_stat_t *fr_statetstats __P((void));
static void fr_delstate __P((ipstate_t *));
static int fr_state_remove __P((caddr_t));
+static void fr_ipsmove __P((ipstate_t **, ipstate_t *, u_int));
int fr_stputent __P((caddr_t));
int fr_stgetent __P((caddr_t));
void fr_stinsert __P((ipstate_t *));
@@ -135,7 +137,8 @@ u_long fr_tcpidletimeout = FIVE_DAYS,
fr_tcpclosewait = 2 * TCP_MSL,
fr_tcplastack = 2 * TCP_MSL,
fr_tcptimeout = 2 * TCP_MSL,
- fr_tcpclosed = 1,
+ fr_tcpclosed = 120,
+ fr_tcphalfclosed = 2 * 2 * 3600, /* 2 hours */
fr_udptimeout = 240,
fr_icmptimeout = 120;
int fr_statemax = IPSTATE_MAX,
@@ -240,9 +243,12 @@ caddr_t data;
for (sp = ips_list; sp; sp = sp->is_next)
if ((sp->is_p == st.is_p) && (sp->is_v == st.is_v) &&
- !bcmp(&sp->is_src, &st.is_src, sizeof(st.is_src)) &&
- !bcmp(&sp->is_dst, &st.is_src, sizeof(st.is_dst)) &&
- !bcmp(&sp->is_ps, &st.is_ps, sizeof(st.is_ps))) {
+ !bcmp((char *)&sp->is_src, (char *)&st.is_src,
+ sizeof(st.is_src)) &&
+ !bcmp((char *)&sp->is_dst, (char *)&st.is_src,
+ sizeof(st.is_dst)) &&
+ !bcmp((char *)&sp->is_ps, (char *)&st.is_ps,
+ sizeof(st.is_ps))) {
WRITE_ENTER(&ipf_state);
#ifdef IPFILTER_LOG
ipstate_log(sp, ISL_REMOVE);
@@ -590,8 +596,8 @@ u_int flags;
hv += tcp->th_dport;
hv += tcp->th_sport;
}
- is->is_send = ntohl(tcp->th_seq) + ip->ip_len -
- fin->fin_hlen - (tcp->th_off << 2) +
+ is->is_send = ntohl(tcp->th_seq) + fin->fin_dlen -
+ (tcp->th_off << 2) +
((tcp->th_flags & TH_SYN) ? 1 : 0) +
((tcp->th_flags & TH_FIN) ? 1 : 0);
is->is_maxsend = is->is_send;
@@ -660,6 +666,8 @@ u_int flags;
is->is_flags = fin->fin_fi.fi_fl & FI_CMP;
is->is_flags |= FI_CMP << 4;
is->is_flags |= flags & (FI_WILDP|FI_WILDA);
+ if (flags & (FI_WILDP|FI_WILDA))
+ ips_wild++;
is->is_ifp[1 - out] = NULL;
is->is_ifp[out] = fin->fin_ifp;
#ifdef _KERNEL
@@ -718,6 +726,7 @@ tcphdr_t *tcp;
((tcp->th_flags & TH_SYN) ? 1 : 0) +
((tcp->th_flags & TH_FIN) ? 1 : 0);
+ MUTEX_ENTER(&is->is_lock);
if (fdata->td_end == 0) {
/*
* Must be a (outgoing) SYN-ACK in reply to a SYN.
@@ -783,12 +792,11 @@ tcphdr_t *tcp;
/*
* Nearing end of connection, start timeout.
*/
- MUTEX_ENTER(&is->is_lock);
/* source ? 0 : 1 -> !source */
fr_tcp_age(&is->is_age, is->is_state, fin, !source);
- MUTEX_EXIT(&is->is_lock);
ret = 1;
}
+ MUTEX_EXIT(&is->is_lock);
return ret;
}
@@ -892,6 +900,7 @@ tcphdr_t *tcp;
is->is_maxdend = is->is_dend + 1;
}
is->is_flags &= ~(FI_W_SPORT|FI_W_DPORT);
+ ips_wild--;
}
ret = -1;
@@ -983,7 +992,7 @@ fr_info_t *fin;
* Only a basic IP header (no options) should be with
* an ICMP error header.
*/
- if (((ip->ip_v != 4) && (ip->ip_hl != 5)) ||
+ if (((ip->ip_v != 4) || (ip->ip_hl != 5)) ||
(fin->fin_plen < ICMPERR_MINPKTLEN))
return NULL;
ic = (struct icmp *)fin->fin_dp;
@@ -1037,8 +1046,8 @@ fr_info_t *fin;
* the IP6EQ and IP6NEQ macros produce the wrong results because
* of the 'junk' in the unused part of the union
*/
- bzero(&src, sizeof(src));
- bzero(&dst, sizeof(dst));
+ bzero((char *)&src, sizeof(src));
+ bzero((char *)&dst, sizeof(dst));
if (oip->ip_p == IPPROTO_ICMP) {
icmp = (icmphdr_t *)((char *)oip + (oip->ip_hl << 2));
@@ -1158,6 +1167,38 @@ fr_info_t *fin;
return NULL;
}
+
+static void fr_ipsmove(isp, is, hv)
+ipstate_t **isp, *is;
+u_int hv;
+{
+ u_int hvm;
+
+ hvm = is->is_hv;
+ /*
+ * Remove the hash from the old location...
+ */
+ if (is->is_hnext)
+ is->is_hnext->is_phnext = isp;
+ *isp = is->is_hnext;
+ if (ips_table[hvm] == NULL)
+ ips_stats.iss_inuse--;
+
+ /*
+ * ...and put the hash in the new one.
+ */
+ hvm = hv % fr_statesize;
+ isp = &ips_table[hvm];
+ if (*isp)
+ (*isp)->is_phnext = &is->is_hnext;
+ else
+ ips_stats.iss_inuse++;
+ is->is_phnext = isp;
+ is->is_hnext = *isp;
+ *isp = is;
+}
+
+
/*
* Check if a packet has a registered state.
*/
@@ -1240,7 +1281,7 @@ fr_info_t *fin;
break;
case IPPROTO_TCP :
{
- register u_short dport = tcp->th_dport, sport = tcp->th_sport;
+ register u_short dport, sport;
register int i;
i = tcp->th_flags;
@@ -1250,57 +1291,42 @@ fr_info_t *fin;
if ((i & TH_RST) &&
((i & (TH_FIN|TH_SYN|TH_RST)) != TH_RST))
break;
+ case IPPROTO_UDP :
+ dport = tcp->th_dport;
+ sport = tcp->th_sport;
tryagain = 0;
-retry_tcp:
- hvm = hv % fr_statesize;
- WRITE_ENTER(&ipf_state);
- for (isp = &ips_table[hvm]; (is = *isp);
- isp = &is->is_hnext)
-
-
- if ((is->is_p == pr) && (is->is_v == v) &&
- fr_matchsrcdst(is, src, dst, fin, tcp)) {
- if (fr_tcpstate(is, fin, ip, tcp))
- break;
- is = NULL;
- break;
- }
- if (is != NULL)
- break;
- RWLOCK_EXIT(&ipf_state);
hv += dport;
hv += sport;
- if (tryagain == 0) {
- tryagain = 1;
- goto retry_tcp;
- }
- break;
- }
- case IPPROTO_UDP :
- {
- register u_short dport = tcp->th_dport, sport = tcp->th_sport;
-
- tryagain = 0;
-retry_udp:
- hvm = hv % fr_statesize;
- /*
- * Nothing else to match on but ports. and IP#'s
- */
READ_ENTER(&ipf_state);
- for (is = ips_table[hvm]; is; is = is->is_hnext)
+retry_tcpudp:
+ hvm = hv % fr_statesize;
+ for (isp = &ips_table[hvm]; (is = *isp); isp = &is->is_hnext)
if ((is->is_p == pr) && (is->is_v == v) &&
fr_matchsrcdst(is, src, dst, fin, tcp)) {
- is->is_age = fr_udptimeout;
+ if ((pr == IPPROTO_TCP)) {
+ if (!fr_tcpstate(is, fin, ip, tcp)) {
+ continue;
+ }
+ }
break;
}
- if (is != NULL)
+ if (is != NULL) {
+ if (tryagain &&
+ !(is->is_flags & (FI_WILDP|FI_WILDA))) {
+ hv += dport;
+ hv += sport;
+ fr_ipsmove(isp, is, hv);
+ MUTEX_DOWNGRADE(&ipf_state);
+ }
break;
+ }
RWLOCK_EXIT(&ipf_state);
- hv += dport;
- hv += sport;
- if (tryagain == 0) {
+ if (!tryagain && ips_wild) {
+ hv -= dport;
+ hv -= sport;
tryagain = 1;
- goto retry_udp;
+ WRITE_ENTER(&ipf_state);
+ goto retry_tcpudp;
}
break;
}
@@ -1357,6 +1383,8 @@ ipstate_t *is;
{
frentry_t *fr;
+ if (is->is_flags & (FI_WILDP|FI_WILDA))
+ ips_wild--;
if (is->is_next)
is->is_next->is_pnext = is->is_pnext;
*is->is_pnext = is->is_next;
@@ -1566,7 +1594,7 @@ int dir;
* SYN_RECEIVED -> FIN_WAIT_1
*/
state[dir] = TCPS_FIN_WAIT_1;
- *age = fr_tcpidletimeout; /* or fr_tcptimeout? */
+ *age = fr_tcpidletimeout;
}
break;
@@ -1578,7 +1606,7 @@ int dir;
* ESTABLISHED -> FIN_WAIT_1
*/
state[dir] = TCPS_FIN_WAIT_1;
- *age = fr_tcpidletimeout;
+ *age = fr_tcphalfclosed;
} else if (flags & TH_ACK) {
/* an ACK, should we exclude other flags here? */
if (ostate == TCPS_FIN_WAIT_1) {
@@ -1590,7 +1618,7 @@ int dir;
* a half-closed connection
*/
state[dir] = TCPS_CLOSE_WAIT;
- *age = fr_tcpidletimeout;
+ *age = fr_tcphalfclosed;
} else if (ostate < TCPS_CLOSE_WAIT)
/*
* Still a fully established connection,
@@ -1614,7 +1642,7 @@ int dir;
* closed already and we did not close our side yet;
* reset timeout
*/
- *age = fr_tcpidletimeout;
+ *age = fr_tcphalfclosed;
}
break;
@@ -1638,7 +1666,7 @@ int dir;
* other side is still active (ESTABLISHED/CLOSE_WAIT);
* continue with this half-closed connection
*/
- *age = fr_tcpidletimeout;
+ *age = fr_tcphalfclosed;
break;
case TCPS_CLOSING: /* 7 */
diff --git a/contrib/ipfilter/ip_state.h b/contrib/ipfilter/ip_state.h
index a5643af..1d1bc00 100644
--- a/contrib/ipfilter/ip_state.h
+++ b/contrib/ipfilter/ip_state.h
@@ -6,7 +6,7 @@
* to the original author and the contributors.
*
* @(#)ip_state.h 1.3 1/12/96 (C) 1995 Darren Reed
- * $Id: ip_state.h,v 2.13.2.1 2000/07/08 02:15:35 darrenr Exp $
+ * $Id: ip_state.h,v 2.13.2.2 2000/08/23 11:01:31 darrenr Exp $
*/
#ifndef __IP_STATE_H__
#define __IP_STATE_H__
@@ -173,6 +173,7 @@ extern u_long fr_tcpclosewait;
extern u_long fr_tcplastack;
extern u_long fr_tcptimeout;
extern u_long fr_tcpclosed;
+extern u_long fr_tcphalfclosed;
extern u_long fr_udptimeout;
extern u_long fr_icmptimeout;
extern int fr_state_lock;
diff --git a/contrib/ipfilter/ipf.c b/contrib/ipfilter/ipf.c
index 36448b4..355c42a 100644
--- a/contrib/ipfilter/ipf.c
+++ b/contrib/ipfilter/ipf.c
@@ -43,7 +43,7 @@
#if !defined(lint)
static const char sccsid[] = "@(#)ipf.c 1.23 6/5/96 (C) 1993-2000 Darren Reed";
-static const char rcsid[] = "@(#)$Id: ipf.c,v 2.10.2.3 2000/08/07 14:54:05 darrenr Exp $";
+static const char rcsid[] = "@(#)$Id: ipf.c,v 2.10.2.5 2000/10/25 10:37:11 darrenr Exp $";
#endif
#if SOLARIS
@@ -71,7 +71,7 @@ static void set_state __P((u_int)), showstats __P((friostat_t *));
static void packetlogon __P((char *)), swapactive __P((void));
static int opendevice __P((char *));
static void closedevice __P((void));
-static char *getline __P((char *, size_t, FILE *));
+static char *getline __P((char *, size_t, FILE *, int *));
static char *ipfname = IPL_NAME;
static void usage __P((void));
static void showversion __P((void));
@@ -252,8 +252,7 @@ char *name, *file;
exit(1);
}
- while (getline(line, sizeof(line), fp)) {
- linenum++;
+ while (getline(line, sizeof(line), fp, &linenum)) {
/*
* treat CR as EOL. LF is converted to NUL by getline().
*/
@@ -335,10 +334,11 @@ char *name, *file;
* Similar to fgets(3) but can handle '\\' and NL is converted to NUL.
* Returns NULL if error occured, EOF encounterd or input line is too long.
*/
-static char *getline(str, size, file)
+static char *getline(str, size, file, linenum)
register char *str;
size_t size;
FILE *file;
+int *linenum;
{
char *p;
int s, len;
@@ -356,6 +356,7 @@ FILE *file;
p[len] = '\0';
break;
}
+ (*linenum)++;
p[len - 1] = '\0';
if (len < 2 || p[len - 2] != '\\')
break;
@@ -568,7 +569,7 @@ static void showversion()
}
if (ioctl(vfd, SIOCGETFS, &fiop)) {
- perror("ioctl(SIOCGETFS");
+ perror("ioctl(SIOCGETFS)");
close(vfd);
return;
}
diff --git a/contrib/ipfilter/ipl.h b/contrib/ipfilter/ipl.h
index 866d34d..cfec734 100644
--- a/contrib/ipfilter/ipl.h
+++ b/contrib/ipfilter/ipl.h
@@ -6,12 +6,12 @@
* to the original author and the contributors.
*
* @(#)ipl.h 1.21 6/5/96
- * $Id: ipl.h,v 2.15.2.10 2000/08/07 15:10:09 darrenr Exp $
+ * $Id: ipl.h,v 2.15.2.13 2000/10/25 11:08:41 darrenr Exp $
*/
#ifndef __IPL_H__
#define __IPL_H__
-#define IPL_VERSION "IP Filter: v3.4.9"
+#define IPL_VERSION "IP Filter: v3.4.12"
#endif
diff --git a/contrib/ipfilter/ipmon.c b/contrib/ipfilter/ipmon.c
index bb7e75f..5f9db0b 100644
--- a/contrib/ipfilter/ipmon.c
+++ b/contrib/ipfilter/ipmon.c
@@ -7,7 +7,7 @@
*/
#if !defined(lint)
static const char sccsid[] = "@(#)ipmon.c 1.21 6/5/96 (C)1993-2000 Darren Reed";
-static const char rcsid[] = "@(#)$Id: ipmon.c,v 2.12.2.4 2000/08/07 12:32:22 darrenr Exp $";
+static const char rcsid[] = "@(#)$Id: ipmon.c,v 2.12.2.5 2000/10/19 15:41:41 darrenr Exp $";
#endif
#ifndef SOLARIS
@@ -692,7 +692,7 @@ int blen;
p = (u_short)ip->ip_p;
s = (u_32_t *)&ip->ip_src;
d = (u_32_t *)&ip->ip_dst;
- plen = ntohs(ip->ip_len);
+ plen = ip->ip_len;
} else {
goto printipflog;
}
diff --git a/contrib/ipfilter/ipsend/44arp.c b/contrib/ipfilter/ipsend/44arp.c
index f19fe5f..7a16c5a 100644
--- a/contrib/ipfilter/ipsend/44arp.c
+++ b/contrib/ipfilter/ipsend/44arp.c
@@ -67,7 +67,7 @@ char *addr, *eaddr;
struct sockaddr_dl *sdl;
#ifdef IPSEND
- if (arp_getipv4(ip, ether) == 0)
+ if (arp_getipv4(addr, ether) == 0)
return 0;
#endif
diff --git a/contrib/ipfilter/man/ipf.4 b/contrib/ipfilter/man/ipf.4
index 4549855..0e080a0 100644
--- a/contrib/ipfilter/man/ipf.4
+++ b/contrib/ipfilter/man/ipf.4
@@ -11,33 +11,33 @@ To add and delete rules to the filter list, three 'basic' ioctls are provided
for use. The ioctl's are called as:
.LP
.nf
- ioctl(fd, SIOCADDFR, struct frentry *)
- ioctl(fd, SIOCDELFR, struct frentry *)
+ ioctl(fd, SIOCADDFR, struct frentry **)
+ ioctl(fd, SIOCDELFR, struct frentry **)
ioctl(fd, SIOCIPFFL, int *)
.fi
.PP
However, the full complement is as follows:
.LP
.nf
- ioctl(fd, SIOCADAFR, struct frentry *) (same as SUICADDFR)
- ioctl(fd, SIOCRMAFR, struct frentry *) (same as SUICDELFR)
- ioctl(fd, SIOCADIFR, struct frentry *)
- ioctl(fd, SIOCRMIFR, struct frentry *)
- ioctl(fd, SIOCINAFR, struct frentry *)
- ioctl(fd, SIOCINIFR, struct frentry *)
+ ioctl(fd, SIOCADAFR, struct frentry **) (same as SIOCADDFR)
+ ioctl(fd, SIOCRMAFR, struct frentry **) (same as SIOCDELFR)
+ ioctl(fd, SIOCADIFR, struct frentry **)
+ ioctl(fd, SIOCRMIFR, struct frentry **)
+ ioctl(fd, SIOCINAFR, struct frentry **)
+ ioctl(fd, SIOCINIFR, struct frentry **)
ioctl(fd, SIOCSETFF, u_int *)
ioctl(fd, SIOGGETFF, u_int *)
- ioctl(fd, SIOCGETFS, struct friostat *)
+ ioctl(fd, SIOCGETFS, struct friostat **)
ioctl(fd, SIOCIPFFL, int *)
ioctl(fd, SIOCIPFFB, int *)
ioctl(fd, SIOCSWAPA, u_int *)
ioctl(fd, SIOCFRENB, u_int *)
ioctl(fd, SIOCFRSYN, u_int *)
- ioctl(fd, SIOCFRZST, struct friostat *)
- ioctl(fd, SIOCZRLST, struct frentry *)
- ioctl(fd, SIOCAUTHW, struct fr_info *)
- ioctl(fd, SIOCAUTHR, struct fr_info *)
- ioctl(fd, SIOCATHST, struct fr_authstat *)
+ ioctl(fd, SIOCFRZST, struct friostat **)
+ ioctl(fd, SIOCZRLST, struct frentry **)
+ ioctl(fd, SIOCAUTHW, struct fr_info **)
+ ioctl(fd, SIOCAUTHR, struct fr_info **)
+ ioctl(fd, SIOCATHST, struct fr_authstat **)
.fi
.PP
The variations, SIOCADAFR vs. SIOCADIFR, allow operation on the two lists,
@@ -107,7 +107,7 @@ filter list, the number of the rule which it is to be inserted before must
be put in the "fr_hits" field (the first rule is number 0).
.LP
.PP
-Flags which are recognised in fr_pass:
+Flags which are recognised in fr_flags:
.nf
FR_BLOCK 0x000001 /* do not allow packet to pass */
diff --git a/contrib/ipfilter/man/ipf.5 b/contrib/ipfilter/man/ipf.5
index 478d672..243edac 100644
--- a/contrib/ipfilter/man/ipf.5
+++ b/contrib/ipfilter/man/ipf.5
@@ -31,7 +31,7 @@ proto = "proto" protocol .
ip = srcdst [ flags ] [ with withopt ] [ icmp ] [ keep ] .
group = [ "head" decnumber ] [ "group" decnumber ] .
-block = "block" [ icmp[return-code] | "return-rst" ] .
+block = "block" [ return-icmp[return-code] | "return-rst" ] .
auth = "auth" | "preauth" .
log = "log" [ "body" ] [ "first" ] [ "or-block" ] [ "level" loglevel ] .
call = "call" [ "now" ] function-name .
@@ -42,7 +42,7 @@ protocol = "tcp/udp" | "udp" | "tcp" | "icmp" | decnumber .
srcdst = "all" | fromto .
fromto = "from" [ "!" ] object "to" [ "!" ] object .
-icmp = "return-icmp" | "return-icmp-as-dest" .
+return-icmp = "return-icmp" | "return-icmp-as-dest" .
object = addr [ port-comp | port-range ] .
addr = "any" | nummask | host-name [ "mask" ipaddr | "mask" hexnumber ] .
port-comp = "port" compare port-num .
diff --git a/contrib/ipfilter/man/ipmon.8 b/contrib/ipfilter/man/ipmon.8
index 61d6575..7cd98f6 100644
--- a/contrib/ipfilter/man/ipmon.8
+++ b/contrib/ipfilter/man/ipmon.8
@@ -149,7 +149,7 @@ show the packet data in hex.
show the log header record data in hex.
.SH DIAGNOSTICS
\fBipmon\fP expects data that it reads to be consistent with how it should be
-saved and will abort if it fails an assertion which detects an anomoly in the
+saved and will abort if it fails an assertion which detects an anomaly in the
recorded data.
.SH FILES
/dev/ipl
diff --git a/contrib/ipfilter/man/ipnat.4 b/contrib/ipfilter/man/ipnat.4
index ee385b7..6cba7b6 100644
--- a/contrib/ipfilter/man/ipnat.4
+++ b/contrib/ipfilter/man/ipnat.4
@@ -15,8 +15,10 @@ To add and delete rules to the NAT list, two 'basic' ioctls are provided
for use. The ioctl's are called as:
.LP
.nf
- ioctl(fd, SIOCADNAT, struct ipnat *)
- ioctl(fd, SIOCRMNAT, struct ipnat *)
+ ioctl(fd, SIOCADNAT, struct ipnat **)
+ ioctl(fd, SIOCRMNAT, struct ipnat **)
+ ioctl(fd, SIOCGNATS, struct natstat **)
+ ioctl(fd, SIOCGNATL, struct natlookup **)
.fi
.PP
Unlike \fBipf(4)\fP, there is only a single list supported by the kernel NAT
diff --git a/contrib/ipfilter/mlf_ipl.c b/contrib/ipfilter/mlf_ipl.c
index f12e989..f6e7ad4 100644
--- a/contrib/ipfilter/mlf_ipl.c
+++ b/contrib/ipfilter/mlf_ipl.c
@@ -95,6 +95,8 @@ SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_active, CTLFLAG_RD, &fr_active, 0, "");
SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_chksrc, CTLFLAG_RW, &fr_chksrc, 0, "");
SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcpidletimeout, CTLFLAG_RW,
&fr_tcpidletimeout, 0, "");
+SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcphalfclosed, CTLFLAG_RW,
+ &fr_tcphalfclosed, 0, "");
SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcpclosewait, CTLFLAG_RW,
&fr_tcpclosewait, 0, "");
SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcplastack, CTLFLAG_RW,
diff --git a/contrib/ipfilter/mlfk_ipl.c b/contrib/ipfilter/mlfk_ipl.c
index f869149..f96c57e 100644
--- a/contrib/ipfilter/mlfk_ipl.c
+++ b/contrib/ipfilter/mlfk_ipl.c
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: mlfk_ipl.c,v 2.1.2.3 2000/08/13 03:42:42 darrenr Exp $
+ * $Id: mlfk_ipl.c,v 2.1.2.4 2000/08/23 11:02:33 darrenr Exp $
*/
@@ -65,6 +65,8 @@ SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcptimeout, CTLFLAG_RW,
&fr_tcptimeout, 0, "");
SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcpclosed, CTLFLAG_RW,
&fr_tcpclosed, 0, "");
+SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcphalfclosed, CTLFLAG_RW,
+ &fr_tcphalfclosed, 0, "");
SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_udptimeout, CTLFLAG_RW,
&fr_udptimeout, 0, "");
SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_icmptimeout, CTLFLAG_RW,
diff --git a/contrib/ipfilter/perl/plog b/contrib/ipfilter/perl/plog
index b251b0c..208c6ea 100644
--- a/contrib/ipfilter/perl/plog
+++ b/contrib/ipfilter/perl/plog
@@ -1,14 +1,15 @@
#!/usr/bin/perl -wT
#
# Author: Jefferson Ogata (JO317) <jogata@pobox.com>
-# Date: 2000/04/10
-# Version: 0.8
+# Date: 2000/04/22
+# Version: 0.10
#
# Please feel free to use or redistribute this program if you find it useful.
# If you have suggestions, or even better, bits of new code, send them to me
# and I will add them when I have time. The current version of this script
# can always be found at the URL:
#
+# http://www.antibozo.net/ogata/webtools/plog.pl
# http://pobox.com/~ogata/webtools/plog.txt
#
# Parse ipmon output into a coherent form. This program only handles the
@@ -18,10 +19,10 @@
#
# EXAMPLES
#
-# plog -A block,log < /var/log/ipf
+# plog -AF block,log < /var/log/ipf
#
# Generate source and destination reports of all packets logged with
-# block or log actions.
+# block or log actions, and report TCP flags and keep state actions.
#
# plog -S -s ./services www.example.com < /var/log/ipf
#
@@ -34,6 +35,14 @@
# lookups. This is handy for an initial pass to identify portscans or
# other aggressive traffic.
#
+# plog -SFp 192.168.0.0/24 www.example.com/24 < /var/log/ipf
+#
+# Generate a source report of all packets whose source or destination
+# address is either in 192.168.0.0/24 or an address associated with
+# the host www.example.com, report packet flags and perform paranoid
+# hostname lookups. This is a handy usage for examining traffic more
+# closely after identifying a potential attack.
+#
# TODO
#
# - Handle output from ipmon -v.
@@ -44,6 +53,14 @@
#
# CHANGES
#
+# 2000/04/22 (0.10):
+# - Restructured host name and address caches. Hosts are now cached using
+# packed addresses as keys. Conversion to IPv6 should be simple now.
+# - Added paranoid hostname lookups.
+# - Added netmask qualifications for address arguments.
+# - Tweaked usage info.
+# 2000/04/20:
+# - Added parsing and tracking of TCP and state flags.
# 2000/04/12 (0.9):
# - Wasn't handling underscore in hostname,servicename fields; these may be
# logged using ipmon -n. Observation by <ark@eltex.ru>.
@@ -58,8 +75,7 @@
# slightly) from Andy Kreiling <Andy@ntcs-inc.com> and John Ladwig
# <jladwig@nts.umn.edu>.
# - Added fix to handle new Solaris log format, e.g.:
-# Nov 30 04:49:37 raoul ipmon[121]: [ID 702911 local0.warning] 04:49:36.420
-541 hme0 @0:34 b 205.152.16.6,58596 -> 204.60.220.24,113 PR tcp len 20 44
+# Nov 30 04:49:37 raoul ipmon[121]: [ID 702911 local0.warning] 04:49:36.420541 hme0 @0:34 b 205.152.16.6,58596 -> 204.60.220.24,113 PR tcp len 20 44
# Fix thanks to Taso N. Devetzis <devetzis@SNET.Net>.
# - Added services map option.
# - Added options for generating only source/destination tables.
@@ -141,219 +157,251 @@ $me =~ s/^.*\///;
# Map of log codes for various actions. Not all of these can occur, but
# I've included everything in print_ipflog() from ipmon.c.
my %acts = (
- 'p' => 'pass',
- 'P' => 'pass',
- 'b' => 'block',
- 'B' => 'block',
- 'L' => 'log',
+ 'p' => 'pass',
+ 'P' => 'pass',
+ 'b' => 'block',
+ 'B' => 'block',
+ 'L' => 'log',
'S' => 'short',
'n' => 'nomatch',
);
# Map of ICMP types and their relevant codes.
my %icmpTypeMap = (
- 0 => +{
- name => 'echorep',
- codes => +{0 => undef},
+ 0 => +{
+ name => 'echorep',
+ codes => +{0 => undef},
},
- 3 => +{
- name => 'unreach',
- codes => +{
- 0 => 'net-unr',
- 1 => 'host-unr',
- 2 => 'proto-unr',
- 3 => 'port-unr',
- 4 => 'needfrag',
- 5 => 'srcfail',
- 6 => 'net-unk',
- 7 => 'host-unk',
- 8 => 'isolate',
- 9 => 'net-prohib',
- 10 => 'host-prohib',
- 11 => 'net-tos',
- 12 => 'host-tos',
- 13 => 'filter-prohib',
- 14 => 'host-preced',
- 15 => 'preced-cutoff',
- },
+ 3 => +{
+ name => 'unreach',
+ codes => +{
+ 0 => 'net-unr',
+ 1 => 'host-unr',
+ 2 => 'proto-unr',
+ 3 => 'port-unr',
+ 4 => 'needfrag',
+ 5 => 'srcfail',
+ 6 => 'net-unk',
+ 7 => 'host-unk',
+ 8 => 'isolate',
+ 9 => 'net-prohib',
+ 10 => 'host-prohib',
+ 11 => 'net-tos',
+ 12 => 'host-tos',
+ 13 => 'filter-prohib',
+ 14 => 'host-preced',
+ 15 => 'preced-cutoff',
+ },
},
- 4 => +{
- name => 'squench',
- codes => +{0 => undef},
+ 4 => +{
+ name => 'squench',
+ codes => +{0 => undef},
},
- 5 => +{
- name => 'redir',
- codes => +{
- 0 => 'net',
- 1 => 'host',
- 2 => 'tos',
- 3 => 'tos-host',
- },
+ 5 => +{
+ name => 'redir',
+ codes => +{
+ 0 => 'net',
+ 1 => 'host',
+ 2 => 'tos',
+ 3 => 'tos-host',
+ },
},
- 6 => +{
- name => 'alt-host-addr',
- codes => +{
- 0 => 'alt-addr'
- },
+ 6 => +{
+ name => 'alt-host-addr',
+ codes => +{
+ 0 => 'alt-addr'
+ },
},
- 8 => +{
- name => 'echo',
- codes => +{0 => undef},
+ 8 => +{
+ name => 'echo',
+ codes => +{0 => undef},
},
- 9 => +{
- name => 'routerad',
- codes => +{0 => undef},
+ 9 => +{
+ name => 'routerad',
+ codes => +{0 => undef},
},
- 10 => +{
- name => 'routersol',
- codes => +{0 => undef},
+ 10 => +{
+ name => 'routersol',
+ codes => +{0 => undef},
},
- 11 => +{
- name => 'timex',
- codes => +{
- 0 => 'in-transit',
- 1 => 'frag-assy',
- },
+ 11 => +{
+ name => 'timex',
+ codes => +{
+ 0 => 'in-transit',
+ 1 => 'frag-assy',
+ },
},
- 12 => +{
- name => 'paramprob',
- codes => +{
- 0 => 'ptr-err',
- 1 => 'miss-opt',
- 2 => 'bad-len',
- },
+ 12 => +{
+ name => 'paramprob',
+ codes => +{
+ 0 => 'ptr-err',
+ 1 => 'miss-opt',
+ 2 => 'bad-len',
+ },
},
- 13 => +{
- name => 'timest',
- codes => +{0 => undef},
+ 13 => +{
+ name => 'timest',
+ codes => +{0 => undef},
},
- 14 => +{
- name => 'timestrep',
- codes => +{0 => undef},
+ 14 => +{
+ name => 'timestrep',
+ codes => +{0 => undef},
},
- 15 => +{
- name => 'inforeq',
- codes => +{0 => undef},
+ 15 => +{
+ name => 'inforeq',
+ codes => +{0 => undef},
},
- 16 => +{
- name => 'inforep',
- codes => +{0 => undef},
+ 16 => +{
+ name => 'inforep',
+ codes => +{0 => undef},
},
- 17 => +{
- name => 'maskreq',
- codes => +{0 => undef},
+ 17 => +{
+ name => 'maskreq',
+ codes => +{0 => undef},
},
- 18 => +{
- name => 'maskrep',
- codes => +{0 => undef},
+ 18 => +{
+ name => 'maskrep',
+ codes => +{0 => undef},
},
- 30 => +{
- name => 'tracert',
- codes => +{ },
+ 30 => +{
+ name => 'tracert',
+ codes => +{ },
},
- 31 => +{
- name => 'dgram-conv-err',
- codes => +{ },
+ 31 => +{
+ name => 'dgram-conv-err',
+ codes => +{ },
},
- 32 => +{
- name => 'mbl-host-redir',
- codes => +{ },
+ 32 => +{
+ name => 'mbl-host-redir',
+ codes => +{ },
},
- 33 => +{
- name => 'ipv6-whereru?',
- codes => +{ },
+ 33 => +{
+ name => 'ipv6-whereru?',
+ codes => +{ },
},
- 34 => +{
- name => 'ipv6-iamhere',
- codes => +{ },
+ 34 => +{
+ name => 'ipv6-iamhere',
+ codes => +{ },
},
- 35 => +{
- name => 'mbl-reg-req',
- codes => +{ },
+ 35 => +{
+ name => 'mbl-reg-req',
+ codes => +{ },
},
- 36 => +{
- name => 'mbl-reg-rep',
- codes => +{ },
+ 36 => +{
+ name => 'mbl-reg-rep',
+ codes => +{ },
},
);
# Arguments we will parse from argument list.
-my $numeric = 0; # Don't lookup hostnames.
-my $verbosity = 0; # Bla' bla' bla'.
-my $sTable = 0; # Generate source table.
-my $dTable = 0; # Generate destination table.
-my $services = undef; # Preload services table.
-my %selectHosts; # Limit report to these hosts.
-my %selectActs; # Limit report to these actions.
+my $numeric = 0; # Don't lookup hostnames.
+my $paranoid = 0; # Do paranoid hostname lookups.
+my $verbosity = 0; # Bla' bla' bla'.
+my $sTable = 0; # Generate source table.
+my $dTable = 0; # Generate destination table.
+my @services = (); # Preload services tables.
+my $showFlags = 0; # Show TCP flag combinations.
+my %selectAddrs; # Limit report to these hosts.
+my %selectActs; # Limit report to these actions.
# Parse argument list.
while (defined ($_ = shift))
{
if (s/^-//)
{
- while (s/^([nSD\?hsA])//)
- {
- my $flag = $1;
- if ($flag eq 'v')
- {
- ++$verbosity;
- }
- elsif ($flag eq 'n')
- {
- $numeric = 1;
- }
- elsif ($flag eq 'S')
- {
- $sTable = 1;
- }
- elsif ($flag eq 'D')
- {
- $dTable = 1;
- }
- elsif (($flag eq '?') || ($flag eq 'h'))
- {
- &usage (0);
- }
- else
- {
- my $arg = shift;
- defined ($arg) || &usage (1, qq{-$flag requires an argument});
- if ($flag eq 's')
- {
- defined ($services) && &usage (1, qq{too many service maps});
- $services = $arg;
- }
- elsif ($flag eq 'A')
- {
- my @acts = split (/,/, $arg);
- my $a;
- foreach $a (@acts)
- {
- my $aa;
- my $match = 0;
- foreach $aa (keys (%acts))
- {
- if ($acts{$aa} eq $a)
- {
- ++$match;
- $selectActs{$aa} = $a;
- }
- }
- $match || &usage (1, qq{unknown action $a});
- }
- }
- }
- }
-
- &usage (1, qq{unknown option: -$_}) if (length);
-
- next;
+ while (s/^([vnpSD\?hsAF])//)
+ {
+ my $flag = $1;
+ if ($flag eq 'v')
+ {
+ ++$verbosity;
+ }
+ elsif ($flag eq 'n')
+ {
+ $numeric = 1;
+ }
+ elsif ($flag eq 'p')
+ {
+ $paranoid = 1;
+ }
+ elsif ($flag eq 'S')
+ {
+ $sTable = 1;
+ }
+ elsif ($flag eq 'D')
+ {
+ $dTable = 1;
+ }
+ elsif ($flag eq 'F')
+ {
+ $showFlags = 1;
+ }
+ elsif (($flag eq '?') || ($flag eq 'h'))
+ {
+ &usage (0);
+ }
+ else
+ {
+ my $arg = shift;
+ defined ($arg) || &usage (1, qq{-$flag requires an argument});
+ if ($flag eq 's')
+ {
+ push (@services, $arg);
+ }
+ elsif ($flag eq 'A')
+ {
+ my @acts = split (/,/, $arg);
+ my $a;
+ foreach $a (@acts)
+ {
+ my $aa;
+ my $match = 0;
+ foreach $aa (keys (%acts))
+ {
+ if ($acts{$aa} eq $a)
+ {
+ ++$match;
+ $selectActs{$aa} = $a;
+ }
+ }
+ $match || &usage (1, qq{unknown action $a});
+ }
+ }
+ }
+ }
+
+ &usage (1, qq{unknown option: -$_}) if (length);
+
+ next;
}
# Add host to hash of hosts we're interested in.
- my $addr = &hostNumber ($_);
- defined ($addr) || &usage (1, qq{cannot resolve hostname $_});
- $selectHosts{$addr} = undef;
+ (/^(.+)\/([\d+\.]+)$/) || (/^(.+)$/) || &usage (1, qq{invalid CIDR address $_});
+ my ($addr, $mask) = ($1, $2);
+ my @addr = &hostAddrs ($addr);
+ (scalar (@addr)) || &usage (1, qq{cannot resolve hostname $_});
+ if (!defined ($mask))
+ {
+ $mask = (2 ** 32) - 1;
+ }
+ elsif (($mask =~ /^\d+$/) && ($mask <= 32))
+ {
+ $mask = (2 ** 32) - 1 - ((2 ** (32 - $mask)) - 1);
+ }
+ elsif (defined ($mask = &isDottedAddr ($mask)))
+ {
+ $mask = &integerAddr ($mask);
+ }
+ else
+ {
+ &usage (1, qq{invalid CIDR address $_});
+ }
+ foreach $addr (@addr)
+ {
+ # Save mask unless we already have a less specific one for this address.
+ my $a = &integerAddr ($addr) & $mask;
+ $selectAddrs{$a} = $mask unless (exists ($selectAddrs{$a}) && ($selectAddrs{$a} < $mask));
+ }
}
# Which tables will we generate?
@@ -363,7 +411,7 @@ push (@dirs, 'd') if ($dTable);
push (@dirs, 's') if ($sTable);
# Are we interested in specific hosts?
-my $selectHosts = scalar (keys (%selectHosts));
+my $selectAddrs = scalar (keys (%selectAddrs));
# Are we interested in specific actions?
if (scalar (keys (%selectActs)) == 0)
@@ -375,42 +423,45 @@ if (scalar (keys (%selectActs)) == 0)
# Isn't it cool that we can use the same hash for both?
my %pn;
-# Preload any services map.
-if (defined ($services))
+# Preload any services maps.
+my $sm;
+foreach $sm (@services)
{
- my $sf = new IO::File ($services, "r");
- defined ($sf) || &quit (1, qq{cannot open services file $services});
+ my $sf = new IO::File ($sm, "r");
+ defined ($sf) || &quit (1, qq{cannot open services file $sm});
while (defined ($_ = $sf->getline ()))
{
- my $text = $_;
- chomp;
- s/#.*$//;
- s/\s+$//;
- next unless (length);
- my ($name, $spec, @aliases) = split (/\s+/);
- ($spec =~ /^([\w\-]+)\/([\w\-]+)$/)
- || &quit (1, qq{$services:$.: invalid definition: $text});
- my ($pnum, $proto) = ($1, $2);
-
- # Enter service definition in pn hash both forwards and backwards.
- my $port;
- my $pname;
- foreach $port ($name, @aliases)
- {
- $pname = "$pnum/$proto";
- $pn{$pname} = $port;
- }
- $pname = "$name/$proto";
- $pn{$pname} = $pnum;
+ my $text = $_;
+ chomp;
+ s/#.*$//;
+ s/\s+$//;
+ next unless (length);
+ my ($name, $spec, @aliases) = split (/\s+/);
+ ($spec =~ /^([\w\-]+)\/([\w\-]+)$/)
+ || &quit (1, qq{$sm:$.: invalid definition: $text});
+ my ($pnum, $proto) = ($1, $2);
+
+ # Enter service definition in pn hash both forwards and backwards.
+ my $port;
+ my $pname;
+ foreach $port ($name, @aliases)
+ {
+ $pname = "$pnum/$proto";
+ $pn{$pname} = $port;
+ }
+ $pname = "$name/$proto";
+ $pn{$pname} = $pnum;
}
$sf->close ();
}
-# Again, we can use the same hash for both host name -> IP mappings and
-# IP -> name mappings.
-my %ip;
+# Cache for host name -> addr mappings.
+my %ipAddr;
+
+# Cache for host addr -> name mappings.
+my %ipName;
# Hash for protocol number <--> name mappings.
my %pr;
@@ -434,16 +485,16 @@ while (<STDIN>)
my ($log);
if (s/^\w+\s+\d+\s+\d+:\d+:\d+\s+(?:\d\w:)?[\w\.\-]+\s+\S*ipmon\[\d+\]:\s+(?:\[ID\s+\d+\s+[\w\.]+\]\s+)?\d+:\d+:\d+\.\d+\s+//)
{
- $log = $_;
+ $log = $_;
}
elsif (s/^(?:\d+\/\d+\/\d+)\s+(?:\d+:\d+:\d+\.\d+)\s+//)
{
- $log = $_;
+ $log = $_;
}
else
{
- # It don't look like no ipmon output to me, baby.
- next;
+ # It don't look like no ipmon output to me, baby.
+ next;
}
next unless (defined ($log));
@@ -455,11 +506,11 @@ while (<STDIN>)
# number, "PR", a protocol name or number, "len", a header length, a
# packet length (which will be in parentheses for protocols other than
# TCP, UDP, or ICMP), and maybe some additional info.
- my @fields = ($log =~ /^(?:(\d+)x)?\s*(\w+)\s+@(\d+):(\d+)\s+(\w)\s+([\w\-\..,]+)\s+->\s+([\w\-\.,]+)\s+PR\s+(\w+)\s+len\s+(\d+)\s+\(?(\d+)\)?\s*(.*)$/ox);
+ my @fields = ($log =~ /^(?:(\d+)x)?\s*(\w+)\s+@(\d+):(\d+)\s+(\w)\s+([\w\-\.,]+)\s+->\s+([\w\-\.,]+)\s+PR\s+(\w+)\s+len\s+(\d+)\s+\(?(\d+)\)?\s*(.*)$/ox);
unless (scalar (@fields))
{
- print STDERR "$me:$.: cannot parse: $_\n";
- next;
+ print STDERR "$me:$.: cannot parse: $_\n";
+ next;
}
my ($count, $if, $group, $rule, $act, $src, $dest, $proto, $hlen, $len, $more) = @fields;
@@ -469,102 +520,131 @@ while (<STDIN>)
# Packet count defaults to 1.
$count = 1 unless (defined ($count));
- my ($sport, $dport);
+ my ($sport, $dport, @flags);
if ($proto eq 'icmp')
{
- if ($more =~ s/^icmp (\d+)\/(\d+)\s*//)
- {
- # We save icmp type and code in both sport and dport. This
- # allows us to sort icmp packets using the normal port-sorting
- # code.
- $dport = $sport = "$1.$2";
- }
- else
- {
- $sport = '';
- $dport = '';
- }
+ if ($more =~ s/^icmp (\d+)\/(\d+)\s*//)
+ {
+ # We save icmp type and code in both sport and dport. This
+ # allows us to sort icmp packets using the normal port-sorting
+ # code.
+ $dport = $sport = "$1.$2";
+ }
+ else
+ {
+ $sport = '';
+ $dport = '';
+ }
}
else
{
- if ($src =~ s/,([\-\w]+)$//)
- {
- $sport = &portSimplify ($1, $proto);
- }
- else
- {
- $sport = '';
- }
- if ($dest =~ s/,([\-\w]+)$//)
- {
- $dport = &portSimplify ($1, $proto);
- }
- else
- {
- $dport = '';
- }
+ if ($showFlags)
+ {
+ if (($proto eq 'tcp') && ($more =~ s/^\-([A-Z]+)\s*//))
+ {
+ push (@flags, $1);
+ }
+ if ($more =~ s/^K\-S\s*//)
+ {
+ push (@flags, 'state');
+ }
+ }
+ if ($src =~ s/,([\-\w]+)$//)
+ {
+ $sport = &portSimplify ($1, $proto);
+ }
+ else
+ {
+ $sport = '';
+ }
+ if ($dest =~ s/,([\-\w]+)$//)
+ {
+ $dport = &portSimplify ($1, $proto);
+ }
+ else
+ {
+ $dport = '';
+ }
}
# Make sure addresses are numeric at this point. We want to sort by
- # IP address later. This has got to do some weird things, but if you
- # want to use ipmon -n, be ready for weirdness.
+ # IP address later. If the hostname doesn't resolve, punt. If you
+ # must use ipmon -n, be ready for weirdness. Use only the first
+ # address returned.
my $x;
- $x = &hostNumber ($src);
+ $x = (&hostAddrs ($src))[0];
unless (defined ($x))
{
- print STDERR "$me:$.: cannot resolve hostname $src\n";
- next;
+ print STDERR "$me:$.: cannot resolve hostname $src\n";
+ next;
}
$src = $x;
- $x = &hostNumber ($dest);
+ $x = (&hostAddrs ($dest))[0];
unless (defined ($x))
{
- print STDERR "$me:$.: cannot resolve hostname $dest\n";
- next;
+ print STDERR "$me:$.: cannot resolve hostname $dest\n";
+ next;
}
$dest = $x;
# Skip hosts we're not interested in.
- next if ($selectHosts && !(exists ($selectHosts{$src}) || exists ($selectHosts{$dest})));
+ if ($selectAddrs)
+ {
+ my ($a, $m);
+ my $s = &integerAddr ($src);
+ my $d = &integerAddr ($dest);
+ my $cute = 0;
+ while (($a, $m) = each (%selectAddrs))
+ {
+ if ((($s & $m) == $a) || (($d & $m) == $a))
+ {
+ $cute = 1;
+ last;
+ }
+ }
+ next unless ($cute);
+ }
# Convert proto to proto number.
$proto = &protoNumber ($proto);
sub countPacket
{
- my ($host, $dir, $peer, $proto, $count, $packet) = @_;
+ my ($host, $dir, $peer, $proto, $count, $packet, @flags) = @_;
- # Make sure host is in the hosts hash.
- $hosts{$host} =
- +{
- 'd' => +{ },
- 's' => +{ },
- } unless (exists ($hosts{$host}));
+ # Make sure host is in the hosts hash.
+ $hosts{$host} =
+ +{
+ 'd' => +{ },
+ 's' => +{ },
+ } unless (exists ($hosts{$host}));
- # Get the source/destination traffic hash for the host in question.
- my $trafficHash = $hosts{$host}->{$dir};
+ # Get the source/destination traffic hash for the host in question.
+ my $trafficHash = $hosts{$host}->{$dir};
- # Make sure there's a hash for the peer.
- $trafficHash->{$peer} = +{ } unless (exists ($trafficHash->{$peer}));
+ # Make sure there's a hash for the peer.
+ $trafficHash->{$peer} = +{ } unless (exists ($trafficHash->{$peer}));
- # Make sure the peer hash has a hash for the protocol number.
- my $peerHash = $trafficHash->{$peer};
- $peerHash->{$proto} = +{ } unless (exists ($peerHash->{$proto}));
+ # Make sure the peer hash has a hash for the protocol number.
+ my $peerHash = $trafficHash->{$peer};
+ $peerHash->{$proto} = +{ } unless (exists ($peerHash->{$proto}));
- # Make sure there's a counter for this packet type in the proto hash.
- my $protoHash = $peerHash->{$proto};
- $protoHash->{$packet} = 0 unless (exists ($protoHash->{$packet}));
+ # Make sure there's a counter for this packet type in the proto hash.
+ my $protoHash = $peerHash->{$proto};
+ $protoHash->{$packet} = +{ '' => 0 } unless (exists ($protoHash->{$packet}));
- # Increment the counter.
- $protoHash->{$packet} += $count;
+ # Increment the counter and mark flags.
+ my $packetHash = $protoHash->{$packet};
+ $packetHash->{''} += $count;
+ map { $packetHash->{$_} = undef; } (@flags);
}
# Count the packet as outgoing traffic from the source address.
- &countPacket ($src, 's', $dest, $proto, $count, "$sport:$dport:$if:$act") if ($sTable);
+ &countPacket ($src, 's', $dest, $proto, $count, "$sport:$dport:$if:$act", @flags) if ($sTable);
# Count the packet as incoming traffic to the destination address.
- &countPacket ($dest, 'd', $src, $proto, $count, "$dport:$sport:$if:$act") if ($dTable);
+ &countPacket ($dest, 'd', $src, $proto, $count, "$dport:$sport:$if:$act", @flags) if ($dTable);
}
my $dir;
@@ -579,67 +659,76 @@ foreach $dir (@dirs)
sub ipSort
{
- my @a = split (/\./, $a);
- my @b = split (/\./, $b);
- $a[0] <=> $b[0] || $a[1] <=> $b[1] || $a[2] <=> $b[2] || $a[3] <=> $b[3];
+ &integerAddr ($a) <=> &integerAddr ($b);
}
sub packetSort
{
- my ($asport, $adport, $aif, $aact) = split (/:/, $a);
- my ($bsport, $bdport, $bif, $bact) = split (/:/, $b);
- $bact cmp $aact || $aif cmp $bif || $asport <=> $bsport || $adport <=> $bdport;
+ my ($asport, $adport, $aif, $aact) = split (/:/, $a);
+ my ($bsport, $bdport, $bif, $bact) = split (/:/, $b);
+ $bact cmp $aact || $aif cmp $bif || $asport <=> $bsport || $adport <=> $bdport;
}
my $host;
foreach $host (sort ipSort (keys %hosts))
{
- my $traffic = $hosts{$host}->{$dir};
-
- # Skip hosts with no traffic.
- next unless (scalar (keys (%{$traffic})));
-
- if ($numeric)
- {
- print "$host\n";
- }
- else
- {
- print &hostName ($host), " \[$host\]\n";
- }
-
- my $peer;
- foreach $peer (sort ipSort (keys %{$traffic}))
- {
- my $peerHash = $traffic->{$peer};
- my $peerName = &hostName ($peer);
- my $proto;
- foreach $proto (sort (keys (%{$peerHash})))
- {
- my $protoHash = $peerHash->{$proto};
- my $protoName = &protoName ($proto);
-
- my $packet;
- foreach $packet (sort packetSort (keys %{$protoHash}))
- {
- my ($sport, $dport, $if, $act) = split (/:/, $packet);
- my $count = $protoHash->{$packet};
- $act = '?' unless (defined ($act = $acts{$act}));
- if (($protoName eq 'tcp') || ($protoName eq 'udp'))
- {
- printf (" %-6s %7s %4d %4s %16s %2s %s.%s\n", $if, $act, $count, $protoName, &portName ($sport, $protoName), $arrow, $peerName, &portName ($dport, $protoName));
- }
- elsif ($protoName eq 'icmp')
- {
- printf (" %-6s %7s %4d %4s %16s %2s %s\n", $if, $act, $count, $protoName, &icmpType ($sport), $arrow, $peerName);
- }
- else
- {
- printf (" %-6s %7s %4d %4s %16s %2s %s\n", $if, $act, $count, $protoName, '', $arrow, $peerName);
- }
- }
- }
- }
+ my $traffic = $hosts{$host}->{$dir};
+
+ # Skip hosts with no traffic.
+ next unless (scalar (keys (%{$traffic})));
+
+ if ($numeric)
+ {
+ print &dottedAddr ($host), "\n";
+ }
+ else
+ {
+ print &hostName ($host), " \[", &dottedAddr ($host), "\]\n";
+ }
+
+ my $peer;
+ foreach $peer (sort ipSort (keys %{$traffic}))
+ {
+ my $peerHash = $traffic->{$peer};
+ my $peerName = ($numeric ? &dottedAddr ($peer) : &hostName ($peer));
+ my $proto;
+ foreach $proto (sort (keys (%{$peerHash})))
+ {
+ my $protoHash = $peerHash->{$proto};
+ my $protoName = &protoName ($proto);
+
+ my $packet;
+ foreach $packet (sort packetSort (keys %{$protoHash}))
+ {
+ my ($sport, $dport, $if, $act) = split (/:/, $packet);
+ my $packetHash = $protoHash->{$packet};
+ my $count = $packetHash->{''};
+ $act = '?' unless (defined ($act = $acts{$act}));
+ if (($protoName eq 'tcp') || ($protoName eq 'udp'))
+ {
+ printf (" %-6s %7s %4d %4s %16s %2s %s.%s", $if, $act, $count, $protoName, &portName ($sport, $protoName), $arrow, $peerName, &portName ($dport, $protoName));
+ }
+ elsif ($protoName eq 'icmp')
+ {
+ printf (" %-6s %7s %4d %4s %16s %2s %s", $if, $act, $count, $protoName, &icmpType ($sport), $arrow, $peerName);
+ }
+ else
+ {
+ printf (" %-6s %7s %4d %4s %16s %2s %s", $if, $act, $count, $protoName, '', $arrow, $peerName);
+ }
+ if ($showFlags)
+ {
+ my @flags = sort (keys (%{$packetHash}));
+ if (scalar (@flags))
+ {
+ shift (@flags);
+ print ' (', join (',', @flags), ')' if (scalar (@flags));
+ }
+ }
+ print "\n";
+ }
+ }
+ }
}
print "\n";
@@ -658,8 +747,8 @@ sub portName
my $pname = "$port/$proto";
unless (exists ($pn{$pname}))
{
- my $name = getservbyport ($port, $proto);
- $pn{$pname} = (defined ($name) ? $name : ($port <= 1023 ? $port : '<high>'));
+ my $name = getservbyport ($port, $proto);
+ $pn{$pname} = (defined ($name) ? $name : ($port <= 1023 ? $port : '<high>'));
}
return $pn{$pname};
}
@@ -672,16 +761,16 @@ sub portNumber
my $pname = "$port/$proto";
unless (exists ($pn{$pname}))
{
- my $number = getservbyname ($port, $proto);
- unless (defined ($number))
- {
- # I don't think we need to recover from this. How did the port
- # name get into the log file if we can't find it? Log file from
- # a different machine? Fix /etc/services on this one if that's
- # your problem.
- die ("Unrecognized port name \"$port\" at $.");
- }
- $pn{$pname} = $number;
+ my $number = getservbyname ($port, $proto);
+ unless (defined ($number))
+ {
+ # I don't think we need to recover from this. How did the port
+ # name get into the log file if we can't find it? Log file from
+ # a different machine? Fix /etc/services on this one if that's
+ # your problem.
+ die ("Unrecognized port name \"$port\" at $.");
+ }
+ $pn{$pname} = $number;
}
return $pn{$pname};
}
@@ -695,7 +784,7 @@ sub portSimplify
# Make sure port is numeric.
$port = &portNumber ($port, $proto)
- unless ($port =~ /^\d+$/);
+ unless ($port =~ /^\d+$/);
# Look up port name.
my $portName = &portName ($port, $proto);
@@ -708,61 +797,130 @@ sub portSimplify
return $port;
}
-# Translates a dotted quad into a hostname. Don't pass names to this
-# function.
+# Translates a numeric address into a hostname. Pass only packed numeric
+# addresses to this routine.
sub hostName
{
my $ip = shift;
- return $ip if ($numeric);
- unless (exists ($ip{$ip}))
- {
- my $addr = inet_aton ($ip);
- my $name = gethostbyaddr ($addr, AF_INET);
- if (defined ($name))
- {
- $ip{$ip} = $name;
-
- # While we're at it, cache the forward lookup.
- $ip{$name} = $ip;
- }
- else
- {
- # Just map the IP address to itself. There's no reverse.
- $ip{$ip} = $ip;
- }
- }
- return $ip{$ip};
+ return $ipName{$ip} if (exists ($ipName{$ip}));
+
+ # Do an inverse lookup on the address.
+ my $name = gethostbyaddr ($ip, AF_INET);
+ unless (defined ($name))
+ {
+ # Inverse lookup failed, so map the IP address to its dotted
+ # representation and cache that.
+ $ipName{$ip} = &dottedAddr ($ip);
+ return $ipName{$ip};
+ }
+
+ # For paranoid hostname lookups.
+ if ($paranoid)
+ {
+ # If this address already matches, we're happy.
+ unless (exists ($ipName{$ip}) && (lc ($ipName{$ip}) eq lc ($name)))
+ {
+ # Do a forward lookup on the resulting name.
+ my @addr = &hostAddrs ($name);
+ my $match = 0;
+
+ # Cache the forward lookup results for future inverse lookups,
+ # but don't stomp on inverses we've already cached, even if they
+ # are questionable. We want to generate consistent output, and
+ # the cache is growing incrementally.
+ foreach (@addr)
+ {
+ $ipName{$_} = $name unless (exists ($ipName{$_}));
+ $match = 1 if ($_ eq $ip);
+ }
+
+ # Was this one of the addresses? If not, tack on a ?.
+ $name .= '?' unless ($match);
+ }
+ }
+ else
+ {
+ # Just believe it and cache it.
+ $ipName{$ip} = $name;
+ }
+
+ return $name;
}
-# Translates a hostname or dotted quad into a dotted quad.
-sub hostNumber
+# Translates a hostname or dotted address into a list of packed numeric
+# addresses.
+sub hostAddrs
{
my $name = shift;
- if ($name =~ /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/)
- {
- # Return original value for dotted quads.
- my $or = int ($1) | int ($2) | int ($3) | int ($4);
- return $name if ($or == ($or & 0xff));
- }
- unless (exists ($ip{$name}))
- {
- my $addr = inet_aton ($name);
- unless (defined ($addr))
- {
- # Again, I don't think we need to recover from this. If we can't
- # resolve a hostname that ended up in the log file, punt. We
- # want to be able to sort hosts by IP address later, and letting
- # hostnames through will snarl up that code. Users of ipmon -n
- # will have to grin and bear it for now.
- return undef;
- }
- my $ip = inet_ntoa ($addr);
- $ip{$name} = $ip;
-
- # While we're at it, cache the reverse lookup.
- $ip{$ip} = $name;
- }
- return $ip{$name};
+ my $ip;
+
+ # Check if it's a dotted representation.
+ return ($ip) if (defined ($ip = &isDottedAddr ($name)));
+
+ # Return result from cache.
+ $name = lc ($name);
+ return @{$ipAddr{$name}} if (exists ($ipAddr{$name}));
+
+ # Look up the addresses.
+ my @addr = gethostbyname ($name);
+ splice (@addr, 0, 4);
+
+ unless (scalar (@addr))
+ {
+ # Again, I don't think we need to recover from this gracefully.
+ # If we can't resolve a hostname that ended up in the log file,
+ # punt. We want to be able to sort hosts by IP address later,
+ # and letting hostnames through will snarl up that code. Users
+ # of ipmon -n will have to grin and bear it for now. The
+ # functions that get undef back should treat it as an error or
+ # as some default address, e.g. 0 just to make things work.
+ return ();
+ }
+
+ $ipAddr{$name} = [ @addr ];
+ return @{$ipAddr{$name}};
+}
+
+# If the argument is a valid dotted address, returns the corresponding
+# packed numeric address, otherwise returns undef.
+sub isDottedAddr
+{
+ my $addr = shift;
+ if ($addr =~ /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/)
+ {
+ my @a = (int ($1), int ($2), int ($3), int ($4));
+ foreach (@a)
+ {
+ return undef if ($_ >= 256);
+ }
+ return pack ('C*', @a);
+ }
+ return undef;
+}
+
+# Unpacks a packed numeric address and returns an integer representation.
+sub integerAddr
+{
+ my $addr = shift;
+ return unpack ('N', $addr);
+
+ # The following is for generalized IPv4/IPv6 stuff. For now, it's a
+ # lot faster to assume IPv4.
+ my @a = unpack ('C*', $addr);
+ my $a = 0;
+ while (scalar (@a))
+ {
+ $a = ($a << 8) | shift (@a);
+ }
+ return $a;
+}
+
+# Unpacks a packed numeric address into a dotted representation.
+sub dottedAddr
+{
+ my $addr = shift;
+ my @a = unpack ('C*', $addr);
+ return join ('.', @a);
}
# Translates a protocol number into a protocol name, or a number if no name
@@ -773,15 +931,15 @@ sub protoName
return $code if ($code !~ /^\d+$/);
unless (exists ($pr{$code}))
{
- my $name = scalar (getprotobynumber ($code));
- if (defined ($name))
- {
- $pr{$code} = $name;
- }
- else
- {
- $pr{$code} = $code;
- }
+ my $name = scalar (getprotobynumber ($code));
+ if (defined ($name))
+ {
+ $pr{$code} = $name;
+ }
+ else
+ {
+ $pr{$code} = $code;
+ }
}
return $pr{$code};
}
@@ -793,15 +951,15 @@ sub protoNumber
return $name if ($name =~ /^\d+$/);
unless (exists ($pr{$name}))
{
- my $code = scalar (getprotobyname ($name));
- if (defined ($code))
- {
- $pr{$name} = $code;
- }
- else
- {
- $pr{$name} = $name;
- }
+ my $code = scalar (getprotobyname ($name));
+ if (defined ($code))
+ {
+ $pr{$name} = $code;
+ }
+ else
+ {
+ $pr{$name} = $name;
+ }
}
return $pr{$name};
}
@@ -821,12 +979,12 @@ sub icmpType
my $codeName;
if (exists ($info->{codes}->{$code}))
{
- $codeName = $info->{codes}->{$code};
- $codeName = (defined ($codeName) ? "/$codeName" : '');
+ $codeName = $info->{codes}->{$code};
+ $codeName = (defined ($codeName) ? "/$codeName" : '');
}
else
{
- $codeName = "/$code";
+ $codeName = "/$code";
}
return "$typeName$codeName";
}
@@ -847,11 +1005,11 @@ sub usage
if (scalar (@msg))
{
- print STDERR "$me: ", join ("\n", @msg), "\n\n";
+ print STDERR "$me: ", join ("\n", @msg), "\n\n";
}
- print STDERR <<EOT;
-usage: $me [-n] [-S] [-D] [-s servicemap] [-A act1,...] host...
+ print <<EOT;
+usage: $me [-nSDF] [-s servicemap] [-A act1,...] [address...]
Parses logging from ipmon and presents it in a comprehensible format. This
program generates two reports: one organized by source address and another
@@ -862,24 +1020,26 @@ destination address and port are counted as a single entry. Any port number
greater than 1023 that does not match an entry in the services table is treated
as a "high" port; all high ports are coalesced into the same entry. The fields
for the source address report are:
- iface action packet-count proto src-port dest-ip dest-port
+ iface action packet-count proto src-port dest-host.dest-port \[\(flags\)\]
The fields for the destination address report are:
- iface action packet-count proto dest-port src-ip src-port
+ iface action packet-count proto dest-port src-host.src-port \[\(flags\)\]
Options are:
-n Disable hostname lookups, and report only IP addresses.
+-p Perform paranoid hostname lookups.
-S Generate a source address report.
-D Generate a destination address report.
+-F Show all flag combinations associated with packets.
-s map Supply an alternate services map to be preloaded. The map should
- be in the same format as /etc/services. Any service name not found
+ be in the same format as /etc/services. Any service name not found
in the map will be looked for in the system services file.
--A act1,... Limit the report to the specified actions. The possible actions ar
-e
- pass, block, log, short, and nomatch.
+-A act1,... Limit the report to the specified actions. The possible actions
+ are pass, block, log, short, and nomatch.
-If any hostnames are supplied on the command line, the report is limited to
-these hosts. If a host has multiple addresses, only the first address will be
-considered.
+If any addresses are supplied on the command line, the report is limited to
+these hosts. Addresses may be given as dotted IP addresses or hostnames, and
+may be qualified with netmasks in CIDR \(/24\) or dotted \(/255.255.255.0\) format.
+If a hostname resolves to multiple addresses, all addresses are used.
If neither -S nor -D is given, both reports are generated.
@@ -899,5 +1059,3 @@ EOT
exit ($ec);
}
-
-
diff --git a/contrib/ipfilter/rules/BASIC.NAT b/contrib/ipfilter/rules/BASIC.NAT
index df041d1..213e338 100644
--- a/contrib/ipfilter/rules/BASIC.NAT
+++ b/contrib/ipfilter/rules/BASIC.NAT
@@ -8,6 +8,12 @@
#
# If we have only 1 valid IP address from our ISP, then we do this:
#
+# To make ftp work, using the internal ftp proxy, use:
+#
+map ppp0 w.x.y.z/24 -> a.b.c.d/32 proxy port ftp ftp/tcp
+#
+# For normal TCP/UDP and other IP protocols
+#
map ppp0 w.x.y.z/24 -> a.b.c.d/32 portmap tcp/udp 40000:60000
map ppp0 w.x.y.z/24 -> a.b.c.d/32
#
@@ -38,8 +44,3 @@ map ppp0 w.x.y.z/24 -> a.b.c.d/32
#map ppp0 w.x.y.q/32 -> a.b.c.J/32
#map ppp0 w.x.y.p/32 -> a.b.c.K/32 portmap tcp/udp 40000:60000
#map ppp0 w.x.y.p/32 -> a.b.c.K/32
-#
-# To make ftp work, using the internal ftp proxy, use:
-#
-map ppp0 w.x.y.z/24 -> a.b.c.d/32 proxy port ftp ftp/tcp
-#
OpenPOWER on IntegriCloud